ry's Tech blog

Cloud Native技術などについて書いていきます。

Kubenews #55

2021-06-17

Comparing Ceph, LINSTOR, Mayastor, and Vitastor storage performance in Kubernetes (click here to source)

各Storageプロダクトに対して、ベンチマークを行っているもの。

DRBD:9.1.4(linstor-server v1.17.0);

Ceph:16.2.7(rook v1.8.2);

Mayastor:1.0.0;

Vitastor:0.6.12(カーネル5.13.0-27-ジェネリック);

ZFS: 0.8.3;

LVM:2.03.07

ArgoCD Best Practices You Should Know (click here to source)

1. Disallow providing an empty retryStrategy

Project: Argo Workflows

retryStrategyを用いて、ワークフローで失敗またはエラーが発生したステップを再試行する方法を指定できます。

空のretryStrategy(つまり、 retryStrategy:{})を指定すると、コンテナーは完了するまで再試行し、最終的にOOMの問題が発生します。

2. Ensure that Workflow pods are not configured to use the default service account

Project: Argo Workflows

ワークフロー内のすべてのポッドは、workflow.spec.serviceAccountNameで指定したサービスアカウントで実行されます。

省略した場合、Argoはワークフローの名前空間にあるデフォルトのサービスアカウントを使用します。

単一のコンテナにアクセスできる攻撃者は、AutomountServiceAccountTokenを使用してKubernetesを悪用でき、万が一、AutomountServiceAccountTokenのオプションが無効になった場合、Argoが使用するデフォルトのサービスアカウントには権限がなく、ワークフローは失敗します。

適切な役割を持つ専用のユーザー管理サービスアカウントを作成することをお勧めします。

Ensure label part-of: argocd exists for ConfigMaps

Project: Argo CD

app.kubernetes.io/part-of:argocdというラベルを使用してConfigMapリソースに注釈を付けることが重要です。

何かしら設定を反映する場合に、app.kubernetes.io/part-of:argocdというラベルが抜けると、 ArgoCDはそれらを使用できません。

4. Disable with DAG to set FailFast=false

Project: Argo Workflows

ワークフローで一連のステップを指定する代わりに、各タスクの依存関係を指定することにより、ワークフローをDAG(有向非巡回グラフ)として定義できます。

DAGロジックには、フェイルファスト機能が組み込まれています。

これは、DAGノードの1つに障害が発生したことを検出するとすぐに、新しいステップのスケジューリングを停止すし、すべてのDAGノードが完了するまで待機してから、DAG自体に障害が発生します。

FailFastフラグのデフォルトはtrueになっており、falseに設定すると、DAG内のブランチの失敗した結果に関係なく、DAGはDAGのすべてのブランチを(成功または失敗のいずれかで)完了するまで実行できます。

5. Ensure Rollout pause step has a configured duration

Project: Argo Rollouts

Argo Rolloutsではロールアウトごとにステップのリストを定義でき、各ステップには、 setWeight(新しいRevisionに指定した割合のトラフィックを流すかを指定する)とpause(待機時間の指定)の2つのフィールドのいずれかを含めることができます 。

spec:
  replicas: 5
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {}
      - setWeight: 60
      - pause: {duration: 10}

pauseステップに入ると、PauseCondition構造体が.status.PauseConditionsフィールドに追加されます。

pause構造体内のdurationフィールドが設定されている場合、durationフィールドの値を待機するまで、ロールアウトは次のステップに進みません。

ただし、durationフィールドが省略されている場合、追加された一時停止条件が削除されるまで、ロールアウトは無期限に待機する可能性があります。

6. Specify Rollout’s revisionHistoryLimit

Project: Argo Rollouts

.spec.revisionHistoryLimitは、ロールバックを許可するために保持する必要がある古いReplicaSetの数を示すオプションのフィールドです。

デフォルトでは、10個の古いReplicaSetが保持されます。

このフィールドをゼロに設定すると、新しいdeploymentは、そのリビジョン履歴がクリーンアップされるため、元に戻すことはできません。

7. Set scaleDownDelaySeconds to 30s to ensure IP table propagation across the nodes in a cluster

Project: Argo Rollouts

