Open86

Kubernetes - 2024

toVersustoVersus

2024/1/5

  • Kubernetes 1.30 のリリースサイクルは 1/8 から開始 (google group)
    • KEP フリーズ: 2/9
    • コードフリーズ: 3/6
    • KubeCon EU: 3/19-
    • テスト / Docs フリーズ: 3/26
      • Docs フリーズはドキュメントも大事ということで今回から始まった
      • 期限を超える場合は例外申請が必要
    • リリース予定日: 4/17
toVersustoVersus

2024/1/8

  • In Place Pod Vertical Scaling で Pod のリソース要求と上限を patch で変更すると、ノードの割り当て可能なリソースを超えてもエラーにならない。patch でエラーを返すようにするか、他の Pod を Evict して割り当てられるようにするか、オプションで挙動を変えられるようにするか。再起動して別のノードで起動するって挙動もありえるし、考えることが多くて難しそう (k/k#122602)
toVersustoVersus

2024/1/10

  • 今までなぜかノードの Eviction Hard (過負荷状態のノードを救うために Pod を追い出す機能) の発動条件に nodefs の inode の空きが少なくなったらの条件はあったけど、imagefs の inode の空きが少なくなったらの条件はなかった。今までは nodefs と imagefs が同じディスクのファイルシステムだったので問題なかった。ただ、KEP-4191 でコンテナイメージ用のファイルシステムを別のディスクのファイルシステムに変更できるようになるから、imagefs の inode の空きもちゃんと見るようにする (k/k#121834)
toVersustoVersus

2024/1/11

  • Kubernetes 1.27 で Evented PLEG (Pod Lifecycle Event Generator) がベータに昇格した。コンテナランタイム側のサポートが必要なのでデフォルト無効だったけど、Kubelet が Pod を重複して起動しようとしたり致命的なバグがあるので、1.30 でアルファに降格されようとしている珍しいケース。1.27, 1.28, 1.29 にも cherry-pick 済み (k/k#122697)
    • 元々ベータ昇格の条件としてすぐにパフォーマンス改善やテストのカバレッジを上げると約束していたけど、結局実装されなかったため
toVersustoVersus

2024/1/12

  • GKE の Rapid channel で 1.29 が使えるようになっている。年末年始挟んだので、upstream のリリースから通常より少し遅め (release note)
    • 1.29 で Validating Admission Policy も Beta API を有効にすることで使えるようになってる
    • 1.29 で Sidecar containers の機能がベータになっているので、initContainers で指定すると起動しっぱなしにもなる
toVersustoVersus

2024/1/13

  • Google から xDS Adapter for Cilium という提案が上げられている (google docs)
    • GKE は Dataplane v2 の追加設定として xDS の導入を計画していて、同様の機能は Cilium でも有用だと思うから upstream への追加しようと思っているらしい
    • xDS Adapter の実装による恩恵
      • クラスタ外の Service / Endpoint へのリクエストのルーティング
      • Topology Aware Routing などの高度なルーティング設定のサポート
    • ユーザーが Topology Aware Routing に期待する挙動として、各ゾーンの容量に対してまず同一ゾーンの Endpoint で埋めていき、溢れた Endpoint を次に近いゾーンで埋めていくというのがある
      • Kubernetes が容量に対して Endpoint を埋めていく時にデータプレーン (e.g. Cilium) から配置に対するフィードバックがなく、適切に容量を埋め切ったかどうかがよく分からない
      • 仮にデータプレーンからフィードバックがあったとしても、中央集権的なオーケストレーターがいないと徐々に増えるフィードバックのイベントが多すぎて Thundering herd 問題を引き起こしてしまう
      • エンドポイントのルーティングに対する変更は Service / EndpointSlice など Kubernetes API サーバーを経由して取得する必要があり、オーバーヘッドになる。重み付けや Topology Aware Routing のために容量を調整しようにもコストが掛かる。Endpoint の重み付けを調整するには API 経由で EndpointSlice に情報を書き込む必要がある。Endpoint / Node が大量にあるクラスタではパフォーマンスに影響してしまう。
    • 上記の問題を解決するために xDS が有効
      • LRS (Load Reporting Service) が中央集権的なコントロールプレーンに対して負荷の状況を報告できる
      • Delta xDS で Kubernetes API が返す情報より少ない、更新のあったエンドポイントの情報だけを返すことができ、Kubernetes API サーバへの負荷も下げることができる
    • ローカルの Kubernetes クラスタ以外からのエンドポイントに対してのルーティング
      • Multi-Cluster Service で実現できるが、以下の実装がよく使われている
        • 別のクラスタに Service / EndpointSlice を作成して、エンドポイントの情報をミラーする必要がある
        • クラスタに中にゲートウェイを用意して、別のクラスタからのリクエストを受け取ってよしなにルーティングする
      • xDS はローカルクラスタだろうが外部のクラスタだろうが関係なくエンドポイントの情報を取り扱えるので上記の実装よりも効率的になる
    • Cilium が Kubernetes 以外にも xDS からエンドポイントの情報を受け取れるようにする
      • エンドポイントの情報が重複してしまった場合は、Kubernetes から取得した方を優先的に使う
      • 同一の Service が Kubernetes と xDS の両方からエンドポイントの情報を取得できる場合、Kubernetes API 経由で取得した Service の情報が優先されて xDS で取得した情報は使われない (重複したよの警告は出すかも?)
    • xDS のサポートは Cilium に現状ある KVStore の機能と似たような形になる
      • Cilium が新しいバックエンド (xDS) から情報を取得できるようになるだけ
      • 今は Kubernetes API と KVStore から取得できているので、そこに新しくオプションを追加し、全てのデータストアで利用できるように共通のインターフェイスを定義しておく
    • 最初は Cluster IP のルーティングに必要な Cilium のフィールドを xDS API とマッピングする。必要に応じて API のマッピングを増やしていく
      • e.g.) FrontendAddress (Cilium) -> filter_chain_match.prefix_ranges (xDS)
    • GKE の場合は xDS サーバとして Traffic Director を使うだろうから Traffic Director にエンドポイントの情報を登録するエージェントが動く感じかな?KEP-4188 で Kubelet で公開した情報を各ノードで動作するエージェントが Traffic Director に登録するとか?流石に Traffic Director の API のレート制限に引っかかりそう?
toVersustoVersus

2023/1/14

  • DaemonSet を複数のインスタンスサイズのノードが混在した環境で起動すると、リソース割り当てが環境に依らず静的に設定される。ノードの割り当て可能なリソースや Pod 数などに応じて動的に DaemonSet の Pod のリソース割り当てを変更する機能が欲しいという要望。今でもノードのラベルを使って Affinity ルールで実現できなくはないけど、インスタンスサイズが複数あると大変。提案者は時間がなくて KEP のプロセスは難しそうらしいので、誰かやってくれるなららしい。Pod In-place Vertical Scaling の機能を使って調整するのが現実的? (k/k#122753)
  • Kubernetes 1.28 で kube-scheduler のメモリ使用量の高騰の報告がある (k/k#122661, k/k#122725)
    • QueueingHint 関連の既知のリグレッションで 1.28.4 でデフォルトで機能を無効化してるからそれ以降は起きないはず (k/k#120622)
    • Kubernetes 1.29 で StatefulSet の Pod を Evict すると RecreatingTerminatedPod のイベントが重複して大量に発生する問題。以前の Pod のフェーズ変更で StatefulSet が Graceful Node Shutdown 発動後に Succeeded フェーズでスタックして起動してこなくなる問題の修正のリグレッションみたい (k/k#122709)
toVersustoVersus

2023/1/15

  • Preemption された Pod 数のメトリクスに PriorityClass のラベルを付与しようとしたけど、メトリクスが Stable なのでラベルの追加が許されない。ラベルが付いただけの別のメトリクスをこのためだけに追加するのは、既存のメトリクスと混乱するし、Stable なメトリクスを非推奨化して移行を促すことができるのか分からないので難しい。一旦追加はなしでユーザーから要望があれば考えることに (k/k#122357)
toVersustoVersus

2023/1/16

  • Kubernetes 1.30 から kubectl get cronjob の結果にタイムゾーン列が追加される (k/k#122231)
  • kubectl debug で事前定義のプロファイルじゃなくて、JSON 形式でコンテナのスペックを渡せる (変更したい箇所だけ?) カスタムプロファイルの機能は 1.30 でアルファを目指すみたい (comment - kubernetes/enhancements#4292)
  • 長いことベータ機能で居座っていた kubectl debug が 1.30 で GA を目指す (kubernetes/enhancements#4408)
toVersustoVersus

2023/1/17

  • Kubernetes Network Interface (KNI) (slide, blog)
    • KNI の目指すところ
      • CNI は Kubernetes 専用の仕組みではないので、CNI の上にレイヤーを置いて gRPC で Kubernetes 向けのネットワーク関連の操作ができる API (インターフェイス) を作りたい
      • CNI の仕組みができて 8 年経っているので再考したい
        • 現在は CNI の処理の結果の中で IP アドレスしか使われていないけど、他の情報も使いたい
        • CNI 2.0 の議論の中で Kubernetes 向けの機能の議論もある
      • クラウドとかネットワーク関連のハードウェアと良い感じに連携できるようにしたい
      • 単なるインターフェイスではなくエコシステムにしたい
    • 現在は kubelet から CRI を通して指示 (SyncPod / KillPod など) することで、コンテナランタイム (e.g. containerd) が sandbox コンテナを作成したとにネットワークネームスペースを作成して CNI plugin を呼び出して (e.g. CNI ADD / DEL) Pod のネットワークを設定している
      • kubelet (CRI client) <-> コンテナランタイム (CRI plugin) <-> CNI plugin
    • kubelet から CRI に加えて KNI を通して指示できるようになり、コンテナのセットアップとネットワークのセットアップを分離
      • KNI から gRPC 経由で KNI ネットワークランタイムに指示し、KNI ネットワークランタイムが CNI plugin を呼び出す
        • Attach / Update / Detach Query Pod or Node / Verify などなど
      • KNI ネットワークランタイムはコンテナランタイム内に埋め込むこともできるし、コンテナランタイムとは別のプロセスとして実装することもできるが、デーモンとして起動
      • ネットワークランタイム API の実装方法は様々でカスタムリソースや Kubernetes のオブジェクトを参照して Pod ネットワークを構成するコントローラーを埋め込んでも良く拡張は自由
    • Kubernetes のネットワークの制御がこれまでよりもしやすく、プラグイン的な実装も可能になる
      • NAT 排除したい、ECMP Anycast でのルーティング、BGP や TOR との連携、複数ネットワークなど色々と拡張性がある
      • Pod とノードのネットワークのセットアップ処理を分離できる
      • Kubernetes 本体への変更を減らすことができる
        • KNI 自体への変更は Kubernetes コア機能に比べて影響も少ない
toVersustoVersus

2023/1/19

  • Argo CD で脆弱性が修正されてる。昔から CSRF の危険性については言われてきたけど、最近のブラウザは Cookie の SameSite 属性が指定されていないと Lax 扱いになるから、優先度をあげて対応してなかったっぽい。ただ、オリジンが同一の親ドメインだと当然問題になる。Argo CD は CORS のプリフライトリクエストの Content-Type ヘッダーを検証しておらず、攻撃が成功してしまう。攻撃者が text/plain とかを指定してブラウザに対して機密情報を含んでないよと嘘をついてプリフライトリクエストが回避できちゃうから。今回の修正で、GET 以外のメソッドで Content-Type が application/json 以外のリクエストを受け付けなくしたので、プリフライトリクエストがバイパスできなくなる (GitHub Security Advisory)
toVersustoVersus

2023/1/20

  • KEP-4420: Retry Generate Name (kubernetes/enhancements#4421)
    • GenerateName を使ってリソースを作成し時に、ランダム文字列が衝突する問題の緩和策
    • 現在は 27 文字からランダムに 5 つの文字を選択してランダム文字列を生成しているので、27^5 = 14,348,907 のランダム文字列が生成可能
    • クラスタ内にあるカスタムリソースの数は多く共 100,000 - 1,000,000 個なので、ランダム文字列が枯渇する問題は今のところ大丈夫
    • ただ、ランダム文字列が衝突する可能性は高く、5 文字のランダム文字列だと、500 個の名前を生成する場合に 0.1% の確率で衝突し、5,000 個の名前を作成する場合だと 50% の確率で衝突してしまう
    • リソース名が衝突した場合に 409 Conflict を返すようにしているが、本番環境で動作している多くのクライアントが 409 の場合に再処理する実装にはなっていない
    • Generate Name でリソースを作成する場合に、ランダム文字列が衝突すると 7 回までリトライして新しいランダム文字列の生成を試みる
      • 7 回なのは 7 回繰り返すと、1,000,000 個の名前の生成でやっと衝突する可能性が 0.1% になる程度に抑えられるから
      • ランダム文字列の長さを増やす場合、11 文字まで増やさないと ~1,000,000 個の名前の衝突を 0.1% 程度まで抑えることができない
        • ランダム文字列の数に依存した実装をしているサードパーティ製のツールもあるので簡単に増えせない
    • リトライすると kube-apiserver のレスポンス時間に影響してしまう
      • 特に Validating Admission Webhook などを介する場合は、Admission Webhook にリトライの度にリクエストが流れるのでその分余計に時間が掛かる
      • ただ、そもそもリソース名の衝突はエッジケースで確率的にも起きにくいので、レスポンス時間の悪化は無視できるはず
toVersustoVersus

2023/1/21

  • KEP-4330: Compatibility versions (kubernetes/enhancements#4395)
    • WG-LTS で去年提案のあった Rust のエディション的な概念を導入する話
    • Kubernetes のコントロールプレーンのコンポーネントに --compatibility-version の起動オプションを追加し、Kubernetes のバージョン更新をより細かいステップに分けて安全に行えるようにする
    • 互換性バージョンは Kubernetes のコントロールプレーンのバイナリのバージョンとは完全に独立したもので、以前の Kubernetes バージョンの挙動 (API や機能など) を再現することができる
    • Kubernetes のバージョンを N から N+1 に更新するときに、より細かい粒度で更新できるようになると、N にはないが N+1 にはあるようなデータを柔軟に取り扱えるようになる
      • 1.30 から 1.31 に更新する場合、互換性バージョンを 1.30 に設定する場合を考える。クラスタ管理者は 1.31 で追加された機能に伴うデータを etcd に書き込むことなしに、1.31 の各コンポーネントのバイナリの挙動に問題ないかを確認できる。その後で互換性バージョンを 1.31 に更新すれば新しい機能を有効化して検証ができる。
    • KEP-4330 がベータに昇格した時点で、互換性バージョンのスキューポリシーを N-3 に拡張予定
      • コントロールプレーンのバイナリバージョンをスキップして更新が可能に
      • 1.28 -> 1.31 への更新を考える
        • コントロールプレーンのバイナリバージョンと互換性バージョンが 1.28 から開始
        • コントロールプレーンのバイナリバージョンを 1.31 に更新、互換性バージョンは 1.28 のまま
        • コントロールプレーンのバイナリバージョンは 1.31 のまま、互換性バージョンを 1.29 に更新
        • コントロールプレーンのバイナリバージョンは 1.31 のまま、互換性バージョンを 1.30 に更新
        • コントロールプレーンのバイナリバージョンは 1.31 のまま、互換性バージョンを 1.31 に更新
      • 互換性バージョンを更新しないので、クライアントが新しい API や機能を利用することはなく、バイナリバージョンの更新で問題が起きないことを確認できる
      • 更新ステップの粒度が細かくなるので、Kubernetes の更新を管理しているシステムがどこで問題が起きたのか特定しやすく、対処を実施しやすい
      • バイナリバージョンを変えることなく、互換性バージョンを戻すだけで切り戻しができる
    • API や機能、ストレージバージョン (etcd 内に保存される時のオブジェクトのバージョン)、CEL などが過去の Kubernetes のリリースバージョンと同じ挙動をするためのメタデータの追加
    • Kubernetes の互換性バージョンを N とした時に、Kubernetes のバージョン N のコンフォーマンステストを追加することを確認
    • 互換性バージョンに N が設定された Kubernetes のバイナリは API や機能、ストレージバージョン、CEL などに変更を加えず、N-1 にロールバックできるようにする
    • --compatibility-version<major.minor> 形式で指定 (e.g. 1.31)
    • FeatureGate に変更が入り、機能毎にバージョンを追跡できる仕組みが追加される
      • コンポーネントが起動するとその互換性バージョンでの FeatureGate の定義をもとに機能を有効 / 無効化、アルファ / ベータ / GA を選択

        map[Feature]VersionedSpecs{
        		featureA: VersionedSpecs{
        			{Version: mustParseVersion("1.27"), Default: false, PreRelease: Beta},
        			{Version: mustParseVersion("1.28"), Default: true, PreRelease: GA},
        		},
        }
        
      • 1.28 で GA or 削除された機能を考えると、1.30 までは FeatureGate による機能の ON/OFF のコードが残っていて、削除された機能の場合もコードは残っている状態だが、1.31 で FeatureGate & 機能のコードが削除される (N-3 のバージョンスキューポリシーの拡張)

      • 同一のステージ (e.g. ベータ) でも大きな変更が入った場合に、実装者は Feature Gate の互換性バージョンの情報を用いて挙動を変更することもできる

        • バグ修正を cherry-pick する場合に、バグの互換性を維持するための機能ではない
        if feature_gate.Enabled(FeatureA) && feature_gate.CompatibilityVersion() <= "1.28" {implementation 1}
        if feature_gate.Enabled(FeatureA) && feature_gate.CompatibilityVersion() >= "1.29" {implementation 2}
        
  • container_memory_working_set_bytes はカーネルによって解放されないメモリ使用量と必ずしも一致しない。例えば、Pod 内の複数のコンテナが emptyDir を共有していて、あるコンテナが emptyDir のファイルに書き込んで、別のコンテナがファイルを継続的に読み取っている場合、時間の経過とともにアクティブなファイルキャッシュ (total_active_file) が増えて、container_memory_working_set_bytes の値が増えてしまう。この状態で、プロセスが解放できないメモリ使用量を使おうとすると、カーネルがアクティブなファイルキャッシュを解放して total_active_file は減っていく。container_memory_working_set_bytes の値にはアクティブでないファイルキャッシュの値は含まれていないが、アクティブなファイルキャッシュ (total_active_file) の値が含まれている。カーネルは cgroup のメモリ上限の ~90% 程度で推移するようにゆっくりとページキャッシュを解放していくので、継続的にファイルに読み書きしているプロセスで、container_memory_working_set_bytes を解放できないメモリ使用量の指標に使うとアラートの設定が難しい。新しく container_memory_non_evictable_set のメトリクスを追加して、両方のファイルキャッシュを差し引いた値を返すようにする (google/cadvisor#3445)
toVersustoVersus

2024/1/23

  • AWS の EKS チームで EKS Anywhere に関わっていた人が Sidero Labs (Talos Linux) に移ってる (X)
toVersustoVersus

2024/1/24

  • 前に言ってた Kubernetes の PR / Issue コメントでメンテナを攻撃するユーザーの発言集を共有してガス抜きと自省するセッションが KubeCon EU 2024 で予定されている!スピーカーの 2 人ともユーモアあるから楽しそう (link)
toVersustoVersus

2024/1/26

  • Argo CD v2.10.0 で Server-Side Diff の機能がベータで入るみたい。差分表示に Server-Side Apply の Dry Run モードを使うオプションが選択できるようになる。API conversion のエラー (v1beta1 で作っていて v1 に更新した場合の差分が見られない問題) が解決されて、Validating Webhook の検証エラーも差分の時点で表示されるようになる。毎回 Server-Side Apply が実行されると API server に対して負荷になるので Server-Side Diff の結果をキャッシュして Application の Refresh や変更時などだけ再取得する (argoproj/argo-cd#13663)
  • Argo CD v2.10.0 で差分更新のために定期的に Git リポジトリをポーリングする間隔に Jitter を設定してタイミングをずらせるようになるみたい。timeout.reconciliation を 0 にして、Git Webhook でプッシュ時にイベントベースで Refresh させる方が良いけどその構成が取れない場合は、Git リポジトリへの負荷の低減になりそう (argoproj/argo-cd#16820)
toVersustoVersus

2024/1/27

  • EKS のコントロールプレーンを更新したら EKS マネージドアドオンも自動で更新して欲しい。AWS の人が良いねとは言ってるけど、やるとは言ってないな (comment - aws/containers-roadmap#2109)

  • Sidecar containers でメインのコンテナが停止中にサイドカーコンテナが異常終了したら再起動する機能は別の KEP にして対応する方針にしたのかな (kubernetes/enhancements#4438)

  • コンテナイメージの圧縮で Zstandard を使うと、gzip に比べて zstd の解凍の速度が 3 倍くらい早いからコンテナの起動も早くなるかもらしい。Image Streaming と互換性がないから一緒には使えない。コンテナ起動時にほぼ全てのイメージレイヤーが必要ならこの方法が向いている (blog)

  • KEP-4447: Promote Policy Reports API to a Kubernetes SIG API (kubernetes/enhancements#4448)

    • PolicyReport API が WG-Policy のリポジトリの下で開発されてきたけど、利用プロジェクトも増えてきたことだし kubernetes-sigs の正式なプロジェクトに昇格させたい
    • PolicyReport API は Falco, OPA / Gatekeeper, Keyverno, ... などのポリシー管理ツールの結果をクラスタ管理者やユーザーに報告するための仕組み
      • カスタムリソースとしては PolicyReport (ユーザー向け) と ClusterPolicyReport (クラスタ管理者向け)
      • Summary にポリシーの結果毎の集計が合って、Results に実際にあるリソースに対してどういう結果でメッセージも表示できたり
      • 以下の例にはないけど、scope / scopeSelectorで対象のリソースを絞ったりもできる
    • クラスタ管理者としてプラットフォームの利用ユーザーの動向を知るのには使えそう
      • 何か新しいポリシーを今後強制しようと思った時に、一旦違反しても警告だけ表示するようにしておいて、実際にどれくらいのユーザーがこのポリシーに違反しているのかを集計して、Results の詳細を見てどのリソースでどう言う使い方をしていて違反になっているかの傾向も分かるので便利そう。ポリシー違反の件数自体はメトリクスでも見れそうだけど、詳細もってなると把握しづらいと思うので。
    • 利用ユーザー側にもレポートとして報告できるので、教育するのにも使えそう
    apiVersion: wgpolicyk8s.io/v1beta1
    kind: PolicyReport
    metadata:
      name: sample-v1beta1-cr
      annotations:
        name: Sample CR
    configuration:
      limits:
        maxResults: 100
        statusFilter:
          - pass
          - fail
          - skip
    source: kyverno
    summary:
      pass: 1
      fail: 0
      warn: 0
      error: 0
      skip: 0
    results:
      - category: Pod Security Standards (Baseline)
        message: validation rule 'adding-capabilities' passed.
        policy: disallow-capabilities
        resources:
        - apiVersion: v1
          kind: Pod
          name: kyverno-6d88f6dcdd-k6bc5
          namespace: nirmata
          uid: 3407b31a-b0bb-4716-a443-f4aa15662ef2
        result: pass
        rule: adding-capabilities
        scored: true
        severity: medium
        source: kyverno
        timestamp:
          nanos: 0
          seconds: 1679565894
    
toVersustoVersus

2024/1/28

  • Validating Admission Policy でパラメータをカスタムリソースから参照している場合に、kube-apiserver を再起動するとポリシーに違反しているかに依らず必ずエラーになるバグの修正の PR。informer の作成がポリシーの resync 時に行われるが、ポリシーに変更がない場合に resync をスキップしていたのが原因。kube-apiserver が再起動した後にパラメータを渡すためのカスタムリソースの informer が作られるまでリトライするように修正 (k/k#123003)
toVersustoVersus

2024/1/31

  • EKS も GKE と同じで Pod に対する Mutating Admission Webhook で Kubernetes のライブラリのバージョンが古く Sidecar container 用の新しいフィールド (initContainers の restartPolicy) を握りつぶしていて 1.29 でベータに昇格したのに使えなくなってた (aws/amazon-eks-pod-identity-webhook#209)
toVersustoVersus

2024/2/1

  • EKS の AWS VPC CNI plugin で Network Policy を利用するの、内向きのルールでポート番号じゃなくてポート名を指定すると動作しないので注意です。再現手順渡したら修正の PR を上げてくれたので、しばらくすると直りそう。ただ、コントロールプレーンで動作しているコンポーネントなので EKS の新しいプラットフォームバージョンまで待たないといけなそう (aws/amazon-network-policy-controller-k8s#71)
toVersustoVersus

2024/2/3

  • Pod にマウントしている ConfigMap / Secret のファイルが作成されないことがある問題 (k/k#122807)
    • Pod が ConfigMap / Secret などのデータディレクトリをマウントする場合、タイムスタンプ付きのディレクトリ (e.g. ..2024_02_03_00_00_32.149716995) にデータを書き込んで、内部データディレクトリ (..data) にシンボリックリンクを作る。実際のファイルは内部データディレクトリ内のファイルへのシンボリックリンク (foo -> ..data/foo) になっている。
    • データを更新する場合の流れ
      1. 新しくマウントするファイルパスのバリデーション
      2. 内部データディレクトリ (..data) のシンボリックリンクを読むことで現在の参照先のタイムスタンプ付きのディレクトリを確認
      3. タイムスタンプ付きのディレクトリの中のファイルを見て回って削除すべきファイルを探す
      4. 新しくマウントするファイルの中身を現在のタイムスタンプ付きのディレクトリ内のファイルと比較して、更新が必要かを確認
      5. 更新が必要な場合は、新しいタイムスタンプ付きのデータディレクトリを作成
      6. 新しいタイムスタンプ付きのデータディレクトリにファイルを書き込む
      7. 新しいタイムスタンプ付きのデータディレクトリに書き込んだファイルの所有者の変更や権限を設定
      8. 新しいタイムスタンプ付きのディレクトリから ..data_tmp の一時的な内部ディレクトリに対してシンボリックリンクを作成
      9. ..data_tmp の一時的な内部ディレクトリを ..data に名前を変更
      10. 新しく作成されたファイルなど必要なら各ファイルから内部ディレクトリ内のファイルへのシンボリックリンクを作成 (e.g. bar -> ..data/bar)
      11. 削除されたファイルの内部ディレクトリ内のファイルへのシンボリックリンクを削除
      12. 古いタイムスタンプ付きのディレクトリを削除
    • この一連の処理の中で、新しくファイルを書き込む必要があって 9. と 10. の間で Kubelet が再起動すると正しくシンボリックリンクが作成されない問題の修正の PR。これまでは 4. でファイルの比較をして更新が不要と判断したら処理が終わっていたが、ファイルを更新する必要がなくても 10. からの処理は必ず通る様に変更している。
toVersustoVersus

2024/2/4

  • EKS 1.29 に更新後にノードのディスク使用量が増えたりで Kubelet がイメージ GC を発動し、Sandbox container (pause container) のイメージが GC されてそれ以降 Pod が起動できなくなるやばい問題。EKS で使っている pause コンテナイメージ (602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/pause:3.5) が Private な ECR に格納されていて認証が必要で落として来れなくなる。これまでは AMI の中に ctr pull でコンテナイメージを事前キャッシュとして含んでいたが、ctr pull だとイメージがピン留め (ピン留めすると Kubelet の GC の対象外となる) されておらず、CRI を経由する必要があった。containerd の CRI API を経由するために crictl でイメージをプルする形に変更してピン留めされるようにしている。1.29 に上げてるところまだないと思いますが、修正版の AMI (v20240202) がリリースされているので更新するか、ワークアラウンド (DaemonSet で pause のコンテナイメージを使用する Pod を起動しておいて GC されないようにする) を入れないとですね (awslabs/amazon-eks-ami#1597)
    • ピン留めの機能の cherry-pick は 1.7.3 だから EKS の AMI に同梱されていた containerd だとそもそもハンドリングできなかった。ただ、containerd 1.7.10 まで CRI のピン留め周りの実装が期待通りに動いていなかったっぽいので、AMI も containerd 1.7.2 から 1.7.11 まで更新しているっぽい (containerd/containerd#9381)
    • Kubernetes 1.28 以前は --pod-infra-container-image で指定したコンテナイメージは Kubelet によって GC されなかった。Kubernetes 1.29 からで Kubelet で管理していた Sandbox container のコンテナイメージの管理を CRI (e.g. containerd, CRI-O) 管理に移行した。その影響でこれまで Kubelet が Sandbox container のイメージを管理していた処理をコードベースから削除して、CRI (containerd) 側でピン留めして管理する方式に強制的に切り替えたのが原因。containerd / CRI-O の古いマイナーバージョンにも cherry-pick しているから大丈夫という話だったけど、古いマイナーバージョンの古いパッチバージョンを使っていたら壊れる。--pod-infra-container-image のフラグの非推奨化と処理の削除が同時に行われたのも良くなかったのかも (k/k#118544)
    • GKE の COS は定期的に containerd のバージョンを上げていっているので影響なし。ピン留め周りで Google の人が関わっているのもありそう (cos release notes)
    • Bottlerocket の AMI を使っている場合はまだ修正されていないようなのでワークアラウンドで DaemonSet を起動する必要がありそう (pause コンテナは CRI API からは見えず使っていても削除されちゃうので、明示的に pause コンテナのイメージを使った Pod を起動して消えないようにする) (bottlerocket-os/bottlerocket#3745)
toVersustoVersus

2024/2/6

  • MetalLB v0.14.2 で node.kubernetes.io/exclude-from-external-load-balancers のラベルが付いたノードを Service type LoadBalancer の紐付け対象から外すようになり、kind でシングルノードのクラスタを作るとコントロールプレーンとデータプレーンが同一ノードで動くので MetalLB が期待通りに動作しなくなる問題。ノードから手動でラベルを外すのが現状のワークアラウンドで、今後 kind 側で自動的にラベルを削除してくれるようになりそう (kubernetes-sigs/kind#3506)
  • Weaveworks が事業閉鎖。OSS プロジェクトは影響なく継続できるようにするみたいで、Flux は既に他と話し合ってるみたい。Cortex とか eksctl とか大丈夫かな (X)
toVersustoVersus

2024/2/7

  • 1.26.6-gke.1900 以降でコネクションの確立に断続的に失敗することが低確率であって、症状が発生してから数日で直るらしい。記載されている GKE のバージョン以降に更新すると問題は起きなくなる。コントロールプレーンとの接続の話なのかワークロードの話なのかよく分からん (release note)
toVersustoVersus

2024/2/8

  • KEP-4444: Routing Preference for Service (kubernetes/enhancements#4445)
    • Topology Keys (廃止済み) や Topology Aware Routing の後継の機能で Topology Aware Routing を置き換える予定
    • Topology Keys
      • 同一ノード -> 同一ゾーン -> どこでも、といったルーティングの順序付けをユーザーが柔軟に行えた
      • エンドポイントの過負荷などを考慮してデータプレーンからのフィードバックを元に賢くルーティングを行うことができなかった
      • Topology Keys という名前なのでトポロジー以外の要素でルーティングを決めるといった使い方が敬遠されていたかも
      • 順序付けを自由に行える弊害として、同一ゾーンや同一リージョンと言った使い方を超えて現実的に実装の難しい設定を要求することができてしまう
    • Topology Aware Routing
      • Service に service.kubernetes.io/topology-mode の annotation を指定することで、データプレーンの実装に従ってルーティングが行える
      • 当初、モードとして Auto 以外を指定できないようにした背景は、ユーザーにとって最も理想的で賢いルーティングをデータプレーンが決められるようにするため
      • 賢いルーティングの弊害として、ユーザーによる制御ができず、ルーティングの決定をユーザーが予測することさえ難しくなってしまった
      • 安全性とゾーンベースのルーティングの両立を目指して実装しようとしたが、両方を効果的に実現することはできなかった
      • ユーザーの中にはエンドポイントの過負荷よりも同一ゾーン内でのルーティングによるパフォーマンスの最適化や予測可能性が大事と思う人もいた
    • InternalTrafficPolicy
      • Service の internalTrafficPolicy を Local に指定することで、Pod からのリクエストが同一ノード上の Pod にのみ向かうようになる
      • フェイルオーバーの仕組みがないため、同一ノードに Pod が存在しないとパケットは DROP される
      • InternalTrafficPolicy が提案された当初は PreferLocal ポリシーの実装も検討されていたが破棄された
      • Topology Keys 亡き後、同一ノード -> 同一ゾーン -> どこでもといったフェイルオーバーが可能なルーティングを実現する手段はない
      • Routing Preference for Service でも最初は上記のルーティングを実現できないが、将来的に実装が可能なように考慮した設計を目指す
    • KEP-4444 でやらないこと
      • ユーザーが指定できるのはルーティングのヒントや優先度であって、ルーティングを厳密に保証できる訳ではない
      • Kubernetes Service で指定できる設定は実装によって解釈が異なることがあり、実装者は Kubernetes の標準的なルーティングの設定を全てサポートしなければならないといった制約もない
      • 既存の internalTrafficPolicy や extenalTrafficPolicy を置き換えるものではなく、あくまで補間し合うもの
    • Kubernetes Service に新しく routingPreference のフィールドを追加する (フィールド名は確定ではなく、変更の可能性が高い)
      • routingPreference としてサポート予定 (決定ではない) の値
        • Default: ルーティングの優先度を指定せず、実装に任せたベストエフォート
        • Close: クライアントに最も近いトポロジーを考慮してルーティングを行う
          • 同じノード、ラック、ゾーンあるいはリージョンなどトポロジーの近さの解釈は実装によって異なる可能性がある
      • 実装者は独自の <domain>/<heuristicName> の値を使って、標準的なルーティング以外を実装することも可能
      • データプレーンの実装が進むにつれて最初の解釈から変わる可能性もある
        • e.g.) 最初は同一ゾーンだけを考慮していたが、その後で過負荷も考慮した賢いルーティングに実装が変わった
    • kube-proxy の実装に関しては Default は現在の実装から変化はなく、Close に関しても既存の Topology Aware Routing のヒントや EndpointSlice を使って同じように実装して過負荷を考慮しないシンプルなものになる予定
      • コントロールプレーン (kube-controller-manager の中の EndpointSlice controller) は routingPreference を見て EndpointSlice にヒントを埋め込む
      • データプレーン (kube-proxy) は EndpointSlice のヒントや xTP (internalTrafficPolicy / externalTrafficPolicy) を見てルーティングを決定する
      • コントロールプレーンとデータプレーンはそれ以外のフィールドを考慮しない
    • Topology Aware Routing の場合はイベントだけだったけど、今回は Service の status にルーティングに関する情報が追加される予定
      • RoutingPreferenceAccepted: コントロールプレーンが routingPreference の値をパースして問題がない場合に設定される
      • RoutingPreferenceProgrammed: EndpointSlice コントローラーが routingPreference に従って EndpointSlice のヒントを生成できた場合に設定される
      • 現状はデータプレーンが EndpointSlice のヒントを見て設定したことを示す status はないが、将来的に RoutingPreferenceHonored とかで追加される可能性がある
      • routingPreference を指定しつつ、xTP にも Local が指定された場合は xTP: Local のルーティングが優先される
toVersustoVersus

2024/2/9

  • EKS 1.29 で pause のコンテナイメージが GC される問題、Bottlerocket の方でも修正版がリリースされた (v1.19.1)
  • Weaveworks の事業閉鎖に対する AWS の声明 (aws/containers-roadmap#2280)
    • Weaveworks 今までありがとう
    • eksctl は AWS が引き継いで引き続き開発していく
    • 今の高頻度なリリースサイクルは変えない予定
    • eksctl のリポジトリは 2024 年の後半に aws 組織に移す予定
  • Kubernetes 1.27 でアルファ機能として入った KEP-1287 In-place Update of Pod Resources の機能を使って、起動時に CPU を使う JVM 系のアプリケーションの起動時間を早くする kube-startup-cpu-boost を開発した話。Pod のスケジュール時に起動時に必要なリソースを割り当てておいて、起動が終わってから Pod の再起動なしでリソース割り当てを少なくする。リソース割り当てを減らすタイミングは固定の時間指定もできるし、Pod がリクエストを処理できる状態 (Pod condition の Ready が True になったら) になったらといった指定もできる。KEP-1287 はまだまだ不安定 & 機能不足で Kubernetes 1.30 でもアルファのままなので、使えるの当分先ですが (blog)
  • Kubernetes 1.30 の KEP Freeze 発動 (mailing list)
toVersustoVersus

2024/2/11

  • EKS で kube-proxy とか vpc-cni とかのアドオンがインストールされていないベアな Kubernetes クラスタを作るオプションを開発中らしい。GKE と棲み分けできていて良いとは思うけど、みんな本当にコアなアドオンまで Helm とかで自前管理したいのかな…。マネージドアドオンの更新すら面倒だけど (comment - aws/containers-roadmap#923)
toVersustoVersus

2024/2/14

  • KEP-1287: In-Place Update of Pod Resources の機能を使って Pod 内のコンテナのリソース上限 (resources.limits) を再起動なしに更新しようとしても、cgroup 内にプロセスがいる状態で CPU でもメモリでも cgroup の上限 (Pod 内の実行中のコンテナの resources.limits の合計か initContainers の合計の大きい方) を増やせないので、Pod を再起動して cgroup を作り直す必要がある。これはカーネルの制約。逆に Pod レベルのリソース上限の合計を減らす場合は再起動する必要がない (comment - k/k#122760)
  • etcd の中のバイナリエンコードされたオブジェクトを YAML / JSON / Protobuf に変換して表示したり逆にバイナリエンコードしたりできるツールが etcd-io に寄贈されている (kubernetes/org#4754, etcd-io/auger)
toVersustoVersus

2024/2/15

  • GKE で In-tree CSI から Compute Engine persistent disk CSI Driver で作った PVC / PV へのデータの移行方法。Effortless とかいうから期待したけど、GKE Backup でバックアップ取得してリストアしているだけだった。当然ダウンタイムは発生。新規のクラスタだとないだろうけど、前に VictoriaMetrics の数 TB あるデータを vmbackup / vmrestore で Compute Engine persistent disk CSI Driver に移行したな (blog)
toVersustoVersus

2024/2/16

  • EKS のマネージドノードグループ、セルフマネージドノードグループ、 Karpenter ノードのカスタム AMI で AL2023 のテックプレビューが開始。systemd cgroup v2 に移行している (X)
toVersustoVersus

2024/2/17

  • 個人的に気になる KubeCon 2024 Europe のセッション
    • 全体的に LLM の運用とか活用、マルチクラウド / マルチクラスタ、Platform Engineering、FinOps 関連の話が多め?
    • No 'Soup' for You! Enforcing Network Policies for Host Processes via eBPF - Vinay Kulkarni, eBay
      • 現在の Network Policy は L3 / L4 レイヤーの情報 (Pod の CIDR) を使ってアクセスを制御しているが、ホスト上で動作しているコンポーネント (e.g. kubelet) や hostNetwork を使っている Pod だと制御が難しい。そういったコンポーネントは L7 レベルの認証でセキュリティを担保するのが基本だけど、パフォーマンス影響がある。eBPF を使ってカーネルレベルで処理できるようにしてみた話。パケット毎にホスト上のプロセスの情報を送信して効率的にネットワークを制御する方法をデモを交えながら紹介する。KEP-1287: In-place Pod Vertical Scaling を実装した人で過去の KubeCon で eBPF を使って CPU 負荷の高いコマンド実行のイベントをトリガーにリソース割り当てを調整する話 (Resize Your Pods In-Place With Deterministic eBPF Triggers) をしてた人なので難しい話だろうけど楽しそう
    • Precision Matters: Scheduling GPU Workloads on Kubernetes - Amit Kumar & Gaurav Kumar, Uber
      • Uber の到着時間予測やマッチング、カスタマーサポートの自動化を AI / ML ワークロードで処理しており、Compute Team が GPU on Kubernetes を管理している。NVIDIA Device Plugin と cAdvisor の GPU メトリクスを利用して GPU リソースをどう提供しているか、CPU と GPU の両方が使われるクラスタで GPU の SKUs を考慮したスケジューリングや負荷ベース / ビンパッキングによる効率的なスケジューリングをどう実現しているかを紹介。また、GPU の共有やトポロジを考慮したスケジューリング、AMD や Intel などの異なる GPU のサポートなど将来的にやりたいことについても話す。
    • How Spotify Re-Created Our Entire Backend Without Skipping a Beat - Nick Rutigliano & Daniel de Repentigny, Spotify
      • 既存の Kubernetes クラスタを再作成して 50万台の Pod を移行する必要があり、ダウンタイムが発生すると全世界で報道されるような状況なら何から始めるか?Spotify の Platform Engineer チームが Kubernetes クラスタをゼロから作り直して、ダウンタイムなしでアプリケーション開発者にも影響を与えず、数万台のノードに跨る数百万台の Pod をどのように移行したかの話。移行作業の計画から実行までの流れやその過程で発生した障害についても触れる。この移行を実現できたアーキテクチャの詳細と制限、将来同じような移行作業を行う人たちはこうすべきという助言も。
    • Sharing Is Caring: GPU Sharing and CDI in Device Plugins - Evan Lezar, NVIDIA & David Porter, Google
      • Dynamic Resource Allocation (DRA) や Device Plugins に統合された Container Device Interface (CDI) の話。コスト削減のために使用効率の向上が必要となっている今、GPU の time-slicing や MIG、MPS など GPU のリソース共有を CDI でどう実現されているかを紐解く。
    • Introducing ClusterInventory and ClusterFeature API - Eduardo Arango Gutierrez, NVIDIA & Ryan Zhang, Microsoft
      • SIG-multicluster で話が進んでいる ClusterInventory / ClusterFeature API の話。ClusterInventory API で多様なツールをクラスタに統合・管理しながら、ClusterFeature API でクラスタ固有の機能や属性を公開する。クラスタ間でインストールされているツールの互換性や移行などこれらの API でマルチクラスタ運用がどう変わるか見ていく。ClusterInventory / ClusterFeature API を実装したカスタムコントローラーのデモもあるみたい。
    • Mastering GPU Management in Kubernetes Using the Operator Pattern - Shiva Krishna Merla & Kevin Klues, NVIDIA
      • LLMs を Kubernetes で動かせるようになってきたけど、GPU の利用は必須。GPU を Kubernetes で利用しようと思うと、カーネルドライバーのインストールやコンテナランタイム、デバイスプラグイン、監視などいろんな知識が必要。GPU のソフトウェアスタックのインストールからライフサイクル管理、更新、監視/復旧の 4 つのフェーズに分けることができる。基本的な GPU のセットアップから高度な利用までを Operator パターンで実装するメリットについて NVIDIA GPU Operator を元に紹介。Kevein Klues さんの深い話楽しみ、いつの間にか NVIDIA の Distinguished Engineer になってる
    • OCI as a Standard for ML Artifact Storage and Retrieval - Peyman Norouzi & Eric Koepfle, Bloomberg LP
      • Bloomberg で OCI レジストリに ML のアセットを保存して配布している話。OCI Distribution Specification のレイヤー構造やバージョンやメタデータを使えば、ML のアセット固有の問題も解決できる。Bloomberg では OCI Artifacts をプラットフォームに組み込んでおり、モデルのビルドから配布まで行っているのでそこで学んだことを共有するセッション。
    • DRAcon: Demystifying Dynamic Resource Allocation - from Myths to Facts - Kevin Klues, NVIDIA & Patrick Ohly, Intel
      • KubeCon NA 2023 は DRA がキーノートで出てきたり、Tim Hockin が KubeCon ではなく DRAcon に参加したようだと発言するなど大きな話題を呼んだ。Patrick さんと Kevein Klues さんによる Dynamic Resource Allocation (DRA) の詳細の話。1.26 でアルファ機能として追加されたが、1.29 でもアルファ機能のまま。ベータに昇格するにはコミュニティからの今の実装で良いのか、GPU 以外のユースケース、、Cluster Autoscaler 連携の問題の解決方法に関してフィードバックが必要。
    • Disintegrated Telemetry: The Pains of Monitoring Asynchronous Workflows - Johannes Tax, Grafana Labs
      • メッセージやイベントを介してやり取りする非同期処理のワークフローのテレメトリを収集しようとすると、メトリクスやトレースがバラバラになってメッセージやイベントの一生や影響を推測しづらい。分散トレーシングの世界だとこの問題に親子関係による強い相関や紐付けによる弱い相関で対処できるとしているが、どちらも問題があるので要件によって最善の方法を選ぶしかなく、その選択に役立つ洞察も紹介する。W3C の Context Propagation の草案にメッセージプロトコルの話も盛り込まれていて、OpenTelemetry で定義されたメッセージ向けのセマンティック制約の話も。
    • Dealing with eBPF’s Observability Data Deluge - Anna Kapuścińska, Isovalent
      • eBPF が自動計装やオーバーヘッドの少なさ、完全な可観測性から Observability 界隈でバズっているけど、完全な可観測性を実現するためにシステムから大量のデータを収集している。干し草の山から針を見つけようにも eBPF が更に干し草の山を作る事態になる。実際の運用経験をもとに、データの奔流に対処するための方法を掘り下げる。アプリケーションの監視やセキュリティ領域での利用事例を取り上げて、共通点やベンチマークの結果を紹介。
    • This Won’t Hurt a Bit: Taking Kubernetes to 3,000+ Dental Offices Simply and Securely - Bogdan Mitrea Kevin Reeuwijk, Dentsply Sirona
      • 3000+ の歯医者さん向けの口腔内スキャナー製品の中で Kubernetes が動いている話。GitOps でデバイス管理して、トラブルシューティングやソフトウェアの更新もリモートから行い、スキャン結果をシームレスにクラウド側に転送。低消費電力デバイス上でどう動かしているか、セキュリティの担保どうやっているかの話も。Edge Kubernetes はどこまで行くのか...
    • Squeeze Your K8s: How We Adopt Time-Series Forecasting Models in FinOps Practices? - He Li, Shopee; Nicholas Kwan, Sea Limited
      • Kubernetes は静的に CPU / メモリのリソース割り当てを指定する機能はあるが、過剰割り当てによるクラスタ全体での使用率の低下を生む。調査によるとほとんどの Kubernetes クラスタの平均 CPU 使用率は 20% 未満だった。1.27 から In-place Resource Resize の機能が使えるようになったが、Pod のリソース使用量を正確に予測して割り当て分を完全に使わせるのは難しい。Shopee での FinOps に時系列予測モデルをどう適用したかの事例。時系列予測モデルを使って、長期 / 短期的なスケジューリングを予測しているか、Kubernetes 向けにどうチューニングしているか、サービスのレイテンシに影響せずにオーバーコミットをするにはどうするかなど。
    • Reducing Cross-Zone Egress at Spotify with Custom gRPC Load Balancing - Aleksandar Mitic & Yannick Epstein, Spotify
      • Spotify のインフラコストの大部分がクラウドのゾーンを跨いだ Egress 課金。gRPC の負荷分散アルゴリズムを Open Request Cost Aggregation (ORCA) によるサーバ側のメトリクスを使って、耐障害性やパフォーマンスを維持しつつ賢くルーティングできるようにした話
    • To Infinity and Beyond: Seamless Autoscaling with in-Place Resource Resize for Kubernetes Pods - Aya Ozawa, CloudNatix Inc. & Kohei Ota, Apple
      • inductor さんと ladicle さんの Kubernetes の現状のリソース管理の辛みと In-place Resource Resize の利点の話
    • Lightning Talk: Expand Your Kubernetes Horizons with Multiple Service CIDRs: A Game-Changer for Network Management - Antonio Ojea, Google
      • アントニオさんの KEP-1880: Multiple Service CIDR の話。Service に割り当てる IP 範囲をクラスタ作成後に変更できる機能
    • Lightning Talk: Help! My Envoy Sidecar Is Consuming 8GBs of Memory! - Krzysztof Słonka, Kong
      • 大規模なメッシュを構成している Envoy のサイドカーコンテナが 8 GB のメモリ消費と 30% の CPU 時間を消費していた例をもとに、delta-xds や on-demand-xds などの設定の増分更新のアルゴリズムを解説し、Envoy のリソース消費が高くなった原因を説明する。Kuma、Istio、Consul でこの状況を改善する方法も紹介。
toVersustoVersus

2024/2/18

  • Kubernetes では Finalizer でリソースの削除を一時的に止めることはできても、リソースの削除を保護することはできない。Deletion Timestamp が付いたリソースに Finalizer が設定されていても、リソースがいずれ消えることには変わりない。KEP-2839 でリソース削除を保護する仕組みを追加しようとしたが、進展がないなので、Crossplane はリソース削除できないようにするために Usage ってカスタムリソースと KEP-2839 がやる予定だった仕組みを使って独自に実装したみたい。ただ、Crossplane のように依存関係の深いリソースを削除しようとすると、子リソースが消えるまで削除保護で守られ、結果的に親リソースの GC の ExponentialBackoff が 15 分とか長くなっちゃって消えるのに時間がかかる。リソースに変更を加えたら GC の Backoff をリセットできないかの要望 (comment - kubernetes/enhancements#2840)
    • Crossplane の各種クラウドプロバイダーのリソースの所有者 (OwnerReference) に Usage がなって、Usage が消えるまでリソースが GC されないようにする
    • リソースに使用中のラベル crossplane.io/in-use: true を付与する
    • Validating Admission Webhook で使用中のラベルが付与されたリソースに対して DELETE が発行されると 409 Conflict を返す
toVersustoVersus

2024/2/20

  • CPU ワークロードと GPU ワークロードが混在しているクラスタだと CPU ワークロード (e.g. 推論システム) はノードに分散して起動させたいけど、GPU ワークロード (e.g. 学習システム) は集約したいから NodeResourceFit scheduler plugin に複数の戦略を設定できるようにしたい要望 (k/k#119849)
    • 以下の方法で回避可能だけど、マネージド Kubernetes だと無理なところは無理だからノード毎 (e.g. CPU or GPU ノード) に NodeResourceFit の戦略を変えられると嬉しいけど、スケジューラーのスコア付の部分は確かにややこしくなりそう
      • セカンダリスケジューラーを用意して CPU / GPU ノードで NodeResourceFit の設定を変える
      • スケジューラーを BinPacking にしておいて、CPU ワークロードに Topology Spread Constraints を強制
  • OpenMetrics はアーカイブされて、Prometheus にアセットなどをマージする予定で進んでいる。Prometheus 形式のメトリクスをベースに標準化を目指したけど、OpenTelemetry のメトリクス形式が主流で、Prometheus も v3 (KubeCon 2024 NA でお披露目予定) で OpenTelemetry メトリクスのサポートを安定化して ingest の機能をデフォルトで有効にする予定らしいのでやむなし (comment - cncf/toc#1242)
toVersustoVersus

2024/2/21

  • GKE の Image Streaming でバグがあって現状 Fix がリリースされていないみたいなのでバージョン上げないようにしないと (release notes)
  • 1.26.6-gke.1900 以降でコネクションの確立に断続的に失敗することが低確率であって、症状が発生してから数日で直るらしい問題 (release notes) の upstream の Issue はこれっぽい (k/k#123024)
    • いまだに原因が分かってないけど、GKE 1.26+ で Cloud Provider を in-tree から out-of-tree に移行したら、稀にノードの Provider ID が設定されていない状態でノードが Ready 状態になり、Ingress や Gateway がエンドポイントの登録処理を進められずにアプリでダウンタイムが発生する可能性がある。Provider ID が設定されていないとノードオブジェクトが更新されなくなるので、Topology Aware Routing のゾーン情報の生成にも影響がでる。Provider ID が設定されていないのにノードが Ready 状態になってるのおかしくない?って話みたい。GKE 以外でも out-of-tree の Cloud Provider を使っているところだと発生しうる。
    • 修正版の GKE バージョンは in-tree の Cloud Provider を使うように変更したのかな、それとも Provider ID が設定されるまで Ready 状態にならないように何か変えた?
    • Topology Aware Routing でノードが Ready 状態の時にゾーンのラベルが存在するという仮定はまずくないって別の Issue。k/k#123024 の状態が発生すると、EndpointSlice controller はゾーンのヒントの情報を全ての EndpointSlice から削除して、ノードにその後でゾーンのラベルが追加されても EndpointSlice のヒントは復活しない。Pod が起動したり停止したり EndpointSlice に変更があるとヒントが復活する。Spot インスタンスの利用など、ノードの再作成が激しいと起こりやすい。両方とも GKE の中の人が挙げている Issue で、GKE の中の人がコメントし合っているので緊急度が高そう。ヒントがなくなってもゾーン跨いだ通信が発生するだけで、通信への影響はなさそう?Provider ID がないと Ingress / Gateway のエンドポイントの登録処理が進まない方が影響は大きそう (k/k#123401)
    • 久しぶりにやばいバグでお祭り感がある
    • ノードに Provider ID が追加されたら NEG コントローラーの処理をトリガーするの最近追加されていて、1.27 にも cherry-pick されている。ノードが Ready 状態になった後で Provider ID が追加されたら登録処理を再開できるようにしている? (kubernetes/ingress-gce#2438, kubernetes/ingress-gce#2439)
    • ゾーンの情報を Provider ID から取得しているから空っぽだとどうしようもないのか。ゾーンの情報がないとどのゾーンの NEG に登録するか分からないし (source)
    • で、アントニオさんのこの PR で Provider ID が設定されていない場合はノードの taint を外してノードを Ready 状態にしないようにしているのかな (k/k#123331)
    • dims さんが cc しているから AWS の人もこの問題に気付いている (comment - k/k#123331)
toVersustoVersus

2024/2/22

  • Descheduler のメンテナの方に Spinnaker のパイプラインの実行時に突然権限エラーが発生する問題の根本原因を解決したか聞かれたけど、当時は spin-clouddriver-caching を再起動するしかなかったな...。Zendesk はまだ Spinnaker を使っていて、この辛い問題もまだ存在するらしい (comment - spinnaker/spinnaker#6542)
toVersustoVersus

2024/2/23

  • また、GKE の Dataplane v2 の Cilium を魔改造している。本家の Cilium CNI に fast-start-namespaces なんてオプションないけど、設定できるようにしようとしている。テストケースで kube-system と default が指定されているけど、何のセットアップを優先しようとしているのか (GoogleCloudPlatform/netd#277)
  • Pod の Lofecycle Hook (e.g. PreStop hook) のアクションで sleep 指定できるようになるの Kubernetes 1.30 でベータに昇格してデフォルト有効になるから、このまま問題起きなければ使えるようになりそう。コンテナイメージの中に sleep のバイナリ含めなくてよくなるやつです (k/k#122456)
toVersustoVersus

2024/2/24

  • Kubernetes 1.29 / 1.30 が containerd のどのバージョンと互換性があるのか記載して欲しいという Issue。containerd v2.0 は beta.2 までリリース済みで、Container Runtime Meetup#5 で徳永さんが正式版は今年中に出てきそうと言っていた。ただ、この Issue の書き方だと containerd v2.0 と Kuberneter 1.30 のリリースが衝突して検証時間が十分に取れないことを心配している。RC もまだ出ていないし、4/17 までに containerd v2 が出てくる可能性は少ない?あとは containerd v1.7 のサポート延長の話で、これは徳永さんも触れていたけど最終的にサポート期間が containerd v1.6 の EOL (最速で 2025/2/15) まで延長された。ただ、Kubernetes 1.29 の EOL (2025/2/28) より前なので、Kubernetes 側の移行パスを考慮できていないのではという話になっている。特にクラウドプロバイダーによっては Kubernetes のマイナーバージョンのサポート期間を 2 年に延長しているケースがあるので、現状だと例えば Kubernetes 1.29 のパッチバージョンで containerd v2 に移行するとかいう無茶をやらないといけない (containerd/containerd#9866, slack)
    • containerd v1.7 のサポート期間延長の話 (containerd/containerd#9833)
    • 各クラウドプロバイダーが containerd v2 に移行する Kubernetes のバージョンは結構慎重に様子を見ないとバグ踏む可能性が高そう
toVersustoVersus

2024/2/25

  • Linkerd が 2.15 以降でリリースの方法を変えて、CNCF の Graduated プロジェクトとして問題があるのではの議論。GitHub 上でのソースコードの公開はそのままだけど、リリース資材は配布されなくなる。安定版は Linkerd の CLI や Helm chart でインストール可能だが、2024/5/24 以降に安定版の 50 人以上の会社での本番利用が有償になる。安定版とは別にエッジリリース (開発中の最新のコードなので破壊的変更の可能性あり) があって、これは GitHub で OSS として公開されるので無償で使えるし、Apache v2 ライセンスなので商用利用可能。OSS であることには変わりないけど、Linkerd のメンテナが元々の開発元の Buoyant しかいなかったりで Graduated プロジェクトの基準を満たしていないのではって話も出ている (cncf/toc#1262)
    • 大企業のタダ乗りがやっぱ原因かな (blog)
    • The reality is that for the past eight years, billion-dollar businesses have been built on these public stable Linkerd releases without any reason to fund the project or contribute back in any way. That's not a moral judgment or a statement of fairness, but it is a statement of fact. If we want Linkerd to grow and improve dramatically, as we all do—we need to fix that now. This change is key to unlocking that opportunity for us.

toVersustoVersus

2024/3/1

  • 何でも良いけどあるリソースのオブジェクト (~ 50KB) を 100 qps で書き込みながら、resourceVersion="" を指定 (etcd から直接読み取る) して 100 並列で watch すると etcd と kube-apiserver のメモリ使用量が高くなりコントロールプレーンが落ちちゃうらしい。Google Cloud で顧客から報告があって調べていて、AWS でも同様の報告があって別の Issue が立てられている。api-server と etcd の間の gRPC の stream を複数の watch で共有しているから過負荷な watch がいると他の watch が十分に stream を使えなくなってエラーが出て壊れる。壊れると watch を再度繋ごうとするが、大量に壊れた watch がいると新しい接続は即座に close されてしまう。で、また再接続を続けることで API Priority and Fairness (APF) による 409 を引き起こすことにもなる (kubernetes/kubernetes#123448)
    • gRPC のメタデータにユニークな値を付けることで明示的に watch stream を共有しないようにする hack があってそれを利用しているっぽいけど、RPC 増えるとそれはそれでメモリ使用量増えないのかな (k/k#123532, comment - k/k#123448)
    • 1 つの stream で watch を共有すると CPU 効率を高めることができるけど、その分スループットは stream の利用者で共有だから低くなるよと。当たり前か。で、今回のメモリ使用量が増えているのはスループットを超えたことで watch が壊れ再接続を繰り返していることが原因なので、watch が壊れないようにすれば緩和できるよねってことか (comment - k/k#123448)
toVersustoVersus

2024/3/2

  • Kubernetes がモノレポでのビルドや依存関係の管理を Go の Workspaces 機能を使う形に移行した。これまでは staging リポジトリと modules の共生のために GOPATH を hack して使っていたが、Go の開発チームがそれを好ましく思わずに作ってくれたのが Workspaces の機能 (google groups)
toVersustoVersus

2024/3/3

  • まだ ContainerCheckpoint の CRI API を実装しているコンテナランタイムは CRI-O だけだけど、KEP-2008: Container Checkpoint がこのまま何もなければ Kubernetes 1.30 でついにベータに昇格。kubectl checkpoint で操作できるようになる予定なので、サブリソースを分けて node/checkpoint の権限が必要に。ただ、node/proxy の権限があると kubectl proxy で kubelet の checkpoint の API を直接叩けてバイパスできちゃうので、RBAC は正しく制限しないと (k/k#123215)
  • kube-scheduler の Filter 拡張点を実行した結果ノードの候補が残らなかったときに、詳細を diagnosis に書き込む処理が毎回排他ロックを掛けている問題。スケジュール予定の Pod の数 * 既存のノード数のロックが掛かって処理が遅くなるので、排他ロックを掛けなくても良いように修正。報告者のケースだと 9k ノードで 500 Pods/sec で起動するらしい (バッチ処理系だろうけど凄い規模) のでボトルネックになっていた。プロファイルをとって調査したみたいで、修正後に大幅に Pending 状態の Pod の数が減っている (=スケジュール時間が改善された) (k/k#123609)
toVersustoVersus

2024/3/4

  • Kubernetes 1.28 で Prometheus Adapter を利用していると OpenAPI のパスが重複エラーになる問題。Prometheus Adapter と metrics-server が同一のパスで /metrics.k8s.io/v1beta1 で異なる OpenAPI のエンドポイントを提供しているのが原因らしい。Prometheus Adapter が Aggregated Discovery の登録方法を間違えている (/metrics.k8s.io/v1beta1/... の登録はあるが、/metrics.k8s.io/ の登録がない) のと Kubernetes 側も登録されている Aggregated Discovery のバリデーションが甘いというのがあったらしい (k/k#122668)
toVersustoVersus

2024/3/5

  • kubectl 1.30 から kubectl debug に —custom のフラグが追加されて変更したい箇所の ContainerSpec を JSON 形式で渡すと元の Debug Container 起動時に設定を上書き可能になる。結局事前定義のプロファイルだと、すべてのユースケースをサポートできないので自由にカスタマイズできるオプションが追加された (k/k#120346)
toVersustoVersus

2024/3/6

  • Kubernetes 1.30 で Topology Aware Routing の後継の KEP-4444: Service Traffic Distribution がアルファ機能で入りそう。Topology Aware Routing はゾーン毎に Endpoint (Pod) の数に偏りがあるとノードの CPU 数で補正されていたけど、その補正がない純粋な同一ゾーンでのルーティングになる。同一ゾーン内に Endpoint がない場合は、別のゾーンの Endpoint にフォールバックする。Service に新たに追加されるフィールド名は結局 trafficDistribution になり、デフォルトは nil で指定なし扱い。アルファの段階だと PreferClose を指定できるだけで、データプレーン (e.g. kube-proxy, Cilium, …) によって解釈は異なる。kube-proxy の場合は↑で書いた挙動になる。(k/k#123487)
  • ExecProbeTimeout の FeatureGate を Kubernetes 1.30 で完全に消して無効化できないようにしようとしている。GKE ではデフォルト有効なところを FeatureGate で明示的に無効化しているのは知らない人多そう。LivenessProbe の ExecProbe の処理がタイムアウトするようになると急に Pod が再起動し始めて困る顧客が結構いる。ExecProbe の実装を変えろ以外に移行パスがないから、Google としても顧客に強く言えなかったんだろうな。AWS と RedHat Microsoft の人が FeatureGate で明示的に無効化しているユーザーなんていないだろうと思って消す気満々で進めていたら、Google の人が止めに入ってて面白い。顧客影響あるしすぐに消す必要もないでしょって (k/k#123574)
    • ExecProbeTimeout は本来バグで Probe で Exec を指定した場合だけタイムアウトが無視されちゃってたんですよね。で、バグに依存しちゃったユーザーがいて破壊的変更になっちゃうパターンなので本当に難しいですよね。
      KEP-1972: kubelet exec probe timeouts の提案と実装も Google の人だし、提案の時点で一部のユーザーにとっては破壊的変更だってことは書かれているので、移行パスを準備できずに放置してたっぽいです。タイムアウトの時間を超えた場合に警告の Event を書き込むようにしてユーザーに実装を確認するよう周知して、数バージョン待って削除とかしかやりようがなさそう
toVersustoVersus

2024/3/10

  • Ephemeral Storage の上限を超えて使い続けるとしばらくして Pod が Evict されるけど、Pod の状態が ContainerStatusUnknown になっちゃう問題。Evict された後に Pod を削除するときに、①コンテナランタイムがコンテナを停止 (このタイミングでは削除はしない)、② コンテナランタイムからコンテナの状態を取得して Pod の状態を更新する。①と②の間でコンテナ削除のタイミングで競合が起こり、コンテナの状態を取得しようにも既に消えていて ContainerStatusUnknown になる。Pod の状態は Failed になっているので、Pod IP が再利用されようが実害はないが、Otel collector では問題があるらしいが詳細は不明 (k/k#122160)
  • GKE の Ingress / Gateway API の 502 / 503 エラーの対処法のドキュメントの記載がかなり詳しくなっている。最近だと BackendService の Drain Timeout が Ingress / Gateway API で設定できるようになったので設定すると 503 を回避できる。preStop Hook で sleep と併せれば 502 エラーも回避できる。Backend Service の Drain Timeout の値はリクエストの処理時間の 1.5 から 2 倍が目安。 BackendService の Drain Timeout を設定しない場合と設定する場合で挙動が異なる。BackendService の Drain Timeout を設定しない場合は NEG controller が Endpoint を NEG から Detach するまでの時間差を気にする必要がある。BackendService の Drain Timeout を設定する場合は、Drain 開始までの時間差 + Drain Timeout を考慮する必要がある。Drain 開始までの時間差は 1 分を見た方が良いってあるけど、preStopHook >= Backend Service Drain Timeout + Drain Latency だとすると preStopHook の sleep の時間結構長くなっちゃうじゃん (docs)
toVersustoVersus

2024/3/11

  • EKS の vpc-cni の v1.16.3 に CPU 使用率が高く張り付くバグがあるので注意です。EKS のマネージドアドオンを利用している場合、東京リージョンに v1.16.4-eksbuild.2 がもうロールアウトされているのでそちらに切り替えると良さそう(aws/amazon-vpc-cni-k8s#2807)
toVersustoVersus

2024/3/15

  • Karpenter を EKS Access Entry API での認証に移行するときに system:bootstrappers の Kubernetes Group の紐付けが必要ない理由 (comment - aws/karpenter-provider-aws#5369)
    • TLS Bootstrap の処理で使用するトークンを取得するための権限が入っているが、EKS は証明書ベースの認証を許可しておらず、IAM を使って認証するのでこの権限は不要
      • Kubernetes API サーバに Bootstrap トークンで一時認証をして証明書署名要求 (CSR) を送信し、コントロールプレーンで CSR リクエストに署名する流れで使う
    • kubelet サービング証明書の要求で使う権限も含まれているが、EKS では eks:node-bootstrapper という ClusterRoleBinding があり、system:nodes の Kubernetes Group が kubelet のサービング証明書の要求ができるように許可しているので不要
    • system:nodes の Kubernetes Group に紐付いた IAM ロールを用意すれば良い (EKS ノードに紐付けた IAM ロールを Karpenter でも共有して使っている場合は、自動的に system:nodes の Kubernetes Group と紐づくのでこの対応も不要)
toVersustoVersus

2024/3/18

  • kubectl run -it で Pod を起動してインタラクティブにコマンドを実行すると実行結果も含めて Pod のログとして書き込まれてしまう件について、せめて kubectl run -it 実行時に警告文を表示しようという Issue。kubectl run -it --rm の組み合わせはやりがちなので気をつけないと (k/k#123967)
❯ kubectl run -it --rm debugger --image alpine -- ash
If you don't see a command prompt, try pressing enter.
/ # ls
bin           home          mnt           product_uuid  sbin          tmp
dev           lib           opt           root          srv           usr
etc           media         proc          run           sys           var
/ # pwd
/
# Pod のログ
❯ stern .
+ debugger › debugger
/ # ls
^[[3;23Rdebugger debugger bin           home          mnt           product_uuid  sbin          tmp
debugger debugger dev           lib           opt           root          srv           usr
debugger debugger etc           media         proc          run           sys           var
debugger debugger / # pwd
debugger debugger /
  • 調査で API トークンとか DB のパスワードとかコンソールに書き込むと kubectl logs や Cloud Logging とかで見れちゃう。例えば、以下のコマンドとか叩くとまずい

    curl -u username:mypass http://example.com/
    
  • kubectl run の後で kubectl exec の場合は大丈夫

    kubectl run debugger --image alpine --command -- sleep infinity
    kubectl exec -it debugger -- ash
    
toVersustoVersus

2024/3/19

  • readinessProbe は successThreshold を 1 以外に設定できるけど、startupProbe と livenessProbe は successThreshold を 1 以外に設定できても良くないという要望に対する答え (comment - k/k#106025)
    • Pod 起動直後の unknown 状態と probe に一度でも成功した後で失敗した trouble 状態は別物として考える
    • Pod 起動直後の unknown 状態での successThreshold は alive と判定するまでの閾値なので意味はありそう
    • Pod が trouble 状態になると、successThreshold の閾値がハードルとなって alive / trouble を行ったり来たりする可能性があるが、その間は Pod が再起動されることはない
      • successThreshold が 5 で failureThreashold が 3 の場合、trouble 状態から 4 回 probe に連続成功していても trouble 状態のまま
      • 現状の successThreshold が 1 で固定の場合でも、trouble 状態か alive 状態かという違いだけで probe に失敗している間は閾値の回数を超えない限り Pod が再起動されることはない
    • trouble 状態の時は probe の失敗の回数をリセットしないのはどうか
      • successThreshold が 5 で failureThreashold が 3 の場合を考える
      • alive 状態から 1 度 probe に失敗して trouble 状態に遷移し probe の失敗回数が 1 となる
      • 次の probe に成功すると成功回数が 1 となるが、trouble 状態のまま
      • そもまま probe に成功して成功回数が 4 回となってもまだ trouble 状態のまま
      • probe に失敗すると失敗回数が 2 となり、成功回数がリセットされる
      • また probe に連続で 4 回成功すると、成功回数が 4 回で失敗回数が 2 回
      • 次の probe に成功すると alive 状態に遷移するし、失敗すると失敗回数が 3 回となるので Pod が再起動される
+-----------+     +---------+                 +-------+
|           |     |         |                 |       |
| (re)start |---->| unknown |--(succeed 1x)-->| alive |<---+
|           |     |         |                 |       |    |
+-----------+     +---------+                 +-------+    |
     ^                 |                          |        |
     +--(fail 3x)------+                      (fail 1x)    |
     |              +---------+                   |        |
     |              |         |<------------------+        |
     +--(fail 2x)---| trouble |                            |
                    |         |--------(succeed 1x)--------+
                    +---------+
toVersustoVersus

2024/3/20

  • Istio の Ambient Mesh が次期 v1.22 でベータに昇格予定 (X)
toVersustoVersus

2024/3/23

  • How Spotify Re-Created Our Entire Backend Without Skipping a Beat (youtube)
    • Spotify は 3,200+ のマイクロサービスがピーク時に 40,000+ VM (コア数は 1M+、メモリは 4 PB+) 上で 500,000 Pod が動作し、1.5 TB/s の通信が発生する
    • Spotify は複数 Kubernetes クラスタでのマルチテナント構成で、同じクラスタをずっと in-place で更新し続けてきた
      • クラスタ数は僕らが思っているより少ないらしい
    • 開発者は基本的に Golden Path (チュートリアル) に従って本番環境にアプリケーションをデプロイしているが、半分くらいは Golden Path から外れたサービスやパフォーマンスの最適化のために設定が異なるサービス、定期実行のジョブなどがある
      • 開発者は namespace レベルで Kubernetes API を叩くことができるので、Golden Path に従っていないサービスもデプロイできてしまう
    • Spotify ではこれまで Compute as the Product の考え方でプラットフォームを提供してきた
      • Kubernetes のことをそれほど気にしない開発者は Golden Path に従ってサービスをデプロイできれば良い
      • 最適化のために YAML を触りたいユーザーもいる
      • Operator を書いたり、専用のクラスタが欲しいといった Cluster as the Product を望むユーザー層もいるが、それらはサポートしていなかった
        • namespace 内での権限しかないからクラスタワイドな CRD とかのリソースを作れない感じかな?
    • Cluster as the Product のユースケースにも対応するため、既存のクラスタを再作成することにした
      • Compute as the Product と Cluster as the Product で求められるものが違う
      • Kubernetes API へのアクセス方法やクラスタ更新などの考え方が変わってくるし、ガバナンスの適用が難しくなったり、GPU などのアクセラレータを使いたいといった要望にも対応する必要がある
      • 逆に SLA やコスト効率に関しては同レベルのものが必要だったりする
        • 信頼性を高めるということはコストも掛かるので、コストを取るか信頼性を取るかはプラットフォームを作っていく上で重要な判断材料
    • 新しいクラスタのアーキテクチャ検討
      • Global Load Balancer を前段に置いてリージョン内に複数の Kubernetes クラスタを作ってサービスを動かし、ユーザーから近いリージョンのサービスに接続できるようにする
      • 同一リージョン内に複数の Kubernetes クラスタがあるが、同一リージョン内のクラスタ間通信は Headless Service を介して行える
        • クラスタ間通信を実現するためのサービス検出の仕組み (Headless Service に Pod IP を紐付ける処理) はクラスタ外でやっているらしい
        • これにより、新しくクラスタを追加しても既存のクラスタのあるサービスから別のサービスへの接続ができる
      • 複数クラスタ化を実現するためには homogeneous なクラスタにする必要がある
        • コア API (クラスタ更新のケース?) やカスタムリソース、GPU などのアクセラレータがクラスタに関わらず利用できなければならない
        • サービスのデプロイツールや監視・アラートのツールが複数クラスタ対応する必要がある
    • 既存のクラスタで動作するワークロードの対応
      • Backstage のソフトウェアカタログでどういうワークロードが動いているか分かる
        • プラットフォームチームは全てのワークロードの全ての要件を把握しているわけではないので、特殊な要件のあるサービスは Backstage で詳細を確認して移行をサポートする
      • 新規のサービスに関しては Golden Path のテンプレートを更新して、利用している言語やフレームワーク向けの最適な Kubernetes の設定を提供する
      • 既存の昔から動いているようなサービスの設定変更 (e.g. HPA の挙動、API の非推奨化) は 内製の Fleet 管理ツールで動的に反映する
      • Keyverno でガバナンスの適用と動的な設定の差し込みを行う
        • クラスタやリージョン固有の設定を Keyverno の Admission Webhook の機能で注入している
    • サービス影響のない移行の自動化
      • 手動でやると人的ミスがあるし、自動化してもコードのバグがあるかもしれないので、安全に移行する仕組みが大事
      • 移行の各ステージで冪等性を担保
        • サービス毎にクラスタを跨ぐ移行を開始しても大丈夫かをチェック
        • 移行作業中にサービスのコード変更が入らないように一時的にサービスのバージョンを固定化
        • コストは掛かるが、新旧のクラスタにサービスをデプロイ
        • 新旧のクラスタでトラフィックを切り替え
        • 旧クラスタのリソースを削除
        • サービスのバージョン固定を外す
      • クラスタ切り替えを決めたのはプラットフォームチームなので開発者の対応は必要ない形で移行できるようにした
    • 質問コーナー
      • Keyverno をどう利用しているかもう少し詳しく
        • 180 のリージョンでサービスを展開しているので、リージョン毎に法令が違って配信できるコンテンツも違うのでそういった設定を Mutating Admission Webhook で差し込んでいる
        • Validating Admission Webhook の機能で requests.memory == limits.memory などのベストプラクティスの確認
      • どうやって開発者の関与なしに移行を完了できた?
        • 各種デプロイのツールは各サービスのソースコードのあるリポジトリへのアクセス権限を持っていて、API 経由でサービスのデプロイもできるので、それを移行ツールでトリガーするだけで良かったし、終わったら Backstage でユーザーにお知らせした
      • Headless Service でのマルチクラスタの疎通はどうやったか?
        • サービス検出の機能がクラスタ外にあるけど、それ以外のネットワークの詳細は話せない
        • この感じ MultiCluster Services は使っていなさそう?
      • Kubernetes 上で動かしているデータベースも移行したのか?
        • データベースはマネージドサービスを使っていて移行していない
      • 移行前のチェックって何を確認していたの?
        • サービスの正常性の確認、サービスが正常な状態じゃなかったら開発者に通知して正常になってから移行していた
      • Kubernetes クラスタはどこで動いている?ベアメタルや仮想マシン上?
        • Google Cloud を使っているのでオンプレではなく、GKE
      • CD 関連でマルチクラスタへのデプロイやクラスタ移行にどういうツールを使ったか?
        • 内製のツールが多いが、Config Sync や Argo CD などの OSS のツールも使っている
      • Cluster as the product に関して、クラスタの管理者権限をユーザーに渡すことになるが、安定性や信頼性との線引きをどうしているか?
        • 専用の Kubernetes クラスタを使いたいユーザーは Kubernetes に関する深い知識を持っているので、ある程度信頼している。クラスタの更新に関しては Compute チームのメンバーが面倒を見たりはしているみたい。今の規模ならこれでも上手くいっている
toVersustoVersus

2024/3/26

Space-Age GitOps: The Rise of the Humble Pull Request - Zach Aller & Michael Crenshaw, Intuit

  • GitOps による CD のフローの中で変更の提案、プロモーション、変更の切り戻しを Argo CD と PR をベースに改善したい話
    • 変更を提案して、(レビューを受けて)、変更がデプロイされて、変更を dev -> stg -> prd とプロモーションして、メトリクスやログを関して問題が起きたら切り戻すのが一連の CD のフロー
    • GitOps による CD のフローの中で Argo CD は変更のデプロイの部分を担っている
  • Helm の values ファイルや Kustomize の overlay などの設定が一部変更された PR を出されても、実際にどういう差分になるのか分からず、approve して良いか分からない
    • ローカル環境に PR の変更をフェッチしてきて、マニフェストを生成してみて確認してみる
    • Argo CD の自動同期の機能を OFF にして、Argo CD の UI で差分を確認する (会場でも笑いが出ていたようなので結構みんなやっているみたい)
  • Jenkins などで dev -> stg -> prd 環境へのプロモーションのワークフローを組んでも、開発者が知らなくても良いプラットフォームの実装の多くを見せてしまっており、問題が起きた時にどう対処して良いか分からない
  • プロモーション中に変更を切り戻しに関して、Argo Rollouts を使っていても分かるのは Pod に対する変更のみで、Service のラベルセレクタの間違った変更が加わったりすると検知はできない
    • Argo CD の History and Rollback の画面から変更を切り戻そうにも、過去のどのコミットが正常な状態なのか UI から分からないので、切り戻し先のコミットを特定するのに時間が掛かる
    • 問題が起きた PR のコミットを revert しようにも、生成されるマニフェストの差分は表示されないので本当に正しいのかよく分からない
  • 上記の問題を解決するために Argo CD に追加する機能の案
    • Argo CD の Controller がメインのブランチを元に各環境のブランチを作成し、そこに生成したマニフェストを置く
    • 開発者が PR を作成すると、各環境のブランチに対してマニフェストを生成して差分のリンクを PR のコメントに貼ってくれる
    • 開発者が差分を見て問題ないことが確認できたら、PR をマージする
    • PR をマージすると Controller が各環境毎にプロモーション用の PR を作成する (マージしたコミットの Git ハッシュを PR タイトルに含む)
      • PR は本来 3 つ (dev/stg/prd) 作成されるが、dev 環境の PR は既に自動でマージされている状態
    • PR のコミットステータスを使って徐々に環境にプロモーションされるようになっている
      • stg 環境へのプロモーションは dev 環境への反映で問題が起きないかをコミットステータスを使って待っている状態
    • コミットステータスでのチェックは色々とカスタマイズできる
      • e.g.) 変更がマネージャーに承認されている
      • e.g.) マニフェストの静的解析をパスしている
    • Argo CD のプロモーションの画面 (スクショの中の画面はかなりラフなモック) で今どこまで進んでいるか確認できる
    • プロモーション中に問題が起きた時の切り戻しも Controller が自動的に PR を作成してくれる
      • PR の中にマニフェストの差分があるので確認してマージすれば良い
  • 質問コーナー
    • Kargo との違いは何?
      • Kargo は CI パイプラインを使って、Kustomize や Helm を使って新しいバージョンのイメージタグを埋め込む戦略
      • 今回の提案は複雑な CI パイプラインを開発者に見せずに、既存の触り慣れたインターフェイス (Git や GitHub など) でやれないかという話
      • Kargo は今回の Argo CD への提案と相反する訳ではないし、共存もできるかもしれない
    • 環境毎にブランチを分ける必要があるの?
      • 人間 (開発者) はディレクトリ毎に環境を分ける運用で良い
      • Argo CD の Controller が環境毎に生成したマニフェストを含んだブランチを作成するだけ
toVersustoVersus

2024/3/27

Pod Scheduling Readiness の仕様に関する指摘

KubeVirt の人が .spec.nodeName が指定された Pod に Pod Scheduling Readiness を差し込めないのなんでか聞いている (comment - kubernetes/enhancements#3521)

  • 特定の namespace に Pod が作成されたときに Mutating Webhook で Pod Scheduling Readiness を差し込むようにしたが、ある Operator が Pod の .spec.nodeName を指定した Pod を作り、その Pod にも Mutating Webhook で Pod Scheduling Readiness を差し込もうとしてエラーになったっぽい
  • Pod の .spec.nodeName にノード名を指定すると、Pod のスケジュールは終わっていて指定したノードで起動する準備ができていることを意味するけど、Pod Scheduling Readiness が指定されると Pod はまだスケジュールの準備ができていないことを意味するので矛盾しちゃう
  • どのノードでスケジュールするか決まっているなら .spec.nodeName は本来 .status.nodeName にするべきでは?.spec.nodeName で指定できちゃうと、ユーザーがこのノードで起動したいという意図でこのフィールド使っちゃうじゃん -> 特定のノードで起動したい場合は Node Affinity の NodeSelectorTerm でmetadata.name にノード名を値として指定するようにしましょう (DaemonSet もそうしている)
  • 歴史的に status フィールドはどこかからリストアできる情報だけを置く場所として使われていた時期があり、nodeName はどこからもリストアできない情報なので .spec.nodeName となった。今は status フィールドにしかない情報も多くあるので .status.nodeName であるべきかもしれないけど破壊的変更になるから無理
  • 破壊的変更を気にしなくて良いなら .spec.nodeName は強い RBAC で守られるべきだけど、難しい。.spec.nodeName は Kubernetes の初期からあり、RBAC は Kubernetes 1.6 から入ったので最初から考慮するのはそもそも無理だった
  • .spec.nodeName は一度設定されると値を消すことができない
  • .spec.nodeName を明示的に指定すると kube-scheduler と競合してスケジューリングの結果に影響することがある。DaemonSet が NodeAffinity を使っているのもこれが理由
  • .spec.nodeName が指定されていてもノードの割り当て可能なリソースを超えてリソース要求を指定すると、OutOfCPU になって Pod が起動できないじゃん -> 最終的に kubelet の Admission でノードで起動できるか判定されて拒否されることはある。ただ、結果がどうであれそのノードで Pod を起動しようとはしている
  • kubelet も自身のノードで起動する Pod を監視する (watch する) 時に .spec.nodeName で絞っているから、.spec.nodeName が指定された時点でそのノードにスケジュールはされているし、そのノードで Pod を起動し始める
toVersustoVersus

2024/3/29

SIG-etcd での etcd-operator の開発

新興の etcd-operator (aenix-io/etcd-operator) が SIG-etcd のサブプロジェクトに名乗りを上げている (kubernetes/community#7796)

  • 先週の KubeCon EU で etcd-operator 開発を再始動しようという議論があったらしい
    ロシア語圏の方たちが中心になって数週間前から開発が始まった etcd-operator のメンバーがせっかく作るならいろんなユースケースを取り込みたいということで声を上げたみたい
  • etcd-operator は色々なところで開発されていて Kubernetes 上で動かすなら coreos/etcd-operator が機能的には優れていたけど、結構前にアーカイブ済み。ただ、IBM などフォークして開発を続けているクラウドプロバイダーもあるらしい
  • OpenShift は openshift/cluster-etcd-operator を作っていて RHEL / CoreOS のホスト上で static Pods として動く単体の etcd のライフサイクル管理のためのもので、OpenShift のインフラや API に強く依存している
  • 他にも Gardener (SAP) が Gardener 向けの etcd-operator を作ったり、すでに開発が止まっている個人プロジェクトがいくつかある状態
  • それとは別に SIG-cluster-lifecycle が etcdadm というツールを開発していて、kOps で使われてきた etcd-manager とまた別の本番利用可能な状態の etcdadm を合体したもので、Kubernetes 以外でも動くので Operator とは言えないし、Kubernetes 以外で動くのが強み (GKE はこれ使ってそう?)
  • どのツールも etcd を熟知しているメンテナが関わっていないし、ツールの開発者も etcd のコミュニティに積極的に関わってきていないのが問題 (たぶん品質の話とコミュニティの要望が含まれていないオレオレ実装ばかりってことを言いたそう)
  • 新興の etcd-operator よりも成熟したプロジェクトをベースにした方がいいのではという指摘があるが、SIG-etcd のメンバーの一人はどのプロジェクトをベースにするとかは関係なく etcd のメンテナが関わること、etcd コミュニティの声を聞きながら開発が進められることが重要というスタンス
  • 今後の SIG-etcd のミーティングでどのプロジェクトをベースに進めるか議論していくみたい。Datadog が内部で使っている etcd-operator を OSS 化してベースにする案もあるらしい
toVersustoVersus

2024/3/30

kind with GPU

NVIDIA の klueska さんがいろいろ試してできた kind のコードベースに変更を加えずに NVIDIA GPU を使うためのサンプルリポジトリ (klueska/kind-with-gpus-examples)

GKE の Workload Identity 連携の改善

GKE の Workload Identity 連携が改善されて Google Cloud のサービスアカウントを作らずに Kubernetes のサービスアカウントを直接メンバーとして権限を紐づけられるようになったらしい (X)

toVersustoVersus

2024/3/31

NetworkPolicy の参照実装

アントニオさんの新作の Kubernetes の Network Policy の E2E テストで使う用のシンプルな Network Policy の参照実装。今は Kubernetes の CI で Network Policy の挙動を確認するために Calico が使われているが、サードパーティのツールだとデバックが難しいので自作している (aojea/kube-netpol, k/k#124117)

  • 一般的な Network Policy の実装は、Network Policy の API リソースを解釈するコントロールプレーンと iptables や nftables のルール、eBPF のフックの差し込みや eBPF Map を管理するエージェントに分かれる
  • kube-netpol は Node 上で動作するエージェントのみで、パケットのフィルタリングの処理をユーザー空間で行うという違いがある
  • kube-netpol は iptables の Filter テーブルの FORWARD / OUTPUT チェイン (パケットが Node から外に出る前のフック) にルールを追加して、NFQUEUE にパケットを渡すようにする
  • kube-netpol は NFQUEUE に接続して、フィルタリングの処理を登録する
    • 現状はヘッダーの情報のみでフィルタリングし、ペイロードの情報は使わない
  • フィルタリングの処理の中で渡されたパケットの IP や TCP / UDP / SCTP ヘッダーから 5-tuple をパースし、Network Policy で許可されているか検証して ACCEPT / DROP を判定する
    • ACCEPT の場合は後続のチェインの処理を継続する
  • Network Policy の CIDR 指定も名前付きポートも対応しているみたいだし、一通り動作しそう
  • Pod Informer に Pod IP でインデックスを貼って Pod IP から対象の Pod の情報を効率的に参照できるようにしている
    • ソース IP から送信元の Pod の情報を、宛先 IP から送信先の Pod の情報をそれぞれ取得し、Pod の情報から namespace 内の全ての Network Policy を取得して、許可されているか確認していく
  • Pod 間でネットワークのやり取りを開始する最初のパケットに対して 5-tuple の抽出 -> Network Policy で許可されているかのチェックが入り、それ以降は conntrack の仕組みでバイパスできるのでパフォーマンスに凄く影響するということはないらしい
  • とはいえ、Network Policy が設定されているされているいないに関わらず、パケットのフィルタリングをユーザー空間で行なっているので、初回のパケットはパフォーマンス影響を受ける
    • E2E テストで挙動を確認するためなら十分だし実装がシンプル
    • NFQUEUE にパケットを渡すのを Network Policy が設定されている Pod に制限すると今の実装よりパフォーマンス改善できる
toVersustoVersus

2024/4/1

External Secrets Operator で利用するプロバイダーが選択式になる予定

External Secrets Operator で利用するシークレット管理サービスの設定のみをインストール & Controller もクライアントを初期化するようになるっぽい (external-secrets/external-secrets#2655)

  • ユーザーはこれまで通り SecretStore の .spec.provider にプロバイダーの設定を書く
  • External Secrets Operator で SecretStore / ClusterSecretStore の .spec.provider を読み取って内部的にそれぞれのプロバイダー毎にクラスタレベルの Provider カスタムリソース (e.g. gitlabs.providers.external-secrets.io) に変換し、認証情報などの設定を保存する
  • SecretStore / ClusterSecretStore に .spec.providerRef のフィールドが新しく追加されて、External Secrets Operator がクライアントの初期化時にその設定を読み取る
    • 互換性担保のため、SecretStore / ClusterSecretStore に .spec.providerRef が設定されていない場合は、.spec.provider からプロバイダーを特定して .spec.providerRef を設定
  • SecretStore / ClusterSecretStore からプロバイダーの設定をカスタムリソースに分離することで、プロバイダーの追加や認証方法の追加などで SecretStore / ClusterSecretStore に変更を加えなくて済む
    • External Secrets Operator の対応プロバイダーは今後も増えるる中でコア機能を GA していくために必要な分離
  • 利用しているサービスのクライアントを初期化するだけに変わるので、メモリのフットプリントを減らせる
  • 将来的に SecretStore の廃止か SecretStore の .spec.provider は検討しているみたい
toVersustoVersus

2024/4/2

EKS での Amazon Linux 2023 のバグ

EKS で Amazon Linux 2023 への切り替えを検証中に、一部の Pod が Kubernetes の API サーバへの接続でタイムアウトして起動できなくなっていたのバグだったみたいで、awslabs/amazon-eks-ami#1738 の修正が入ると直るらしい。systemd.network と VPC CNI plugin で管理している設定が競合して VPC CNI plugin が設定したセカンダリ ENI のルーティングルールとかを上書きしたりしちゃうみたい?EKS 利用している方はまだ Amazon Linux 2023 の AMI に切り替えない方が良いです。(awslabs/amazon-eks-ami#1737)

EKS の Network Policy で名前付きポートの指定で動作しない問題が解消

https://zenn.dev/link/comments/902ecc684f8652 の修正が最新の EKS のプラットフォームバージョンにロールアウトされて問題なく動作するようになった。

toVersustoVersus

2024/4/3

WG-Serving の立ち上げ

Making Kubernetes great for accelerated workloads: a serving working group

  • 大規模モデル (Generative AI) のアクセラレータ (e.g. GPU) を利用した推論用のワークロードの改善を目的とした WG-Serving ができる
  • Kubernetes で大規模モデル (Generative AI) 向けの学習や推論のワークロードを動かす需要は高く、ここ数年間は WG-Batch で学習のための大規模バッチ処理の改善が進められ、SIG-Node を中心に Dynamic Resource Allocation (DRA) の開発が推進されてきた
  • 推論に関しての議論は発散しがちで、最優先で検討もされて来なかったので、WG-Serving を立ち上げてシンプルで安定性のある、効率的にアクセラレータを利用した推論のワークロード議論を進めていきたい
  • LLM のワークロードは Node とほぼ同じリソース割り当てで 1:1 でデプロイされたり、1 台で複数のノードに跨って実行されることが多いため、Node のスケールアウトが必要で通常の Web アプリに比べてワークロードの起動に時間が掛かる
  • 現状の GenAI の推論のワークロードは StatefulSet を使っていることが多いが、推論のワークロードの要求を満たすために設計されたリソースではない
  • WG-Serving に関しては KubeCon EU で議論があったらしい
  • WG-Serving の目的
    • 他の様々な SIG や WG に寄せられた推論のワークロードに対する要望をまとめつつ、コミュニティからも推論のワークロードの要件を集める
    • Kubernetes のコントローラに手を加えて、アクセラレータ利用の改善や推論やモデルの提供でよく使われるフレームワークへの対応を進める
    • kServe や Seldon, Kaito などの既存のエコシステムと連携して、既存の Kubernetes の共有の問題点を特定して改善まで持っていく
      • Kueue が様々なバッチ処理向けのフレームワークのスケジューリング部分を抽象化したように
    • 推論のワークロードの管理や自動スケール、負荷分散を改善するプロジェクトを新しく立ち上げる
  • WG-Serving のユースケース
    • 複数の Node に跨って推論のワークロードを実行するために LeaderWorkerSet という新しいカスタムリソースとコントローラーが提案されている
    • アクセラレータを利用した推論のワークロードの自動スケールはコストの観点で非常に重要だが、対応が十分ではないし、何より起動までに時間が掛かる
    • 検証環境で推論のワークロードを動かすときに、中断は許容できないけど、使っていない時は 0 台にスケールインしたいとかアクセラレータを共有してリソース効率を高めたいといった要望がある
    • アクセラレータを複数のクラウドで同じように利用するのが難しい
    • アクセラレータを利用した大規模なワークロードは中断に脆く、起動は遅いので、中断に対してより保護的な仕組みが求められている
  • WG-Serving に関わる SIG は SIG-Apps を主として、SIG-Architecture, SIG-Node, SIG-Scheduling, SIG-Autoscaling, SIG-Network, SIG-Storage と多岐に渡る

WG-Accelerator-Management の立ち上げ

WG-Creation-Request: WG Accelerator Management

  • 業界内でもアクセラレータの効率的な利用が求められる中、Kubernetes におけるアクセラレータ利用の改善が急務なので、WG を立ち上げて既存の API やモデル、スケジューリングのアルゴリズム、自動スケールなどを再検討する
  • これまでは WG-Batch の中で Dynamic Resource Alloaction (DRA) の KEP を中心に取り組んできたが、AI の推論サーバなどバッチ処理以外のワークロードでもアクセラレータは利用されるので、WG-Batch や WG-Serving と協力して要望を聞きながら進めていく
  • KubeCon Europe 2024 で議論があったらしく、バッチ処理以外でアクセラレータを利用している人たちからコンタクトがあり、一緒に改善していこうと協力的だったので WG を立ち上げることに
  • WG-Serving とは違って低レベルの API の提供や抽象化を目指し、バッチ処理や推論のワークロードでアクセラレータを設定、共有できるようにすることに集中する
  • WG が解決する課題
    • アクセラレータのリソースプールをワークロード間で効率的に共有したり、個々のデバイスを分割して効率的に共有できるように
    • クラスタの詳細に立ち入らずに (管理者がどうクラスタをプロビジョニングしているかによらず)、利用者がアクセラレータを利用したワークロードを実行できるように
    • スケジューラがワークロードを動かす Node を正確に選べるように
    • 自動スケールや自動プロビジョニングのツールがワークロードを起動するのにどの Node をスケール or 作成すれば良いか事前に予測できるように
    • 「Pod が Node で動く」から「ワークロードがリソースのキャパシティを消費する」に転換させ、複数の Pod をアクセラレータを持った複数の Node で起動できるようにする
    • ハードウェアの故障によるワークロードの中断を最小限に抑える
    • アクセラレータの分割による断片化の問題を解決する
    • 上記の課題を解決するために、既存の API を良い感じに拡張したシンプルな API として提供し、簡単に移行できるようにする
toVersustoVersus

2024/4/4

Pod の CrashLoopBackoff の改善の動き

Pod の CrashLoopBackoff の Backoff の間隔の調整とか特定の exit code で挙動を変えたいとか、Pod ステータスの restartCount を初期化したいとかいろいろと要望が上がっている件、Google の人が KEP 準備中で v1.31 でアルファ機能として入れるのを目標に動き出しているみたい (comment - k/k#57291)

toVersustoVersus

2024/4/5

containerd 1.17.4 / 1.6.30 の exec に関するリグレッション

containerd 1.7.14 / 1.6.30 で同一の Pod / コンテナに対して kubectl exec / kubelet の execProbe を並列で実行するとハングすることがあるリグレッションが起きている (containerd/containerd#10036)

  • EKS の Bottlerocket の最新の AMI が containerd 1.6.30 に更新していて readinessProbe / livenessProbe で execProbe を設定している Pod で kubelet からのヘルスチェックに失敗する問題が報告されている。Karpenter の Drift 検出の機能で AMI が置き換えられて何件か報告が上がっている (bottlerocket-os/bottlerocket#3866, bottlerocket-os/bottlerocket#3867)
  • AL2 / AL2023 の AMI の containerd のバージョンは 1.7.11 なので影響は受けていない (awslabs/amazon-eks-ami)

containerd/containerd#9999 で修正の PR がマージされて、1.7.15 / 1.6.31 としてリリース済み

Kubernetes の kind の E2E テストで問題に気付けていて偉い (k/k#124185)

toVersustoVersus

2024/4/6

Amazon Linux 2023 の AMI のバグ修正

https://zenn.dev/link/comments/1468dd87cb7814 で書いた Amazon Linux 2023 の AMI を使った時に Kubernetes の API サーバとの通信に失敗する Pod が出る問題の修正が無事にマージされて、修正を含んだ AMI がリリースされました (comment - awslabs/amazon-eks-ami#1737)

EKS 1.29 on Fargate の名前解決の問題が解消

https://zenn.dev/link/comments/0d3372e8c04399 で書いた EKS 1.29 on Fargate の名前解決の問題の修正が全ての EKS クラスタにロールアウトされたそうです。(comment - aws/containers-roadmap#2281)

KEP-4569: Deprecate support for cgroup v1

ついに cgroup v1 の非推奨に向けた KEP が上がりました。Dockershim の削除以来の大きな変更かつ長期的な取り組みになりそうです。(kubernetes/enhancements#4572)

  • cgroup v2 の方が cgroup v1 よりも機能が豊富でインターフェイスの統一性もある
  • Linux ディストリビューションやコンテナランタイムの多くが cgroup v2 をサポートするようになったので cgroup v1 の非推奨化を進めていく
  • クラウドプロバイダーの利用者の多くがまだ cgroup v1 を利用しており、オンプレ環境なども含めると cgroup v2 への移行は進んでいない
  • cgroup v2 への移行パスや移行時に直面した一般的なバグの共有などをドキュメント化して cgroup v2 への移行を促進する
  • Kubernetes v1.31 からkubelet に cgroup のどのバージョンを利用しているかのメトリクスを追加し、kubelet の起動時に cgroup v1 の非推奨の警告ログを書き込むようにする
  • RemovedCgroupV1 の FeatureGate を追加し、ON の場合に cgroup v1 の Node で kubelet が起動できないようにできる
    • アルファ段階ではデフォルトで無効化
  • Kubernetes の CI の多くがまだ cgroup v1 でしか動いていないので、cgroup v2 に移行しつつも cgroup v1 の CI も別途残すことで cgroup v1 起因のバグに気づけるようにしなければならない
toVersustoVersus

2024/4/8

kubelet の RunOnce / Standalone モードが実装された背景

kubelet には RunOnce と Standalone という余り知られていない 2 つの実行モードがあって、SIG-Node の定例でその背景の話が少し出てる (Kubernetes SIG Node 20240326)

  • kubelet の RunOnce モードは static Pods (staticPodPath で指定したディレクトリのマニフェスト) を起動して、終了するのを待って終わったら exit するだけのモード
    • 10 年くらい前に RunOnce モードの機能が k/k#1534 で入ってからコードは大きく変わっておらず、ここ 4, 5 年の Pod のライフサイクル関連の機能 (Init / Sidecar containers) はサポートしていないし、Pod のボリュームマウントも正しく動作していないらしい
    • 2017 年に RunOnce モードを非推奨化する動きが k/k#47184 であったが、利用しているユーザーがいて議論も上手く進まず非推奨化されなかった
    • 期待通りに動いていないし、簡単なユニットテスト程度でテストもほぼなく、今だと Podman の機能で podman kube play があって RunOnce モードの置き換えになるから RunOnce モードを今度こそ非推奨化したい (k/k#124030)
  • Kubernetes の最古参の一人の Dawn Chen によると、RunOnce モードは Kubernetes が正式にアナウンスされる以前に追加されたもので、Docker にコンテナを起動する機能があり、Kubernetes はコンテナよりも Pod の概念 (当時はコンテナマニフェストと呼ばれていた) を浸透させたくて単一の Pod を実行する RunOnce モードが作られた
  • kubelet の Standalone モードは RunOnce モードと違って API サーバと通信しないだけで、Pod のライフサイクル管理などの機能は通常の kubelet のモードと同じ
    • GKE だとコントロールプレーンのコンポーネントを動かすために使っていて、他のディストリビューションでも使っているところはあるかもしれない
  • Dawn Chen によると、kubelet の Standalone モードは Kubernetes クラスタではなく、シングルノードの Kubernetes で複数の Pod を起動するために追加された機能
  • RunOnce モードに関しては KEP を作って通常の非推奨化のプロセスを進めていき、Standalone モードに関してはコントロールプレーンのコンポーネントの実行以外のユースケースを集めながら必要かどうかも含めて慎重に議論が必要
toVersustoVersus

2024/4/10

Karpenter と Volume のマルチアタッチエラー

Karpenter を v0.32.0 以降に更新すると Node を停止する際に Karpenter が付与する taint に破壊的変更 (node.kubernetes.io/unschedulable から karpenter.sh/disruption:NoSchedule=disrupting に切り替え) があり、AWS EBS CSI driver < 1.29.0 だと停止する Node 上のボリュームを正常にアンマウントできない。そのせいで、kube-controller-manager (KCM) の Volume Attach / Detach controller が別の Node で起動した Pod のボリュームをマウントしようとしてマルチアタッチエラーが 6 分間+ (強制的にデタッチされるまでの間) 発生して Pod の起動が遅れる。AWS EBS CSI driver の Pod は PreStop hook で Node が drain されている場合のみ Node に紐付いている全ての VolumeAttachments を削除して Node にマウントされていたボリュームをアンマウントする。ただ、Node が drain されているかの判断に Node の taint (node.kubernetes.io/unschedulable) を見ており、Karpenter が新しく使う taint を考慮しておらず影響を受けた。AWS EBS CSI driver を 1.29.0 以降に更新すると、AWS EBS CSI driver の Pod が PreStop hook で Node にマウントされているボリュームをアンマウントするかの判断に Karpenter の新しい taint も考慮されるようになるため、正常にアンマウントされる。(kubernetes-sigs/aws-ebs-csi-driver#1969)

Karpenter の Node だと上記の修正を含んだ AWS EBS CSI driver v1.29.0+ に更新しても、ボリュームのマルチアタッチエラーが 6 分間+発生する事象が報告されている。これは Karpenter が EC2 インスタンスを削除するよりも前に (EC2 インスタンスの停止の API が成功したらすぐに) Node オブジェクトから finalizer を削除して Node オブジェクトが消えているからで、AWS EBS CSI Driver の PreStop の処理の中で Node の情報を取得して drain 中かの判断をしているが、Node オブジェクトが見つからず途中でエラーとなり、ボリュームのアンマウントの処理が正常に実行されていないことが原因らしい。(comment - kubernetes-sigs/aws-ebs-csi-driver#1955)

Karpenter 本体の方にリトライ可能なエラーの実装が入り、おそらくこれを使って Karpenter の AWS プロバイダー側で EC2 インスタンスの停止の API を呼び出した後で EC2 インスタンスが停止状態でない場合にリトライ可能なエラーを返し、reconcile の処理を繰り返してインスタンスの状態が停止されるまで待つ予定っぽい。(kubernetes-sigs/karpenter#1164)

こうすることで Node の finalizer が削除されるのが Node (EC2 インスタンス) を完全に停止した後になるので、AWS EBS CSI Driver の PreStop 中には少なくとも Node オブジェクトが消えることはなくなる。Karpenter の開発の人が v0.37.0 で修正を入れる予定と言っているので、それまでは稀に発生しそう。Karpenter の最新バージョンが v0.35 なので v0.36.0 の間違いかと思ったけど、Karpenter 本体に v0.36.0 でリトライ可能なエラーの実装が入り、そこから Karpenter の AWS プロバイダーの実装が入ることになるので v0.37.0 にズレる感じ?

Amazon Linux 2023 での Graceful Node Shutdown の有効化

EKS で Spot インスタンスを利用している場合は、Graceful Node Shutdown を明示的に有効にしないと Node から正常にボリュームがアンマウントされない。
EKS の Node は Graceful Node Shutdown がデフォルトで有効になっておらず、ユーザーデータで明示的に有効にしないといけない。AL2 で Graceful Node Shutdown を有効化する手順は FAQ に記載がある。
AL2023 の場合は、kubelet の設定のカスタマイズの方法が変わっているためユーザーデータの変更が必要で comment - kubernetes-sigs/karpenter#944 に書かれている。

toVersustoVersus

2024/4/12

Kubernetes 1.30 リリース直前でのメトリクスのラベル変更

Kubernetes の API server のメトリクスの apiserver_storage_size_bytes で etcd の ID が入るラベルを cluster にしており、Kubernetes 1.30 でこのメトリクスがアルファから GA に昇格した。Cortex とか Mimir で冗長構成のために複数の Prometheus から同じメトリクスを書き込んで重複排除する時に cluster のラベルを使うらしくて衝突する報告があり、Kubernetes 1.30 のリリースが近いので急いでラベルを変更してマージされた。他のバージョンにも cherry-pick される予定 (kubernetes/kubernetes#124283)

EKS 1.30 以降の組み込みの StorageClass の変更

EKS 1.30 からクラスタ作成時に存在する gp2 タイプの StorageClass から storageclass.kubernetes.io/is-default-class の annotation が消えてデフォルトで使われる StorageClass としてマークされなくなるらしい。既存のクラスタに影響はなく、新規に作成したクラスタのみ影響がある。デフォルトの StorageClass は gp3 タイプかつ allowVolumeExpansion を有効化したやつを新しく作って annotation を差し替えてデフォルトを切り替えたけど、切り替えていなくてデフォルトの StorageClass があることに依存している (PVC で annotation or spec.storageClassName を指定していない) 場合は注意した方が良さそう (comment - aws/containers-roadmap#1330)

EKS 1.30 以降の Node に AZ ID のラベルを追加

少し前に AWS の人が kube-cloud-controller-manager (KCCM) にカスタムのラベルを Node に付与できるようにしたのが Kubernetes 1.30 で使えるようになるので、AZ ID が Node のラベル (topology.k8s.aws/zone-id) に加わる。アカウント毎に AZ 名と物理 AZ がランダムに紐付く概念は Google Cloud や Azure にはない (OCI にはあるらしい) ので、Kubernetes 公式のラベルではない。このラベルを使うことで、複数の AWS アカウントに複数の EKS クラスタがあり、EKS クラスタ間で通信する場合に同じ AZ ID に Pod をスケジュールさせて同一の物理 AZ 間の Pod で通信させたりがやりやすくなる (comment - aws/containers-roadmap#1638)

ベアな EKS クラスタを作成する機能の進捗

VPC CNI とか kube-proxy とか CoreDNS とか余計なものがインストールされていない、コントロールプレーンだけセットアップされた EKS クラスタを作成する機能がそろそろ来るらしい (comment - aws/containers-roadmap#186)

AWS CLI で EKS の利用可能なバージョンを確認する機能

AWS CLI で現在利用可能な EKS クラスタのバージョン一覧を表示する機能を開発中らしい。マイナーバージョン毎に今のプラットフォームバージョンがいくつとか EOL がいつかも見れるみたい (comment - aws/containers-roadmap/#982)

AWS の Cost Explorer で EKS の Pod レベルの課金状況を見る機能

Cost Explorer で Pod (?) のコストを見れるようになる機能を開発中みたい。Namespace でグループ化の Issue が重複でクローズされているから見れるようにもなる感じ?(comment - aws/containers-roadmap#2018)

toVersustoVersus

2024/4/14

ReplicaSet のスケールダウンで Pod 間のスケジュール制約を考慮

sanposhi さんが ReplicaSet controller が PodAffinity や PodTopologySpreadConstraints を考慮して Pod を削除する仕組みの追加を提案している (k/k#124306)

  • ReplicaSet controller が Pod を削除する際に、Pod の起動時間やステータス、再起動の回数などを考慮して削除するが、PodAffinity や PodTopologySpreadConstraints を考慮して Pod を削除しない
  • PodAffinity や PodTopologySpreadConstraints を常に満たした Pod の配置を実現するには Descheduler などを導入する必要がある
  • ReplicaSet controller に ScaleDownPlugin のインターフェイスを生やして、スケールダウンの要素 / 観点毎に plugin を作成して Score 関数を実装する
  • ReplicaSet controller が ReplicaSet 内の Pod をいくつ削除すべきか計算し、各 Score 関数を実行、最も得点の高かった Pod を削除する
    • Score 関数には candidatesToDelete (各 plugin を実行した後の得点を保持) と relatedPods (ReplicaSet に紐づいた Pod 全て) を渡し、Score で得点付けした後の Pod と合計得点を返す
    • 既存のスケールダウンのロジックに関しても ScaleDownPlugin として実装予定
  • PodAffinity の場合は、削除候補の Pod が実行されている Node で PodAffinity と一致する Pod が存在しない場合に高得点にするロジックになる
  • PodTopologySpread の場合は、relatedPods を PodTopologySpreadConstraints のドメイン毎にグループ化し、それぞれのドメイン毎に Pod の合計得点を足し合わせ、各ドメインの合計得点が同じくらいになるように得点を正規化する
    • ドメイン A が 600 点 (PodA: 100, PodB: 200, PodC: 300)、ドメイン B が 300 点 (PodD: 100, PodE: 100, PodF: 100)、ドメイン C が 3000 点 (PodG: 500, PodH: 1000, PodI: 1500) の場合に Pod を 3 つ削除しないといけないとすると、ドメイン C の Pod が 3 つ削除されることになる
    • PodTopologySpread の plugin が得点をドメイン B の 300 点で正規化して、ドメイン A が 300 点 (PodA: 50, PodB: 100, PodC: 150)、ドメイン B が 300 点 (PodD: 100, PodE: 100, PodF: 100)、ドメイン C が 300 点 (PodG: 50, PodH: 100, PodI: 150) となり、ドメイン C の Pod だけが削除されるのを防げる
    • PodC, PodI 以外に 100 点の Pod を 1 つ削除する必要があるので、ドメイン C の Pod が 2 つ削除される可能性はある
  • 現在の実装よりもスケールダウンに時間が掛かるようになるが、スケールダウンの処理が遅れてもそこまで困ることはないはず
toVersustoVersus

2024/4/15

lobuhi/kindscaler

kind で起動した Kubernetes クラスタに後から control-plane と worker ノードを追加・削除するスクリプト

EBS CSI Driver のマルチアタッチの修正の続き

Karpenter と Volume のマルチアタッチエラー で取り上げた件の続報。

EBS CSI Driver の PreStop hook の処理で Node が存在しない場合にエラーを返していた問題は、Node が存在しない時は Node が停止中と判断して VolumeAttachments が削除されるのを待つように修正された。(kubernetes-sigs/aws-ebs-csi-driver#2007) ついでに Cluster Autoscaler の taint が Node に付与されている場合も Node が停止中と判断するようになっている。次のリリースにこの修正が取り込まれる予定。注意点として、この修正により EBS CSI driver の Pod が Karpenter によって drain されなければならない。そうしないと、Karpenter が Node を削除する (finalizer を外す) 前に PreStop hook の処理をトリガーできない。なので、現状のデフォルトで設定されている全ての taints に耐性を持つ tolerations を外す (node.tolerateAllTaints=false にする) 必要がある。

EBS CSI driver が全ての taints に耐性を持つ tolerations がある場合にもこの問題を修正しようと思うと、Karpenter 側で Node を削除する前にボリュームがアンマウントされるまで待つ必要がある。(comment - kubernetes-sigs/karpenter#944)

ボリュームがアンマウントされたかを判断する方法を考えていたら、ちょうど upstream の Kubernetes でも PVC の削除保護の機能で PV が Node からアンマウントされたことを待ってから削除保護を外したいらしく、最初は今の Karpenter と同様に Pod のフェーズが Succeeded or Failed に遷移するのを待っていた。ただ、アンマウントの処理は Pod のフェーズとは関係なく非同期に行われるので、別の方法を考えるべきとなっていた。(comment - k/k#123320)

で、upstream の方は Pod の Condition に新しくボリュームのアンマウントなどが完了したことを知らせる PodTerminated (名前は変わりそう) を追加する KEP-4576: Condition PodTerminated added for pod が上がっていて、これが true となっていたら削除保護を外すようにするみたい。Karpenter / Cluster Autoscaler もこの機能が使えそうだし、KEP のユースケースに挙げてみるのどう?ってコメントしておいた。(comment - kubernetes-sigs/karpenter#944)

toVersustoVersus

2024/4/16

kube-proxy の iptables vs nftables のパフォーマンス比較

アントニオさんによる kube-proxy の iptables モードと nftables モード (アルファ機能) のパフォーマンス比較 (kube-proxy nftables and iptables vs a Service with 100k endpoints)

  • iptables のパフォーマンスの制約の主な原因は以下の 2 つある
    • コネクションを確立するための最初のパケットで iptables のルールを線形探索しないといけない
    • iptables のルールを変更する際に iptables save / restore で iptables の全てのルールの行を扱うことでプログラミングレイテンシが発生する
  • Linux カーネルの開発者は iptables の後継として nftables を開発し、上記で述べたパフォーマンスのボトルネックの改善を目指した
  • 他にも理由はあるものの Kubernetes も KEP-3866: Add an nftables-based kube-proxy backend で kube-proxy の nftables モードを開発している
  • パフォーマンス比較の方法
    • 単一の Service を作成して Endpoints を 100k 手動で紐付け (Pod の作成は不要)、kube-proxy のプログラミングレイテンシを計測する
    • Pod が紐付いた別の Service を作成して、Service 経由でリクエストを投げてこの Servie のルールが最初に作成した Service のルールの後に評価される様子を確認する
    • GCE VM (n2d-standard-48) で kind v0.22.0 で Kubernetes 1.29.2 のクラスタを作成して検証
  • Service に Endpoints を 100k 手動で紐づけるのはセレクタなしの Service を作って 1000 Endpoints を詰め込んだ EndpointSlices を手動で 100 個作成している
  • iptables の場合
    • iptables のプログラミングレイテンシは kube-proxy のログで確認できて iptables restore の処理で 90 秒掛かっており、CPU もフルで消費している
    • 追加で Pod が紐付いた Service を作成して ab で負荷をかけるとタイムアウトが発生した
  • nftables の場合
    • nftables のプログラミングレイテンシも kube-proxy のログで確認できて最大で 11 秒掛かっており、top で CPU 使用率を見ても高くなっている様子はない
    • 追加で Pod が紐付いた Service を作成して ab で負荷をかけても接続確立までに要した時間は 6 ms ± 2.2 ms と影響は見られない
  • Dan さん (kube-proxy の nftables モードの実装者) からの指摘いくつか
    • iptables モードで追加の Service を作成して負荷を掛けた場合の ab のタイムアウトが何か分からないけど、iptables のプログラミングレイテンシである 90 秒間待ってから負荷を掛けた?
    • iptables モードでプログラミングレイテンシに 90 秒掛かっているが、KEP-3453: Minimizing iptables-restore input size が効く状態ならもう少し早くなりそう
    • nftables モードで接続確立の時間に影響はなかったが、iptables モードでもタイムアウトが発生しない状態で実施すれば同じく影響はないはず。Endpoints のルールがいくらあろうが、トップレベルのテーブルの探索 (Service のルール) には影響しないからで、実験するなら 100k Service に 100k Endpoints がぶら下がっている状況の方が良い
    • iptables モードのルールのフル同期で 90 秒と比較しても、nftables モードはまだ部分的な同期などの最適が入っていない状態でプログラミングレイテンシが 11 秒なのはすごく良い

OCI ランタイム仕様での cgroup v1 の非推奨化の議論

OCI のランタイム仕様の方で cgroup v1 の非推奨に向けて足並み揃えようって動きがありますね。Container Plumbing Days で NTT の須田さんが議題に挙げたとか。cgroup v1 の非推奨の発表はいつやるか (Linux ディストリビューションの発表より前かなど)、低レベル・高レベル含めたコンテナランタイム全体で一緒に発表するか、各プロジェクトの非推奨に向けた取り組みはどうなっているかなど確認するみたいです。Kubernetes でも cgroup v1 の非推奨化の動きがあるが、タイミングは異なる可能性もある。NTT の須田さんは cgroup v1 のサポートは 2029 年 (cgroup v1 を使っている各 Linux ディストリビューションの EoL が進んだタイミング) まで少なくとも続け、2030 年以降にユーザーに聞いてどうするか判断するのが良いというスタンスみたい (opencontainers/runtime-spec#1251)

Kubernetes 1.28 + cgroup v2 の memory.oom.group の被害者

また Kubernetes 1.28 + cgroup v2 の memory.oom.group の被害者が... (k/k#117793)

  • Celonis で先週 Kubernetes 1.28 に更新したことで OOM が多発して障害が発生した
  • CPU とメモリ負荷の高いワークロードを動かしていて 10k CPU コアと 80 TiB のメモリを使っている
  • データモデル (> 100k) をインメモリに読み込んでクエリを実行するタイプのワークロードで、Pod 内に管理プロセスがいてデータモデル毎に別プロセスで処理する。複数の Pod のプロセスを管理するオーケストレーターの Pod (?) もいる。
  • Kubernetes 1.28 に更新するまでは、Pod 内の 1 つのプロセスが OOM で死んでもオーケストレーターが別のプロセスをスケジュールし、同一の Pod 内の他のプロセスが提供するデータモデルに影響はなかった
    メモリ効率も高く数万のモデルを数台の Node で動的に提供することができた
  • こんなことしないでプロセスを Pod 単位で起動した方が良いというかもしれないが、100k ものデータモデルを提供するために Pod を 100k 起動するのはリソース効率的にも現実的ではない
  • cgroup v1 に戻るのは長い目で見ると最善の選択ではなく、Kubernetes や systemd、Bottlerocket で cgroup v1 のサポート停止の議論が始まっている
  • 今の設定が大多数にとって嬉しいのは分かるが、これまで動作していたものが動作しなくなるのは問題ではないか
  • kubelet にオプションを追加する案も、コンテナレベルで memory.oom.group を無効化するオプションもリリースからユーザーが利用できるようになるまで時間が掛かる
  • kubelet にオプションを追加しつつ Kubernetes 1.28 や 1.29 に例外的に backport し、コンテナレベルの設定の追加を進めるなど何かしら対応できないか?
toVersustoVersus

2024/4/17

Kubernetes の enforce-mountable-secrets の脆弱性

CVE-2024-3177: Bypassing mountable secrets policy imposed by the ServiceAccount admission plugin

  • Kubernetes の脆弱性報告は Placeholder の Issue を作成して後から詳細を書く形
  • 2024/4/16 に Placeholder の Issue が作成された
  • コードフリーズしているにも関わらず特に説明なくマージされ、既に各バージョンに cherry-pick されているので k/k#124322 関係かなと予想していたら当たった
  • Pod でマウントする Secret を制限する機能が envFrom のバリデーションがなくて参照できちゃってた脆弱性

Kubernetes の cgroup v1 の非推奨化に向けた議論の結末

Kubernetes の cgroup v1 の非推奨化は表現を変えて機能追加を行わないメンテナンスモードに (comment - kubernetes/enhancements#4572)

  • Kubernetes としては古い Linux ディストリビューションの利用者やすぐに cgroup v2 に移行できないユーザーなどを含めた広いユーザー層の互換性を守ることが重要
  • 非推奨化という言葉が混乱を招き、cgroup v1 の機能を継続的にサポートするという意図が伝わりづらい
  • Kubernetes の cgroup v1 サポートに対する機能追加は停止して、想定していた機能追加が完了した状態であるフィーチャーコンプリートに
  • 既存の機能に対するテストは残してリグレッションは検知できる状態にして、何があれば SIG-Node が対応する
  • cgroup v1 絡みのバグ修正はベストエフォートで対応する。脆弱性は優先度を上げて対応するが、影響の大きなバグ修正は SIG-Node 内で相談して取り組むか決める、カーネル側で大きな変更を要するバグは cgroup v1 のままで対応するのが難しいかもしれない
  • SIG-Node としてはフィーチャーコンプリートの状態で十分に時間が経ったあとに正式な非推奨化のアナウンスを別途行う
  • この決断で Kubernetes としては cgroup v2 関連の機能に投資していくという本来の意図が伝わり、cgroup v2 への移行が進むことを期待している
  • ベンダー側も特別対応で cgroup v1 のコードベースを自前でメンテする必要もなくなる
toVersustoVersus

2024/4/18

kube-scheduler の QueuingHints の機能の開発の今後

kube-scheduler の QueuingHints の機能の開発に今後も投資するかどうかの議論が始まりました。(k/k#118893 (comment))

  • QueuingHints は activeQ に Pod を移動するのイベントを Pod の追加とか更新とかの荒い粒度じゃなくて plugin 毎に特定の条件を満たしたイベントに制限する機能
  • SchedulingHints のフレームワークが実装され、現在各 plugin の QueuingHints の実装を進めている
  • PreFilter や Filter を実装した plugin で QueuingHints を実装することになるが、全てのイベントを網羅して実装するのは大変でメンテナンスコストも高い
  • activeQ に無駄に Pod を移動させないことでスループットの向上を目指したが、イベントをフィルタリングする処理が重くパフォーマンスに影響する
  • QueuingHints が何も有効でない場合にメモリ使用量が 1.5 倍になることが観測されている
  • 上記の問題から 1. 機能を削除する 2. QueuingHints のフレームワークに変更を加えてインメモリでのイベントの保持数に上限を設けるなど改善する 3. QueuingHints のフィルタリングの中で複数のオブジェクトを参照するなど複雑な処理をやめさせる、からどうするかを決めたい

Kubernetes 1.30 リリース

Kubernetes 1.30 が予定通りリリースされました。リリーステーマは幸せとか可愛いを表す UwU と Kubernetes を合わせた Uwubernetes。Kubernetes のコントリビュータの多くがお金をもらってやっているのではない。単に楽しいから、問題を解決したいから、何かを学びたいとから、コミュニティが好きだからと理由は様々ある。リリースロゴは、コントリビュータや Kubernetes のリリース作業に関わる人、Kubernetes クラスタを動かしている人に向けた贈り物という意味合いだとか (blog)

Kubernetes 1.30 での client-go の破壊的変更

Kubernetes 1.30 で client-go のleaderelection のパッケージのメトリクスのインターフェイス名に破壊的変更があり、controller-runtime 側でまだ 1.30 対応のリリースがないせいで、downstream のプロジェクトで 1.30 対応できない祭りが起きている (k/k#122069 (comment))

  • 修正の PR が出て新しくインターフェイスを作って元のインターフェイスを wire してるけど、1.30 リリースされたばっかりだしどうなるか (k/k#124372)
  • 何回目かの外部に公開したインターフェイスの破壊的変更なので、そういう変更に対して API レビューを必須にできるように linter か presubmit のジョブで検知して kind/api-change のラベルを付けようとしている (k/k#124380)
toVersustoVersus

2024/4/20

component-base/logs の slog バックエンド

component-base/logs 0.31.0 以降は Go >= 1.21 でビルドした場合 klog のバックエンドとして slog がデフォルトで使われるようになる (k/k#120696)

[Kubernetes 1.31] kube-proxy の nftables モードがベータ昇格予定

Kubernetes 1.31 で kube-proxy の nftables モードがベータに昇格。デフォルトで有効になるが、kube-proxy の --proxy-mode=nftables で指定しないと有効にはならない (k/k#124383)

アントニオさんの Network Policy の参照実装の寄贈

2024/3/31 で紹介したアントニオさんの Network Policy の参照実装の kube-netpol は SIG-Network に寄贈されて予定通り Kubernetes の CI で使われる (kubernetes/org#4856)

toVersustoVersus

2024/4/21

EKS の Access Entry の事前定義ポリシーの改善

EKS の Access Entry の事前定義のポリシーに AmazonEKSAdminViewPolicy が追加されたらしい。既存の AmazonEKSViewPolicy だと Secret などの一部のリソースの読み取り権限がなかったので別で Admin ポリシーが追加された (aws/containers-roadmap#2244 (comment))

[Kubernetes 1.27-1.29] PV の NodeAffinity のバグ

Kubernetes 1.27-1.29 で PV の NodeAffinity に kubernetes.io/hostname のラベルでフィルターを掛けていて、かつ存在しないノード名を含む場合に Pod のスケジュールが必ず失敗するバグ。Kubernetes 1.30 で別の問題を修正したときに、意図せずこの問題も修正されたみたい。あまり使っている人いなさそうだけど (k/k#123465 (comment))

toVersustoVersus

2024/4/22

[Kubernetes 1.31] Service のフィールドセレクタのサポート

Service の Informer cache で .spec.clusterIP.spec.type のフィールドセレクタに対応したので、メモリ使用量を抑えられる。Kubernetes 1.30 で入る予定がテストが Flaky になり revert されたものが 1.31 で入る形。kubelet が Service の環境変数をコンテナに埋め込むために Informer cache を使っており、kube-proxy も Service にラベルを付与するためかな Informer cache を使っている。ただ、どちらも Headless Service の処理では不要なのに無駄に watch していた。大規模クラスタで Kubeflow のジョブを実行した時に大量の Headless Service (10,000+) が作られて API サーバとの通信でのネットワーク帯域を逼迫させたり負荷が掛かっていた。Service type Loadbalancer の場合に LB を作る系のコントローラーも Informer cache で監視する Service を減らせるのでメモリ使用量を減らせる (k/k#123905)

toVersustoVersus

2024/4/23

Descheduling Framework

結構前から議論されてきた Descheduler のフレームワーク化 (Descheduling framework) の話が Descheduler プロジェクト内の KEP に (kubernetes-sigs/descheduler#1372)

  • Descheduler はここ数年広く使われてきて安定してきたが、既存の機能への影響や破壊的変更の懸念などから新しい機能を入れづらくなっている
    • Descheduler の設定は v1alpha1 で破壊的変更は許容できる段階だが、敢えて破壊的変更を避けている
  • 新しい機能の要望やバグ報告が現在活動しているメンテナのキャパを超えており、継続的にコントリビュートしている訳ではないユーザーが実装した新しい機能の面倒をメンテナが見る羽目にもなっている
  • Descheduler を真の意味で安定化させるために、Descheduler を利用可能なコンポーネントの集合からライブラリに昇華させる
    • kube-scheduler の Scheduler Framework の概念を元にしているが、実装に関しては大きく異なる
  • Descheduler のメンテナは Pod の Eviction ロジックを独自に書くフレームワークの開発に集中し、サードパーティの開発者がそれぞれのユースケース毎に機能を実装してメンテできるようにする
    • kube-scheduler の out-of-tree の Scheduler plugin みたいな立ち位置
  • Kubernetes の非推奨化のプロセスに準拠して、フレームワークの開発が既存の Descheduler の機能に影響しない形で進め、Descheduler のコンテナイメージもこれまで通り提供する
  • 現在提案されているユースケースへの対応
    • イベント駆動の Pod の Eviction
      • 現状は Deployment で定期的に Eviction の処理を実行するか、CronJob で定期実行するか
      • イベント駆動でより効率・最適に Pod の Eviction を行いたいが、どのイベントで Eviction を実行するかは機能・戦略による
      • 開発者が自分たちのユースケースにあったイベントで Eviction を実行できるようにフレームワークを作る
    • 独自の Pod の Eviction のロジック
      • 現状は Descheduler 内で Pod や Node をフィルターする処理を持っている
      • フレームワークでは Kubernetes のあらゆるリソースのフィルターやソートの機能を公開する
      • それにより、例えば PVC が紐づいた Pod の Eviction の仕組みはこうするなどカスタマイズできる
    • Descheduler の設定 (Config API) の拡張
      • サードパーティの開発者が実装した機能には挙動を調整するための独自の設定を書けるようにしないといけない
  • Descheduling Cycle の中に拡張点を設けて、plugin 毎に必要な拡張点を実装する形
    • Scheduling Framework と同じで拡張点を実装しない選択も取れる
  • 拡張点は現在、高レベルな Deschedule / Balance と低レベルな PreSort / Filter / Sort を設ける予定
    • 高レベルな拡張点の中で低レベルな拡張点が実行される
    • 高レベルな拡張点
      • Deschedule: 各 Pod を独立で処理して Evict する Pod を決める拡張点
      • Balance: 2 つ以上の Pod を考慮して Pod の配置を調整する拡張点
    • 低レベルな拡張点
      • PreSort: 高レベルな拡張点の処理の最初で Pod をソートする拡張点
      • Filter: Evict する直前に 候補の Pod をフィルタリングする拡張点 (Pod をいつ Evict するかを決める)
      • Sort: Evict する前に Evict 対象の Pod をソートする拡張点
  • Descheduling Cycle は Deschedule -> Balance の順番で固定
    • Deschedule / Balance の中に PreScore / Filter / Sort 拡張点がある (実装しない選択も取れる)
    • Descheduler Plugin は Deschedule / Balance のどちらかを実装 or 両方実装するパターンもあり
  • 既存の Descheduler で実装されている戦略とのマッピング
    • Deschedule: RemoveFailedPods, RemovePodsViolatingNodeAffinity, RemovePodsViolatingNodeTaints, RemovePodsViolatingInterPodAntiAffinity, RemovePodsViolatingInterPodAntiAffinity, RemovePodsHavingTooManyRestarts
    • Balancer: RemoveDuplicatePods, RemovePodsViolatingTopologySpreadConstraint, LowNodeUtilization, HighNodeUtilization
  • Descheduling Profile は対象の Pod を変えたり (e.g. 特定の namespace やラベルセレクタ)、同一の戦略でも plugin の設定を変えて、複数回実行できる最小単位
    • kube-scheduler の Scheduling Profile では Pod の .spec.schedulerName でどの scheduler (Profile) を使うか選択できるが、Descheduling Profile を Pod 単位で設定はできないので、対象の Pod を変えるのは Descheduling Profile の設定の中で変えるしかない
  • Descheduling Cycle の処理の流れ
    • Descheduler Cycle の中で Deschedule / Balance それぞれのプロファイルに Node の一覧を渡す
    • Deschedule のプロファイルを全て実行してから Balance のプロファイルを実行する
    • Evict 対象の Pod が選出されたらなる早で Evict する
    • Descheduling Cycle 毎に Evict された Pod の数を追跡しているので、Evict の上限の Pod 数が設定されている場合にその数に到達したら Descheduling Cycle を早めに終わることもある
    • 指定するプロファイルの順番は Evict したい Pod の優先度で指定する必要がある
  • DeschedulerPolicy でプロファイルを指定する
    • KubeSchedulerConfiguration に設定の記述の方法は似ている
  • KEP-4563: Evacuation API との連携も視野に入れている
toVersustoVersus

2024/4/24

FeatureGate をどの段階から始めるかの指標

Kubernetes で稀にある FeatureGate で Alpha をスキップして Beta から始まる変更の判断基準の言語化 (kubernetes/community#7828)

  • API の変更を含む機能は必ず Alpha -> Beta -> GA の段階を踏むこと
  • やりたいことを実現できるか不明な場合やすごく複雑な場合、不具合やエッジケースのリスクがある場合、パフォーマンスやスケーラビリティに関する影響がある場合は Alpha -> Beta -> GA の段階を踏むべき
  • 可能な限り複雑さを減らし、パフォーマンスやスケーラビリティへの影響も抑えてはいるが、とはいえ重大なリスク (e.g. ユーザー影響のある挙動の変更やエッジケース) を伴う場合は、Alpha を飛ばして Beta から始めても良い (Beta の品質を満たしているなら) が、大規模な本番環境での実績やさまざまな使われ方をして問題がないことが確認できるまではデフォルトで無効にすべき
    より一般化すると、以前動いていた機能が場合によっては動かなくなる可能性があるなら、デフォルトで機能を無効にすべき
  • 変更箇所は小さくリスクも少ないが、新しい設定オプションを追加せずに (互換性の観点から設定オプションを追加してしまうと非推奨化と削除が面倒になる) Feature Gate を使って機能を無効化できるようにしたい場合は Alpha を飛ばして Beta から始まっても良く (Beta の品質を満たしているなら)、最初からデフォルト有効でも良い
  • ある程度のリスクを孕むバグの修正で Feature Gate で無効化できるようにしたい場合は、Feature Gate が Beta から始まり最初からデフォルト有効を推奨する。一方で、バグ修正により機能が"削除"された (=挙動が変更された) と捉えられる可能性がある場合は機能の非推奨化を進めることも選択肢の一つだが、どちらにしろバグ修正を無効化できるようにすることが重要
toVersustoVersus

2024/4/25

ExexProbe のタイムアウトが効かないことがある問題

以下の例だと 5 秒経過してもタイムアウトにならずに 45 秒待ってしまう (containerd/containerd#10094 (comment))

  • ExecProbe は containerd だと ExecSync の中で setns でコマンドを実行する
  • setns で実行したコマンドの結果は標準出力に書き込まれるが、setns から shim までは pipe でデータを流し、shim から CRI plugin までは FIFO (名前付きパイプ) でデータを流す
  • containerd としては標準出力に書き込んだログを取りこぼしたくないので、pipe を通して書き込む側が pipe をクローズするまでは待つようになっている。pipe がクローズされると shim の読み取り側が EOF を受け取り、FIFO もクローズする
  • setns で実行したプロセスは子プロセスを持つ可能性があり、以下の例だと sleep 45 がそれに当たる
  • sub-cgroup が設定されていないので子プロセスの状態を全て追跡できず、ExecProbe がタイムアウト時間を過ぎると setns の親プロセスである sh は殺されるが、sleep は殺せずに残る。それにより pipe もクローズできずに掴み続け、45 秒経過するまで待ってしまう
  • sub-cgroup を導入する以外に良い方法がないが、containerd には drain_exec_sync_io_timeout という設定がありこれを良い感じの時間に設定することで子プロセスが処理を終えるのを待つ必要がなくなる
      readinessProbe:
        timeoutSeconds: 5
        exec:
          command: ['sh', '-c', 'date >> /probe/readiness-log.txt && sleep 45']
toVersustoVersus

2024/4/26

kubernetes-sigs/secrets-store-sync-controller

SIG-Auth が新しく kubernetes-sigs/secrets-store-sync-controller のリポジトリを作ろうとしている (kubernetes/org#4902)

  • Secrets Store CSI Driver には外部のシークレット管理サービスから秘密情報を Kubernetes の Secrets に同期する機能がある
    • 設計思想的に Pod にマウントした秘密情報を Secret に同期する必要があって、Pod を作らないと Secret に同期できないという制約から使いづらい
    • kubernetes-sigs/secrets-store-csi-driver#298 で Issue も上がっていて要望も多いが、Secrets Store CSI Driver が生まれた背景的に Secret を介さずに tmpfs としてマウントした秘密情報を Pod がファイルや環境変数から読み込めるというのがあるので難しい
  • Secrets Store CSI Driver のスコープから外れているので、プロジェクトは分離してコードは一部共有する形で Secret に同期するコントローラーを開発する流れっぽい?
  • 新しく SecretProviderClass と SecretSync のカスタムリソースが追加される
    • SecretProviderClass に外部のシークレット管理サービスの provider 名や固有のパラメータを指定する
    • SecretSync に実際に作成する Secret の情報を記載する
      • Secret の spec が埋め込まれていて、外部のシークレット管理サービスからフェッチしてくる時の権限を付与した Service Account の指定やどの SecretProviderClass を利用するかも指定する
  • 対応するシークレット管理サービスの provider は選択できて、Secrets Store Sync controller の sidecar として起動する感じ?
  • SIG-Auth が開発するのでセキュリティ的な懸念とかちゃんと考慮されるだろうし、コントローラーの質も高くはなりそうだけど、External Secrets Operator がいる中でどれくらい普及するかな...

Argo CD の Ignore Difference の機能の DoS 脆弱性

Argo CD の Application の Ignore Differences の機能で jqPathExpressions を指定している場合に、悪意のある条件を書くと OOM させることができる脆弱性が見つかっている。Argo CD v2.10.8, v2.9.13, v2.8.17 で修正済み (GHSA-9m6p-x4h2-6frq)

  • until で絶対一致しない条件で loop させてリストを徐々に増やしていってじわじわ殺すの面白い。
  • Argo CD 側の修正としては jqPathExpressions の評価にタイムアウト値を儲けてデフォルト 1 秒を超えるとエラーを返すようにしている。
ignoreDifferences:
- group: apps
  kind: Deployment
  jqPathExpressions: 
  - 'until(true == false; [.] + [1])'
toVersustoVersus

2024/4/27

addon-resizer をコントロールプレーンで動かすモード

GKE の metrics-server のサイドカーとしてデプロイされている addon-resizer (a.k.a. nanny) をコントロールプレーンで動かせるようにする変更 (kubernetes/autoscaler#6764)

  • セキュリティを堅牢にするために GKE のコントロールプレーンのノードで addon-resizer を動かしたい
  • Kubernetes API サーバの in-cluster の認証情報以外に kubeconfig を渡せるようにしているのとリーダー選出の機能が入っているのと ConfigMap から addon-resizer の設定を読み込めるようにしている
  • --run-on-master (名前は変わりそう) のフラグを指定するとコントロールプレーンで動作するようになる
    • フラグの説明文に思いっきり GKE って書くのどうなの...
    • Whether the addon-resizer is running on GKE master VMs.

  • リーダー選出で RunOrDie を使っているので にリーダー選出に失敗すると死ぬ形になっていてコントロールプレーンのノードで CrashLoopBackoff するのどうなのって言われているけど、社内の例に従って実装しているって言ってて気になる
    • GKE のコントロールプレーンのコンポーネントは kubelet の Standalone モードで動いているからプロセスが停止すると再起動されちゃうはず
  • addon-resizer が暴走して CPU 使用率が 100% に張り付くみたいなこともあったし、コントロールプレーンに行ってくれるなら嬉しい
toVersustoVersus

2024/4/29

Pod のリソース要求を計算する関数の外部公開

Pod のリソース要求を計算する関数を component-helper に移して外部公開して、downstream のプロジェクトで利用できるようにする動きがある。kubectl や LimitRange の Admission Controller でも同じ関数のコピーを自分たちで管理している。最近だと Sidecar container の追加でリソース割り当ての計算方法が変わったり、downstream で同じ関数をメンテするのは大変だからライブラリ化しておきたい (k/k#124537)

WG-Serving の最初の定例ミーティング

https://www.youtube.com/watch?v=Ri4rQNoRBko

  • serving ワークロードの定義は?
    • Pod の restartPolicy が Always の場合は serving ワークロード、restartPolicy が OnFailure or Never の場合は batch ワークロード
    • restartPolicy が Never の Pod で inference ワークロードを動かしている場合や StatefulSet で batch ワークロードを動かしている場合もあるので 一概にそうと言えないこともあるが簡潔に違いを表すなら上記の定義
  • KServe などのプロジェクトと協力して Kubernetes 上で inference ワークロードを動かすための標準化を進めるか StatefulSet の成功 (StatefulSet に改善を加えることで Kubernetes 上でデータストアを動かす Operator がたくさん生まれた) のように inference ワークロードを動かす上での運用上の懸念などを標準化するか
    • 1 つの Operator が全てのユースケースを満たせる訳もなく、inference ワークロードはこう動かすものみたいな押し付けもやりたくない
    • 設定とコードの分離による ConfigMap のロールアウトの仕組みはいろいろとあったり、Gateway API のような緩い標準化 (Gateway API 以外の選択も取れる) など選択の自由が重要
  • スケジューラーだと Volcano や Kueue などそれぞれが独自の概念を導入しており、標準化されたインターフェイスがないのでプラットフォームに取り込むのが大変だったので、WG-Serving はまずインターフェイスやコンポーネントを標準化して欲しい
    • コンセンサスを取りながら標準化を進めてみても良いが、Kueue が Kubernetes 上になかったキューイングの仕組みを作って他のプロジェクトが連携したように、Kaito の PreSet や KServe の ServingRuntime が連携できる低レイヤーの何かを作るのもアリ
    • WG-Batch は低レイヤーな Job API を改善して Kueue をその上に作った。経験上、上のレイヤーに行けば行くほどコンセンサスを取りづらくなるので、他のプロジェクトが組み合わせを考えられるような基本要素を作ることと LeaderWorkerSet (LWS) のような一部のユースケースを満たすものをその上に作ってあげるのが良さそう
    • 高レイヤーなところでの標準化よりは低レイヤーな基本要素を作る方がコンセンサスは得やすいし、複雑なユースケースにも対応しやすい
    • Deployment や StatefulSet や HPA などの既存の基本要素の改善とモデルの提供やトラフィックの振り分けなどを実現できる基本要素を新しく作る
    • HPA に CPU やメモリ以外に GPU を指標として使えるようにしたり、inference ワークロードと Web アプリケーションの違いとして inference ワークロードは負荷が高ければ高いほどレイテンシが改善する傾向にあるのでゆっくりスケールする仕組みのフィードバックはできそう
  • WG-Device-Management としては DRA に既存の Claim ベースの厳密なリソース要求の仕組み以外にも、スペックの高い GPU が 1 つもしくはスペックの低い GPU を複数欲しいみたいな優先順位を要求して使えるような仕組みも考えている。パフォーマンスが少し落ちても問題ないから難しいことは考えずにとにかくワークロードを動かしたい人向けの UX の改善?
toVersustoVersus

2024/4/30

KEP-4603: Tune CrashLoopBackoff

  • Google の人 (SIG Multi-cluster の人🤔) が予告通り KEP を上げて、Kubernetes 1.31 でアルファ機能入りを目指すみたい
  • CrashLoopBackoff は起動時や実行中に問題の起きたコンテナを再起動する間隔を緩めて kubelet に負荷を掛けないようにする仕組み
  • コンテナを再起動するまでの時間は回数毎に Exponential back-off で増えて (e.g. 10s -> 20s -> 40s, ...) いき、5 分が上限となっている
  • コンテナが起動に成功した後に 10 分間何も問題がなければ Exponential back-off の時間はリセットされる
  • 解決したいユースケースとして Agones の GameServer と AI / ML のバッチ処理を挙げている (Google が推してる 2 つの領域だから解決したいのかな)
    • Agones でゲームセッション (e.g. マルチプレイのサーバのプロセス) を再作成 (= Pod の再作成) はコストが高いので、Pod の中でメインのプロセス (= コンテナ) を再起動して効率的にゲームセッションを再利用したい
    • GameServer (Pod) の中から Agones SDK の Shutdown を実行しちゃうと Pod の再作成からになるので、新たに Agones SDK に Restart を用意してプロセスを再起動できるようにしたいが、 CrashLoopBackoff になるとバックオフ時間待たされて即座に再起動できない
    • AI / ML のバッチ処理でも同様に複数の Pod を起動して並列処理を実行した時に、コードの問題ではなくインフラ側の問題 (e.g. livenessProbe の一時的な失敗) でコンテナが再作成されると、すぐに処理を再開したいのにバックオフ時間待たされる可能性がある
    • ネットワークや GPU などの断続的な問題によりコンテナが再起動を繰り返すことがあるので、処理の再開に最長の 5 分待たされることはありうる
    • Istio やログ転送などのサイドカーコンテナでも同様に早く再起動して処理を再開したいケースはある
  • Pod の再起動時に kubelet がやること
    • コンテナイメージを再度ダウンロードし直す可能性 (ネットワーク帯域やディスク IO への負荷、他のイメージのダウンロードの阻害)
    • コンテナランタイム経由で古いコンテナを削除する
    • 必要なら秘密情報や設定を再度ダウンロード
    • コンテナランタイム経由でコンテナを再作成する
    • コンテナが起動するまで startupProbe を実行する (readinessProbe より高頻度に実行される可能性があり、kubelet に負荷が掛かる)
    • アプリケーションの起動処理 (IO に負荷が掛かりやすい)
    • コンテナの起動に関わるログの書き込み (ディスク IO への負荷と大量のログの書き込み)
  • 起動失敗の理由によってコンテナ単位でバックオフの挙動を上書きできるようにし、Node の安定性を維持できる経験的に安全なデフォルト値も用意する予定
    • コンテナ単位での設定に関しては大多数のワークロードが設定を変更する必要がないデフォルト値を用意し、かつシンプルな UX にする予定
    • 元々の目的である Node の安定性を維持できるように完全にユーザーがカスタマイズできないようにする
    • 上書き可能になる予定の起動失敗の理由は以下の通り
      • コンテナイメージのダウンロードに失敗した
      • プロセスが exit code 0 以外で終了した
      • livenessProbe の失敗や OOMKill、kubelet のランタイム側の問題で再起動された
      • プロセスが exit code 0 で正常終了した
  • 実装の詳細はまだ書かれていないのでここまで
toVersustoVersus

2024/5/1

Kubernetes のバージョンスキューポリシーの誤った解釈

Kubernetes のバージョンスキューポリシーでは、kube-controller-manager も kube-scheduler も kubelet や他のコンポーネントも Aggregated API server (e.g. metrics-server) でさえも kube-apiserver のバージョンを超えて動作は保証されていない。バージョン更新時に kube-apiserver は新しいバージョンの kube-apiserver とやり取りすることがある (e.g. FlowControl, Admission Webhook) ので例外的に -1 のスキューが保証されている。Kubernetes のクライアントライブラリを 1.30 に更新したコントローラーが 1.29 の kube-apiserver で動作が保証されている訳ではない。報告だと Custom Metrics の Adapter を書くためのライブラリが Kubernetes クライアントのバージョンを 1.29 に更新し、Prometheus Adapter がライブラリのバージョンを上げ、Kubernetes 1.28 にデプロイしたら動作しなくなった。Kubernetes 1.28 には API Priority & Fairness (APF) で使う FlowControl の v1 リソースがない(APF は Kubernetes 1.29 で GA) にも関わらず、Aggregated API server のライブラリが FlowControl v1 に依存するようになり起動できなくなった感じ (k/k#124533)

toVersustoVersus

2024/5/2

GKE が Kubernetes 1.30 をサポート開始

GKE の Rapid channel に 1.30 がきてた。Kubernetes の upstream での 1.30 のリリースが 4/17 なので 2 週間遅れ。相変わらずメジャークラウドの中だと最速 (relase notes)

Helmfile v1.0.0 への動き

久々に Helmfile v1.0.0 への動きがあり、(v1.0.0-rc.0) がリリースされた。このまま次のリリースで v1.0.0 に行くのかな?以前予定していた Helmfile 1.0 での破壊的変更

toVersustoVersus

2024/5/3

GKE での RDMA 対応の動き

GKE の Pod に RDMA 対応の NIC を刺せるようになりそう。Pod のマルチネットワークとセットかな。AI / ML で複数 Pod で分散処理するときのネットワーク通信を高速化したいとか (kubernetes/cloud-provider-gcp#681)