Istio における Kubernetes ネイティブサイドカー
Istio での新しい SidecarContainers 機能のデモ。
サービスメッシュについて何か聞いたことがあるなら、それはサイドカーパターンを使って動作することでしょう。プロキシサーバーがアプリケーションコードと一緒にデプロイされます。サイドカーパターンはまさにそれ、パターンです。今まで、Kubernetes ではサイドカーコンテナに対する正式なサポートはまったくありませんでした。
これにより、多くの問題が発生しました。設計上終了するジョブがあるが、サイドカーコンテナは終了しない場合はどうでしょうか?この正確なユースケースは、Kubernetes の Issue トラッカーで最も人気のあるものです。
Kubernetes にサイドカーのサポートを追加する正式な提案は 2019 年に提起されました。多くの停滞と開始を経て、昨年プロジェクトが再開された後、サイドカーの正式なサポートが Kubernetes 1.28 でアルファ版としてリリースされます。Istio はこの機能のサポートを実装しており、この記事では、その利用方法を学ぶことができます。
サイドカーの悩み
サイドカーコンテナは多くの機能を提供しますが、いくつかの問題も伴います。ポッド内のコンテナはいくつかのものを共有できますが、そのライフサイクルは完全に切り離されています。Kubernetes にとって、これらのコンテナは両方とも機能的に同じです。
しかし、Istio では同じではありません。Istio コンテナはプライマリアプリケーションコンテナを実行するために必要であり、プライマリアプリケーションコンテナなしでは価値がありません。
この期待のミスマッチは、さまざまな問題を引き起こします。
- アプリケーションコンテナが Istio のコンテナよりも早く起動した場合、ネットワークにアクセスできません。これは、Istio の GitHub で 圧倒的に最も多くの +1 を獲得しています。
- Istio のコンテナがアプリケーションコンテナよりも前にシャットダウンした場合、アプリケーションコンテナはネットワークにアクセスできません。
- アプリケーションコンテナが意図的に終了した場合 (通常は
Job
で使用される場合)、Istio のコンテナは引き続き実行され、ポッドを無期限に実行し続けます。これも、GitHub の上位の問題です。 - Istio のコンテナが起動する前に実行される
InitContainers
は、ネットワークにアクセスできません。
これらの問題を回避するために、Istio コミュニティ内外で数え切れないほどの時間が費やされてきましたが、成功は限定的でした。
根本原因の解決
Istio のますます複雑化する回避策は、Istio ユーザーの苦痛を軽減するのに役立ちますが、理想的には、これらすべてが機能するはずです。そして、Istio だけではなく、Kubernetes コミュニティは、これらを Kubernetes で直接解決するために懸命に取り組んできました。
Kubernetes 1.28 では、サイドカーのネイティブサポートを追加する新機能がマージされ、5 年以上にわたる継続的な作業が完了しました。これがマージされたことで、すべての問題を回避策なしで解決できます!
「GitHub Issue ホールオブフェイム」では、これら 2 つの Issue は、Kubernetes での全期間の Issue の #1 および #6 に相当し、ついに解決しました!
これを完了させるために貢献した多くの個人に特別な感謝を申し上げます。
試してみる
Kubernetes 1.28 がリリースされたばかりですが、新しい SidecarContainers
機能はアルファ版 (したがって、デフォルトではオフ) であり、Istio でのこの機能のサポートはまだ出荷されていません。それでも、今日試すことはできます。ただし、実稼働環境では試さないでください!
まず、SidecarContainers
機能が有効になっている Kubernetes 1.28 クラスターを起動する必要があります。
$ cat <<EOF | kind create cluster --name sidecars --image gcr.io/istio-testing/kind-node:v1.28.0 --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
SidecarContainers: true
EOF
次に、最新の Istio 1.19 プレリリースをダウンロードできます (1.19 はまだリリースされていないため)。ここでは Linux を使用しました。これは Istio のプレリリースであるため、繰り返しますが、実稼働環境では試さないでください!Istio をインストールする際に、ネイティブサイドカーサポートの機能フラグを有効にし、後でデモを支援するためにアクセスログをオンにします。
$ TAG=1.19.0-beta.0
$ curl -L https://github.com/istio/istio/releases/download/$TAG/istio-$TAG-linux-amd64.tar.gz | tar xz
$ ./istioctl install --set values.pilot.env.ENABLE_NATIVE_SIDECARS=true -y --set meshConfig.accessLogFile=/dev/stdout
そして、最後にワークロードをデプロイできます。
$ kubectl label namespace default istio-injection=enabled
$ kubectl apply -f samples/sleep/sleep.yaml
ポッドを見てみましょう。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
sleep-7656cf8794-8fhdk 2/2 Running 0 51s
一見するとすべて正常に見えます... しかし、内部を見ると魔法を見ることができます。
$ kubectl get pod -o "custom-columns="\
"NAME:.metadata.name,"\
"INIT:.spec.initContainers[*].name,"\
"CONTAINERS:.spec.containers[*].name"
NAME INIT CONTAINERS
sleep-7656cf8794-8fhdk istio-init,istio-proxy sleep
ここでは、ポッド内のすべての containers
と initContainers
を見ることができます。
驚き! istio-proxy
が initContainer
になりました。
より具体的には、restartPolicy: Always
が設定された initContainer
です (SidecarContainers
機能によって有効になる新しいフィールド)。これにより、Kubernetes はそれをサイドカーとして扱うようになります。
これは、initContainers
のリストの後続のコンテナ、およびすべての通常の containers
は、プロキシコンテナの準備が整うまで起動しないことを意味します。さらに、プロキシコンテナがまだ実行されている場合でも、ポッドは終了します。
Init コンテナのトラフィック
これをテストするために、ポッドに実際に何かを実行させてみましょう。ここでは、initContainer
でリクエストを送信する単純なポッドをデプロイします。通常、これは失敗します。
apiVersion: v1
kind: Pod
metadata:
name: sleep
spec:
initContainers:
- name: check-traffic
image: istio/base
command:
- curl
- httpbin.org/get
containers:
- name: sleep
image: istio/base
command: ["/bin/sleep", "infinity"]
プロキシコンテナをチェックすると、リクエストが成功し、Istio サイドカーを介して渡されたことがわかります。
$ kubectl logs sleep -c istio-proxy | tail -n1
[2023-07-25T22:00:45.703Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 1193 334 334 "-" "curl/7.81.0" "1854226d-41ec-445c-b542-9e43861b5331" "httpbin.org" ...
ポッドを調べると、サイドカーが check-traffic
initContainer
の前に実行されるようになっていることがわかります。
$ kubectl get pod -o "custom-columns="\
"NAME:.metadata.name,"\
"INIT:.spec.initContainers[*].name,"\
"CONTAINERS:.spec.containers[*].name"
NAME INIT CONTAINERS
sleep istio-init,istio-proxy,check-traffic sleep
ポッドの終了
以前に、アプリケーションが終了した場合 (Jobs
で一般的)、ポッドは永遠に生き続けると述べました。幸い、これも解決しました!
まず、1 秒後に終了し、再起動しないポッドをデプロイします。
apiVersion: v1
kind: Pod
metadata:
name: sleep
spec:
restartPolicy: Never
containers:
- name: sleep
image: istio/base
command: ["/bin/sleep", "1"]
そして、その進行状況を監視できます。
$ kubectl get pods -w
NAME READY STATUS RESTARTS AGE
sleep 0/2 Init:1/2 0 2s
sleep 0/2 PodInitializing 0 2s
sleep 1/2 PodInitializing 0 3s
sleep 2/2 Running 0 4s
sleep 1/2 Completed 0 5s
sleep 0/2 Completed 0 12s
ここでは、アプリケーションコンテナが終了し、その後すぐに Istio のサイドカーコンテナも終了することがわかります。以前は、ポッドは Running
のままになっていましたが、現在は Completed
に移行できます。もうゾンビポッドはありません!
アンビエントモードはどうですか?
昨年、Istio はアンビエントモードを発表しました。これは、サイドカーコンテナに依存しない Istio の新しいデータプレーンモードです。では、アンビエントモードが登場すると、これらはすべて意味がなくなるのでしょうか?
私は断固として「はい」と言います!
ワークロードにアンビエントモードが使用されると、サイドカーの影響は軽減されますが、大規模な Kubernetes ユーザーのほぼすべてがデプロイメントに何らかのサイドカーを使用していると予想されます。これは、アンビエントに移行したくない Istio ワークロード、まだ移行していないワークロード、または Istio に関連しないものの場合があります。したがって、これが重要となるシナリオは少なくなる可能性がありますが、サイドカーが使用される場合は、それでも大きな改善です。
逆のことを疑問に思うかもしれません。サイドカーの悩みがすべて解決した場合、なぜアンビエントモードがそもそも必要なのでしょうか?サイドカーの制限が解決されても、アンビエントには依然としてさまざまなメリットがあります。たとえば、このブログ記事では、プロキシをワークロードから分離することが有利である理由について詳しく説明しています。
自分で試してみる
冒険好きな読者の皆様には、テスト環境で自分でこれを試してみることをお勧めします!これらの実験的およびアルファ機能のフィードバックは、それらが安定しており、プロモーションする前に期待を満たしていることを確認するために重要です。試してみたら、Istio Slack で感想をお聞かせください!
特に、Kubernetes チームは次の点についてさらに詳しく知りたいと考えています。
- シャットダウンシーケンスの処理。特に複数のサイドカーが関与している場合。
- サイドカーコンテナがクラッシュしている場合のバックオフ再起動処理。
- まだ考慮されていないエッジケース。