ロールアウトによってサービスのセレクターが変更されると(kubectl argo rollouts promote など)、すべてのノードがIPテーブルを更新して、古いポッドではなく新しいポッドにトラフィックを送信するようになりますが、その際に伝播遅延が発生します。

この遅延中にノードがまだ更新されていない場合、トラフィックは古いポッドに転送されます。

古いポッドを強制終了したノードにパケットが送信されないようにするために、ロールアウトはscaleDownDelaySecondsフィールドを使用してノードに十分な時間を与えることができます。

クラスタ内のノード間でIPテーブルが確実に伝播するように、scaleDownDelaySecondsを最低30秒に設定することをお勧めします。

30秒の理由としては、termination grace periodのデフォルトが30秒だからです。

8. Ensure retry on both Error and TransientError

Project: Argo Workflows

ワークフローのステップを再試行するためのコントロールを提供するrestartStrategyのフィールドの1つであるretryPolicyは、再試行されるNodePhaseステータスのポリシーを定義します。(DAGノードのノード(workflowの実行単位)のことかな?)

これに対する値としては、Always, OnError, OnTransientErrorの3つがある。

retryPolicy=Alwaysは過剰である。

retryPolicy=OnErrorは、ノードの消失やポッドの削除など、いくつかのシステムレベルのエラーを処理します。

ただし、ポッドのgraceful termination中に、kubeletは終了したポッドにFailedステータスとShutdown reasonを割り当ててしまい、「エラー」ではなく「失敗」のノードステータスになるため、プリエンプションは再試行されません。

preemption failure messageとして分類されるErrorを対処するには、retryPolicy=OnTransientErrorとする必要がある。

おすすめは、retryPolicy: "Always" にし、'lastRetry.status == "Error" or (lastRetry.status == "Failed" and asInt(lastRetry.exitCode) not in [0])' を設定することです。

9. Ensure progressDeadlineAbort set to true, especially if progressDeadlineSeconds has been set

Project: Argo Rollouts

ユーザーはprogressDeadlineSecondsを設定できます。

これは、更新中にロールアウトが失敗したと見なされるまでの最大時間を秒単位で示します。

ロールアウトポッドがエラー状態(イメージのプルバックなど)でスタックした場合、Progress Deadlinを超えた後、ロールアウトはdegradeになるが、エラーとなっているレプリカセット/ポッドは縮小されません。

ロールアウトを中止するには、 progressDeadlineSecondsとprogressDeadlineAbort:trueの両方を設定する必要があります。

10. Ensure custom resources match the namespace of the ArgoCD instance

Project: Argo CD

すべてのApplicationマニフェストとAppProjectマニフェストが同じmetadata.namespaceと一致する必要があります。

すべてのArgoCDリソースがArgoCDインスタンス名前空間と一致することを確認するだけでなく、argocd名前空間を使用することをお勧めします。

Run Kubernetes Tests with SoapUI and Testkube (click here to source)

TestKubeについて。

Testkubeは、Kubernetesネイティブのテストフレームワークで、Kubernetesクラスターで直接テストを実行し、結果を一元化されたスペースに保存できます。

SoapUIを使用したKubernetesテスト

SoapUIは「方法」を簡素化し、Testkubeは「where」に対する答えを提供します。

これら2つのツールを使用して作成されたテストは、再現性があり、読みやすく、構造化されています。

SoapUIは、複数のテストタイプを持っています。

  • Functional Tests
  • Load Tests
  • Security Tests
  • Mocking

Kubenews #54

2021-05-27

Progressive Delivery with Argo Rollouts : Blue-Green Deployment (click here to source)

Progressive Deliveryについてと、Argo Rolloutsを用いたProgressive Deliveryを取り入れていくための、挙動を知るためのデモが書かれている。

従来のCI/CDとプログレッシブデリバリー

各プロセスを以下のように説明している。

継続的インテグレーション(CI)は、ソフトウェア開発の変更を継続的に統合するのに役立つ自動化プロセスです。 ソースコードの構築、テスト、検証を自動化し、目標としては、最終的に展開するアーティファクトを作成することです。

継続的デリバリー(CD)は、ソフトウェアの変更をユーザーに展開するのに役立ちます。

