GKE AutopilotにOSS版Istioはインストールできない...と思われた。だが...!
はじめに
GKE Autopilotは、Google Cloudが提供するマネージドKubernetesサービスの一つです。さまざまなセキュリティのベストプラクティスが自動で適用されており、特別な設定をしなくても安全にコンテナを運用できる環境を提供しています。
このような環境下でサービスメッシュを構築する際は、Istio互換のCloud Service Mesh(旧Anthos Service Mesh)を使用するのが一般的です。マネージドサービスとして提供されるため、運用負荷が軽減され、多くのメリットがあります。
一方で、互換性の確保や技術検証のために、オープンソース版のIstioを直接使いたいケースもあるでしょう。しかし、GKE Autopilotの制約のため、普通にインストールすると失敗してしまいます。本記事では、GKE AutopilotにOSSのIstioをインストールする方法について解説します。
素直にistio installすると
まず、通常の方法でIstioをインストールしようとすると、以下のようなエラーが発生します。
$ istioctl install
...
✘ CNI encountered an error: failed to update resource with server-side apply for obj ConfigMap/kube-system/istio-cni-config: configmaps "istio-cni-config" is forbidden: User "XXXXXXXXXX" cannot patch resource "configmaps" in API group "" in the namespace "kube-system": GKE Warden authz [denied by managed-namespaces-limitation]: the namespace "kube-system" is managed and the request's verb "patch" is denied
このエラーは、Istioのインストーラがkube-system
namespaceに対して、istio-cni-config
というConfigMapを作ろうとして拒否されたことを示しています。これは、GKE Autopilotではkube-system
namespaceをユーザが操作できないためです。
なお、このConfigMapを別のnamespaceに作成するように設定することもできますが、それだけだとやはり最終的にはインストールは失敗してしまいます。
どうすればいいか
以下の手順を実行する必要があります。
1. NET_ADMIN capabilityを有効にする
NET_ADMIN
capabilityを持つコンテナを作成できるよう、クラスタを更新します。GKE Autopilotの作成時や更新時に以下のフラグを付与することで設定できます。
--workload-policies=allow-net-admin
詳細: https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-security#autopilot-pss
ちなみにこのステップを飛ばすとIstioのインストール自体は成功するかもしれませんが、istio proxyの挿入が失敗します。Podの作成時に以下のようなエラーが発生します。
Error creating: admission webhook "warden-validating.common-webhooks.networking.gke.io" denied the request: GKE Warden rejected the request because it violates one or more constraints.
Violations details: {"[denied by autogke-default-linux-capabilities]":["linux capability 'NET_ADMIN' on container 'istio-init' not allowed; Autopilot only allows the capabilities: 'AUDIT_WRITE,CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,MKNOD,NET_BIND_SERVICE,NET_RAW,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT,SYS_PTRACE'."]}
Requested by user: 'system:serviceaccount:kube-system:replicaset-controller', groups: 'system:serviceaccounts,system:serviceaccounts:kube-system,system:authenticated'.
2. カスタムのoperator.yamlを作成する
次に、以下の内容でoperator.yaml
を作成します。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
cni:
enabled: false
3. カスタム設定を使用してIstioをインストールする
作成した設定ファイルを使用して、Istioをインストールします。
$ istioctl install -f operator.yaml
こうすると、最初のセクションで失敗原因となっていたistio-cni-config
ConfigMap自体作られなくなり、インストールは成功します。
なぜこうなるのか
Istioはサービスメッシュとして動作するために、基本的に各Podにサイドカーコンテナ(istio-proxy)を挿入します。このサイドカーは、Podの全てのネットワークトラフィックを傍受して、ルーティングや認証などの機能を提供するものです。
この挙動を実現するためには、Pod内のアプリケーションが送受信するすべてのトラフィックを自動的にサイドカーへリダイレクトする仕組みが必要になります。この設定を行うために、Istioでは主に2つの方法が提供されています。
1. istio-initコンテナを使う方式
Podが起動する際に、istio proxyと共にistio-initというinitコンテナが挿入されます。このinitコンテナはPod内のネットワーク設定を変更し、すべてのトラフィックがistio-proxyを経由するようにiptablesルールを設定します。
この処理にはNET_ADMIN
とNET_RAW
というcapability が必要となるため、すべてのPodに特権的なinitコンテナが必要になるというセキュリティ上の欠点があります。
なお、以前のバージョンではistioctl install
した際にデフォルトで選択される方式だったため、古いブログなどはこちらを前提にして書かれているものがあったりします。
2. CNI node agentを使う方式
1.のセキュリティ上の懸念に対して新しく実装されたのがこちらの方式です。この方式では、クラスタの各ノードにDaemonSetとしてCNI node agentが配置されます。このエージェントは、クラスタのCNIプラグインを拡張し、Podが作成されるタイミングでトラフィックをistio-proxyへ自動的にリダイレクトするよう設定します。
この方式はメッシュ内の全てのPodに特権的なinitコンテナを追加する必要がなくなる一方で、CNI node agent自体がNET_ADMIN
、NET_RAW
に加えて、CAP_SYS_ADMIN
capabilityを要求するようになります。
Istio 1.24時点では、istioctl install
を実行した際にデフォルトで選択される方式です。
https://istio.io/latest/docs/setup/additional-setup/cni/ より抜粋
さて、GKE Autopilotでは、NET_ADMIN
capabilityはオプトインで使用可能になりますが、CAP_SYS_ADMIN
capability は使用できません。
そのため、CNI node agentをオプトアウトし、istio-initコンテナを使う方式を採用する必要があります。上述したようにこちらの方式はセキュリティ上の弱みがあるので、それを理解しつつ使うのが重要です。
AIで生成したまとめ
GKE AutopilotでオープンソースのIstioを使用するには、以下の点に注意が必要です:
- クラスタに
NET_ADMIN
capability を付与する - CNI機能を無効にしたカスタム設定を使用し、istio-initコンテナ方式でサイドカー挿入を行う
この方法により、GKE Autopilotの制約の中でもIstioを正常に動作させることができます。マネージドサービスであるCloud Service Meshを使用するのも良い選択肢ですが、技術検証や特定のIstioバージョンを必要とする場合は、上記の手順を参考にしてください。
使用するアプローチはプロジェクトの要件に応じて選択してください。Cloud Service Meshが提供する運用の簡便さを求めるなら、マネージドサービスを選択するのが良いでしょう。一方、特定のIstioバージョンや機能が必要な場合は、本記事で紹介した方法でOSSのIstioを導入することができます。
最後に
docsに言及がなかったのでcontributionして徳を積みました
Discussion