プログレッシブデリバリーは、継続的デリバリーの一歩先を行くことであり、障害のリスクを軽減することで、制御された方法でソフトウェアアップデートを展開できます。

デフォルトの「RollingUpdate」Kubernetesデプロイ戦略の課題

Kubernetesは、現在、以下の制限があるデフォルトのRollingUpdate展開戦略を機能として備えている。

  • ロールアウトの速度の制御が少ない
  • 新しいバージョンへのトラフィックフローを制御できない
  • Readiness probesは、より深いストレス、または1回限りのチェックには適していない
  • アップデートしたものの状態を検証するために外部メトリクスを照会するといった機能がない
  • 進行を停止することはできますが、更新を自動的に中止してロールバックすることはできない

この後、Argo Projectの説明及び、上記のものと比較しながらArgo Rolloutsでできる機能を紹介している。

Lab/Hands-on of Argo Rollouts with Blue-Green Deployments

ここから簡単なDemoに入っていく。

Appendix

今回は手動でBlue-Greenをしたが、以下のようにPrometheusなどのメトリックを基に、切り替えたりできる。

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  args:
  - name: service-name
  metrics:
  - name: success-rate
    interval: 5m
    # NOTE: prometheus queries return results in the form of a vector.
    # So it is common to access the index 0 of the returned array to obtain the value
    successCondition: result[0] >= 0.95
    failureLimit: 3
    provider:
      prometheus:
        address: http://prometheus.example.com:9090
        query: |
          sum(irate(
            istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}",response_code!~"5.*"}[5m]
          )) / 
          sum(irate(
            istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}"}[5m]
          ))

Prometheus - Argo Rollouts - Kubernetes Progressive Delivery Controller

これを用いて、Canary ReleaseやBlue-Greenができる。

  • Canary
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: guestbook
spec:
...
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {duration: 5m}
      - analysis:
          templates:
          - templateName: success-rate
          args:
          - name: service-name
            value: guestbook-svc.default.svc.cluster.local

この例では、カナリアの重みを20%に設定し、5分間一時停止してから、分析を実行します。分析が成功した場合は、ロールアウトを続行します。

他にも、複数のAnalysisTemplateを指定もできる。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: guestbook
spec:
...
  strategy:
    canary:
      analysis:
        templates:
        - templateName: success-rate
        - templateName: error-rate
        args:
        - name: service-name
          value: guestbook-svc.default.svc.cluster.local
  • Blue-Green

BlueGreen戦略を使用したロールアウトでは、事前プロモーションを使用してトラフィックを新しいバージョンに切り替える前に検証をして、成功または失敗により、ロールアウトがトラフィックを切り替えるか、ロールアウトを完全に中止するかが決まる。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: guestbook
spec:
...
  strategy:
    blueGreen:
      activeService: active-svc
      previewService: preview-svc
      prePromotionAnalysis:
        templates:
        - templateName: smoke-tests
        args:
        - name: service-name
          value: preview-svc.default.svc.cluster.local

プロモーション後の分析を使用すると、トラフィックが新しいバージョンに切り替わった後に分析実行を開始できる。

プロモーション後の分析が失敗またはエラーになった場合、ロールアウトは中止状態になり、トラフィックを以前の安定したレプリカセットに戻す。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: guestbook
spec:
...
  strategy:
    blueGreen:
      activeService: active-svc
      previewService: preview-svc
      scaleDownDelaySeconds: 600 # 10 minutes
      postPromotionAnalysis:
        templates:
        - templateName: smoke-tests
        args:
        - name: service-name
          value: preview-svc.default.svc.cluster.local

argoproj.github.io

Storage Capacity Tracking reaches GA in Kubernetes 1.24 (click here to source)

私たちが解決した問題

ストレージ容量追跡により、CSIドライバーは残りの容量に関する情報を参照できるようになった。

kube-schedulerは、そのPodにまだプロビジョニングが必要なボリュームがある場合、その情報を使用してPodに適したノードを選択する。

この情報がなければ、kube-schedulerは盲目的に選択する必要がある。

そのため、CSIドライバが管理するストレージシステムに十分な容量が残っておらず、ボリュームをプロビジョニングできないノードを選択してしまうということが発生する。

結果としてPodが適切なノードにスケジュールされずPending状態になるという可能性がある。

(参考)

以下の機能には2つのAPI拡張機能によって実現。

  • CSIStorageCapacityオブジェクト:
    • ドライバがインストールされている名前空間内のCSIドライバによって生成されます。
    • 各オブジェクトには、1つのストレージクラスの容量情報が含まれており、どのノードがそのストレージにアクセスできるかを定義します。
  • CSIDriverSpec.StorageCapacityフィールド:
    • trueに設定すると、KubernetesスケジューラはCSIドライバを使用するボリュームのストレージ容量を考慮します。

私たちが解決していない問題

Podが2つのボリュームを使用すると定義されていて、そのうちの1つだけをプロビジョニングできる状態であった場合、将来のすべてのスケジューリング決定はプロビジョニングされたボリュームによって制限される。

(2VolumeのうちどちらかがPodにプロビジョニングできてしまった場合、その時点でNodeが決まってしまい、万が一そのNodeでもう片方のVolumeが使えないとなったら、Podがスタックするという理解)

ただ、これを解決するためのアイデアは、KEPドラフトで提案されたらしい。

また、ボリュームのあるポッド用のクラスターオートスケーラーのサポートも解決されていない。

(Local Volume用のCSIなどがメインのターゲット???)

Kubenews #53

2021-04-15

GitOps Series (click here to source)

GitOpsを実施するためのツールとその構成や使い方などが簡単に紹介されている。

Introducing PacketStreamer: distributed packet capture for cloud-native platforms (click here to source)

PacketStreamerとは、複数のリモートソースからのネットワークトラフィックを同時にキャプチャし、データを単一のpcapログファイルに集約するオープンソースツール。

ネットワークトラフィックを監視すると、侵害が成功する前の攻撃者の行動を明らかにすることができる。

記事でのデモでは、以下のようなことが紹介されている。

  • Honeypot Server

3つのハニーポットサーバーを立てて、そこにPacketStreamerを建てる。

sudo packetstreamer sensor \
     --config contrib/config/sensor-remote.yaml

sonsor-remote.yamlには、確認したアクセスの記録を送るreceiverなどの情報が書かれる。

  • Receiver serverを建てる。

受信サーバーはファイアウォールの背後にあり、ハニーポットセンサーからのトラフィックをポート8081でリッスンしている。

packetstreamer receiver --config contrib/config/receiver.yaml

受信側サーバーは、集約されたキャプチャトラフィックを/ tmp/dump_fileなどのログファイルに書き込みます。

tsharkを使用するなど、さまざまな方法でそのログファイルを監視および処理できます。

tail -c +1 -f /tmp/dump_file | tshark -r — -Y http
10388 66.320435 178.62.5.62 → 94.200.83.110 HTTP 312 HTTP/1.1 200 OK
10389 66.489650 94.200.83.110 → 178.62.5.62 HTTP 125 POST /wr54jj HTTP/1.1
11905 794.572402 86.171.162.177 → 46.101.77.119 HTTP 416 GET /wp-includes/js/wp-emoji-release.min.js?ver=5.8.4 HTTP/1.1
11907 794.573117 86.171.162.177 → 46.101.77.119 HTTP 441 GET /wp-includes/css/dist/block-library/style.min.css?ver=5.8.4 HTTP/1.1
11909 794.573576 86.171.162.177 → 46.101.77.119 HTTP 408 GET /wp-includes/js/wp-embed.min.js?ver=5.8.4 HTTP/1.1
12558 1204.781243 109.237.103.9 → 178.62.5.62 HTTP 295 GET /.env HTTP/1.1
12580 1205.040161 109.237.103.9 → 178.62.5.62 HTTP 307 GET /.aws/credentials HTTP/1.1
12593 1205.194548 109.237.103.9 → 178.62.5.62 HTTP 86 POST /.aws/credentials HTTP/1.1 (application/x-www-form-urlencoded)
13393 1352.414459 92.53.64.29 → 46.101.77.119 HTTP 599 POST /boaform/admin/formLogin HTTP/1.1 (application/x-www-form-urlencoded)Continuation
19020 3475.869367 91.98.167.220 → 178.62.5.62 HTTP 522 POST /tvm5f7 HTTP/1.1 Continuation
19027 3476.218166 91.98.167.220 → 178.62.5.62 HTTP 522 POST /ep6j56 HTTP/1.1
19042 3478.949728 91.98.167.220 → 178.62.5.62 HTTP 518 POST /y4p8vy HTTP/1.1
22661 4197.353628 2.50.89.16 → 178.62.5.62 HTTP 517 POST /q7e8vf HTTP/1.1 Continuation
22676 4198.930334 2.50.89.16 → 178.62.5.62 HTTP 520 POST /devret HTTP/1.1
24057 4763.594258 92.53.64.29 → 178.62.5.62 HTTP 593 POST /boaform/admin/formLogin HTTP/1.1 (application/x-www-form-urlencoded)Continuation

Red Hatの新しい最軽量コンテナーイメージ:UBI Microの紹介 (click here to source)

UBI Microという軽量コンテナイメージが出たらしい。

インフラエンジニアが学ぶと良さそうなgRPCサーバーについて (click here to source)

勉強したいので共有です!

配信中に得た情報

dagger (click here to source)

CI/CDツール

kueue (click here to source)

set of APIs and controller for job queueing.

mizu (click here to source)

API trafficをキャプチャするためのツール。

Kubenews #49

2021-03-11

Announcing automated multi-cluster failover for Kubernetes (click here to source)

Linkerdの新しい自動フェイルオーバー機能がリリースされたらしい。

この機能により、Linkerdは、障害のあるサービスもしくはアクセスできないサービスから、「他のクラスター上の」レプリカを含む、そのサービスの1つ以上のレプリカにすべてのトラフィックを自動的にリダイレクトすることができます。

リダイレクトされたトラフィックは、オープンなインターネットによって分離されたクラスターの境界を越えたとしても、Linkerdによるアプリケーションのセキュリティ、信頼性、および透過性の保証をすべて維持します。

linkerd-failover 専用レポジトリ

Helm経由でインストール

# Add the linkerd-edge Helm repo if you haven't already
helm repo add linkerd-edge https://helm.linkerd.io/edge

# And the linkerd-smi extension
helm repo add linkerd-smi https://linkerd.github.io/linkerd-smi
helm repo up

# Install linkerd-smi and linkerd-failover
helm install linkerd-smi -n linkerd-smi --create-namespace linkerd-smi/linkerd-smi
helm install linkerd-failover -n linkerd-failover --create-namespace --devel linkerd-edge/linkerd-failover

次に、 既存のTrafficSplitに failover.linkerd.io/controlled-by: linkerd-failover ラベルを適用して、サービスフェイルオーバーを構成します。

apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
name: sample-svc
annotations:
  failover.linkerd.io/primary-service: sample-svc
labels:
  failover.linkerd.io/controlled-by: linkerd-failover
spec:
service: sample-svc
backends:
  - service: sample-svc
    weight: 1
  - service: sample-svc-remote
    weight: 0

この例では、sample-svcヘルスチェックが完全に失敗した場合、サービスへのトラフィックはローカルクラスターからレプリカに自動的にフェイルオーバーします。

Reducing negative and biased language in documentation (click here to source)

Examples of language

要約すると、識別すべき言語の種類には次のものが含まれます。

  • Patronizing (人の上に立った態度を取る):作家の表現を理解していないことに対して、読者に愚かまたは無知に感じさせることができる言語。
  • Rude (失礼):不快な言葉や冒とく的な言い回しを明示的に使用する言葉。
  • Overly negative (過度に否定的):過度に否定的な意味合いを使用する言語は、読者に、タスクを達成するのが難しいと感じさせたり、テキストを読むのに飽きさせたりする可能性があります。
  • Biased (偏見):あるグループを別のグループよりも優遇する、または偏見を与える用語を不必要に使用する言語。
  • Out-dated (時代遅れ):大規模なコミュニティの人々から古いまたは不適切と見なされている用語を使用する言語。
  • Unhelpful (役に立たない):テキストに何も追加しない言語、または最悪の場合、テキストはこのリストの他のカテゴリの1つに分類されます。

An introduction to linting

テキストを「リント」するツールの例としては、次のようなものがあります。

Install

Homebrewで簡単にいれられる

brew install vale

Configure

テキストをチェックするには、Valeには2つの主要なコンポーネントが必要です。

  1. テキストをチェックするための「ルール」を定義するスタイルのコレクション 。事前に作成されたスタイルは多数ありますが、独自のスタイルを作成することもできます。
  2. 少なくともスタイルの場所と有効にするスタイルを定義する.vale.ini 構成ファイル。

以下のコマンドで実行が可能

vale {file_name}

スタイルとルール

スタイルというYAML形式のファイルで定義することで、さまざまな提案がなされます。 YAMLファイルは、正規表現RegEx)と、ルールに応じたいくつかの構成から成っています。

Previous experience as a policewoman, saleswoman, or waitress.

extends: substitution
message: "Consider using '%s' instead of '%s'."
ignorecase: true
level: error
swap:
  police(?:m[ae]n|wom[ae]n):   police officer(s)
  sales(?:m[ae]n|wom[ae]n):    salesperson or sales people
  waitress:                    waiter

Another example might be highlighting “guys” by using the “existence” extension point, which triggers when Vale finds a token in the text.

extends: existence
message: "Avoid using '%s'"
description: "Use of '%s' could indicate that you're discriminating in favor of a certain gender."
ignorecase: true
level: error
tokens:
  - 'guys?'

Cloud Native Observability Microsurvey(click here to source)

最近、CNCF Observability Technical Advisory Group(TAG)と提携して、2021年の終わりにクラウドネイティブコミュニティのマイクロサーベイを実施し、組織が可観測性ツールをどのように使用しているかを調べた結果が載っています。

Kubenews #48

2021-03-04

Manage and debug Kubernetes manifests with Monokle by Kubeshop (click here to source

モノクルについて

Monokleは、Kubernetesマニフェストを管理するためのオープンソースのデスクトップUIです。

Monokle

機能の概要

  • クラスター内のリソースを視覚化。
  • Monokleを使用してリソースの編集が可能。
  • KustomizeとHelmもサポート
  • クラスタ内のリソースをマニフェストファイルで定義されているリソースと比較して、すぐに変更を加えることが可能。

CivoKubernetesクラスターを用いたDemo

以降は、実際のドキュメントを参照ください。

How I got Kubernetes to run on a PS4 (click here to source

Gentoo Linuxカーネルを何度もコンパイルしてはErrorを対処するという試行錯誤の末、KubernetesとCalicoで正常に動作するカーネルを作れましたという記事。

All You Need to Know About Cloud-Native Storage (click here to source

CNCF Storage LandscapeというCloud Native Applicationに用いるStorageのWhitepaperの抜粋が書かれている。

Storageの必要性

ApplicationにはStorageが必要だが、あなたのアプリケーションにとって重要なものって何ですか?

Whitepaperの最初のセクションでは、Storageの基本的な属性について書かれています。

  • Storage system
    • Availability
    • Scalability
    • Performance
    • Consistency
    • Durability
    • Instantiation & Deployment

STORAGE LAYERS

Storageの構成要素について書かれています。

  • ストレージトポロジー

    • システムの様々な部分がどのように相互に関連し、接続されているか(ストレージデバイス、コンピュートノード、データなど)。
    • 集中型、分散型、シャード型、ハイパーコンバージド型があります。
  • データ保護

    • RAID
    • Erasure Encoding
    • Replica
  • データサービス

    • 追加機能として実装されることが多いサービス。
    • システムによって異なるが、レプリケーション、バージョン管理などの管理を目的としたものが一般的。
  • 暗号化

  • 物理層

    • データが保存される実際のハードウェア。
    • 磁気ディスクとフラッシュベース。

Data access interface

  • Block
  • FileSystem
  • Object store
  • Key-Value store

ORCHESTRATION AND MANAGEMENT INTERFACES

Kubernetesは、ストレージシステムとやり取りするための複数のインターフェイスをサポートすることができる。

Cracking Kubernetes Network Policy (click here to source)

後日読みたいので、掲載。

Kubenews #46

2021-02-04

10 real-world stories of how we’ve compromised CI/CD pipelines (click here to source)

NCC Groupというセキュリティの会社のサイバーセキュリティコンサルティングの人が、JenkinsGitlab CI/CDに対して実際にできてしまった攻撃を紹介してくれています。

Restricting cluster-admin Permissions (click here to source)

マルチユーザー/マルチテナントのKubernetesクラスターを管理している場合のRBACに関して書かれた記事になってます。

通常、クラスターの管理者には、cluster-admin というClusterRoleが割り当てられます。

これにより、管理者はクラスター内のすべてのリソースに対してすべての操作を実行するためのアクセスとアクセス許可を得ることができます。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-admin
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'

ここで、クラスター管理者によって実行されるアクションをブロックする必要がある場合はを考えてみます。

経緯としては、Giant Swarmで、クラスター管理者が使用するCLIの1つによって、意図したよりも多くのリソースを誤って削除するという問題が発生しましたことでした。

Giant Swarmでは、Kyvernoを利用することで、cluster-admin(および他のすべてのユーザー)が、今回の問題の原因となった特定の削除アクションの実行をブロックするクラスターポリシーを展開しました。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: block-bulk-certconfigs-delete
  annotations:
    policies.kyverno.io/title: Block bulk certconfig deletes
    policies.kyverno.io/subject: CertConfigs
    policies.kyverno.io/description: >-
      A bug in an old kubectl-gs version causes all certconfigs to
      be deleted on performing a login, this policy blocks that
      action while still allowing the single delete.
spec:
  validationFailureAction: enforce
  background: false
  rules:
  - name: block-bulk-certconfigs-delete
    match:
      any:
      - resources:
          kinds:
          - CertConfig
    preconditions:
      any:
      - key: ""
        operator: Equals
        value: ""
    validate:
      message: "Your current kubectl-gs version contains a critical bug, please update to the latest version using `kubectl gs selfupdate`"
      deny:
        conditions:
        - key: ""
          operator: In
          value:
          - DELETE

まず、以下で今回のPolicyの対象を指定します。(今回は、CertConfig というCRD)

    match:
      any:
      - resources:
          kinds:
          - CertConfig

preconditions では、リクエストに基づいて、フィルタリングをかける前提条件を設定します。 この例では、名前が指定されていないリクエスト(--all オプションなど)を対象とします。

    preconditions:
      any:
      - key: ""
        operator: Equals
        value: ""

最後にPolicyにおけるアクションを指定します。

今回は、validation を行います。

denyを用いて、指定リソースに対する DELETE を拒否しています。

    validate:
      message: "Your current kubectl-gs version contains a critical bug, please update to the latest version using `kubectl gs selfupdate`"
      deny:
        conditions:
        - key: ""
          operator: In
          value:
          - DELETE

Scaling Kubernetes to Over 4k Nodes and 200k Pods (click here to source)

ワークロードの大部分はApacheMesosで実行されていたPayPalが、Kubernetes環境に移行する際に行ったパフォーマンステストに関するナレッジの共有がされています。

内容としては、スケーリング時に直面したいくつかの課題と、それらをどのように解決したかについて説明されています。

環境としては、GCPを使っています。

ワークロード

ユースケースに合わせて、指定値の変更が可能なオープンソースのワークロードジェネレーターであるk-benchを使用。

github.com

規模

各ワーカーノードには4つのCPUコアがあり、最大40のポッドを保持するようにし、約4,100ノードまでスケーリングをさせました。

ベンチマークに使用されたアプリケーションは、100ミリコアの保証されたサービス品質(QoS)において実行されるステートレスサービスでした。

最初、1,000ノードに対し2,000ポッドから始め、次に16,000ポッド、次に32,000ポッドまで増やしました。 この後、ノードを4100までスケールさせ、ポッドを150,000にし、続いて200,000ポッドまで増やしました。

これ以上のポッド数に対応するには、各ノードのコア数を増やす必要がありました。

API Server

APIサーバーへのいくつかの接続が、ローカルクライアントレベルのスロットリング(exponential backoff)に加えて、504のゲートウェイタイムアウトを返したときに、API Serverがボトルネックであることが判明しました。

Controller Manager

Controller Manager が状態をAPI Serverと同期できる速度は制限されていたので、チューニングするために以下を設定した。

  • kube-api-qps — コントローラーマネージャーが特定の1秒間にAPIサーバーに対して実行できるクエリの数。
  • kube-api-burst — これは、kube-api-qpsのバースト時の値.
  • concurrent-deployment-syncs — デプロイメント、レプリカセットなどのオブジェクトの同期呼び出しにおける並列実行。

Scheduler

独立したコンポーネントとして独立してテストした場合、スケジューラーは1秒あたり最大1,000ポッドの高スループットレートをサポートできます。

ただし、稼働中クラスターにおけるスケジューラーでは、実際のスループット値は低下します。

etcdインスタンスが遅いと、スケジューラのバインディングレイテンシーが増加し、Pendingキューのサイズが数千ポッドに対するオーダーが発生したタイミングで増加しました。

なので、テスト中はそのオーダー数を100未満に保つようにしました。

他にも、リーダー選出のパラメータをいじって、ネットワークパーティションにおいて誤った短期間の再起動であったり、ネットワークの輻輳に対して回復力を持たせることを実施した。

etcd

Etcdをスケールさせると、多くのRaftのProposalが失敗し始めた。

GCPは100GのディスクサイズでPD-SSDディスクに対するスループットを毎秒約100MiBに抑制したことが確認できました。

現状、スループット制限を増やす方法を提供していません。

これに対し、ローカルSSDを使用することにしました。

ただ、永続的ではないため、障害が発生した場合にデータが失われる可能性がわずかに高くなりますが、スループットが非常に高くなります。

ただこれでは終わらず、SSDから期待されるパフォーマンスが得られませんでした。

これはext4ファイルシステムwrite barrier cache commitsに起因していました。

これに対し、etcdは write-ahead logging を使用し、raftログにコミットするたびにfsyncを呼び出すようにしました。

この場合、write barrierを無効にしても問題ありません。

この変更後、ローカルSSDの数値はPD-SSDに匹敵するように改善されました。

続いて、v1.20のetcdYAMLにLiveness Proveの下記のようなバグがあることがわかりました。

The etcd server would still restart occasionally and just a single restart can spoil the benchmark results, especially the P99 numbers.

これについては、the failure threshold count を増やすことで対処できます。

最後に、etcdのスケールアップ可能なリソース(CPU、メモリ、ディスク)を使い果たすと、etcdのパフォーマンスがrange queryによって影響を受けることがわかりました。

range queryが多く、Raftログへの書き込みが失敗すると、Etcdはうまく機能せず、クラスターのレイテンシーが遅くなります。

対応としては以下のようです。(よくわからなかったので原文を載せます)

After sharding the etcd server on the events resource, we saw an improvement in cluster stability when there is high contention of pods.

Kubenews #45

2021-01-28

Detect crashes in your Kubernetes cluster using kwatch and Slack (click here to source)

kwatchは、KubernetesK8sクラスターのすべての変更を監視して、実行中のアプリのクラッシュを検出し、お気に入りのチャネル(Slack、Discordなど)に通知を公開することを目的としたオープンソースのツール。

Example

  • Slack のIncoming WebhookのURLを取得。

  • 構成ファイル用のConfigmapのテンプレートの取得。

curl  -L https://raw.githubusercontent.com/abahmed/kwatch/v0.3.0/deploy/config.yaml -o config.yaml
  • 編集及び適用
apiVersion: v1
kind: Namespace
metadata:
  name: kwatch
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: kwatch
  namespace: kwatch
data:
  config.yaml: |
    alert:
      slack:
        webhook: WEBHOOK_URL
kubectl apply -f config.yaml
  • Slackに通知を投げるAgentの作成
kubectl apply -f https://raw.githubusercontent.com/abahmed/kwatch/v0.3.0/deploy/deploy.yaml

Tracing the path of network traffic in Kubernetes (click here to source)

この記事では、Kubernetesクラスターの内外でパケットがどのように流れるかを解説してくれています。