こんにちは。X(クロス)イノベーション本部クラウドイノベーションセンターの柴田です。
この記事は 電通国際情報サービス Advent Calendar 2022 の5日目の投稿です。 前日の記事は宮澤さんの「お金をかけずにAWS Certified SysOps Administrator - Associateに合格した話」でした。
さて、この記事ではArgo CDを使ってIstioをバージョンアップする方法を紹介します。
はじめに
Istioとは
サービスメッシュとは、マイクロサービスにおけるトラフィック管理、可観測性、セキュリティなどを、インフラストラクチャレイヤーで透過的に実現する仕組みです。
サービスメッシュがどんな課題を解決するものかは、以下のスライドが参考になります。
Istioはデータプレーンとコントロールプレーンの2つのコンポーネントから構成されます。
- データプレーン : 実際にサービス間通信を行う部分です。 アプリケーションのプロキシとして Envoy を起動します (サイドカーコンテナとして起動するケースが多いです)。 Envoyはトラフィック管理、可観測性、セキュリティなどの機能を提供します。
- コントロールプレーン : Envoyの設定を管理・更新します。
Istioのサポートポリシーは Supported Releases に定義されています。 概要は以下のとおりです。
- 4半期に1回、マイナーリリースを行う。
- 各マイナーリリースのサポート(=セキュリティパッチの提供など)はN+2マイナーリリースの6週間後まで提供される。
- 例:
v1.11
のサポートはv1.13.0
をリリースした6週間後まで提供される。
- 例:
Argo CDとは
Argo CD はKubernetes用の継続的デリバリーツールの1つです。
Argo CDは、gitリポジトリで管理されたKubernetesのマニフェストの変更を、Kubernetesクラスタへデプロイします。
Argo CDは GitOps という手法に基づいています。 GitOpsはWeaveworks社が提唱した継続的デリバリー・継続的デプロイメントの方法であり、以下の特徴があります。
- システム全体が宣言的に記述されていること。
- マニフェストがgitで管理され、それが信頼できる唯一の情報源(Single Source of Truth)であること。
- 承認されたマニフェストの変更が自動的にデプロイされること。またその際Kubernetesクラスタへの認証情報を外部(例えばCIサーバなど)に持たせる必要がないこと。
- マニフェストとKubernetesクラスタの間に差分がある場合、それを検知したり、自動的に修正したりできること。
Istioをどうやってバージョンアップするか
先述した通りIstioの各マイナーリリースはリリースから約6〜8ヶ月後にサポートが終了します。 そのため定期的にIstioをバージョンアップする必要があります。
公式ドキュメント には以下の3つのバージョンアップ方法が紹介されています。
なお、In-place upgradeの場合、バージョンアップ前後のバージョン差異は1マイナーリリース以内である必要があります。3 また、Canary upgradeの場合、バージョンアップ前後のバージョン差異は2マイナーリリース以内であることが推奨されています。4
実案件の多くは、Kubernetesマニフェストのデプロイを、Argo CDなどの継続的デリバリーツールを使って行います。 しかし、上述のドキュメントでは、Kubernetesクラスタ管理者が手元からコマンドを実行してバージョンアップする方法しか紹介されていません。 そこで本記事では、Argo CDを使ってIstioをバージョンアップする方法を紹介します。
今回は以下の理由から方法3をベースとします。
Argo CDを使ってIstioをバージョンアップする
想定する環境
本記事では以下の環境を前提とします。
- Amazon EKS v1.23
- Argo CD v2.4.14
- Istio v1.13.4 → v1.15.3
またサンプルアプリケーションとしてIstio公式のサンプルアプリケーションである Bookinfoアプリケーション がデプロイされているものとします。
環境を構築する
Amazon EKS
本記事では詳細な手順は割愛します。 詳しくは Amazon EKS クラスターの作成 - Amazon EKS をご参照ください。
Argo CD
KubernetesクラスタへArgo CDをデプロイします。
本記事では詳細な手順は割愛します。 詳しくは以下の公式ドキュメントをご参照ください。
- Getting Started - Argo CD - Declarative GitOps CD for Kubernetes
- Installation - Argo CD - Declarative GitOps CD for Kubernetes
Istio
IstioのHelm chartは以下の3つを使用します。
本記事では以下の手順でKubernetesクラスタにIstio v1.13.4がインストールされているものとします。
- 必要なnamespaceを作成します。
$ kubectl create namespace istio-system $ kubectl create namespace istio-ingress
istio-ingress
namespaceに automatic sidecar injection を有効にするためのlabelを設定します。
$ kubectl label namespace istio-ingress istio-injection=enabled
- 以下のArgo CDのApplication CRを
kubectl apply
コマンドでデプロイします。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istio-base namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: base targetRevision: 1.13.4 helm: releaseName: istio-base destination: server: https://kubernetes.default.svc namespace: istio-system ignoreDifferences: - group: admissionregistration.k8s.io kind: ValidatingWebhookConfiguration name: istiod-default-validator jsonPointers: - /webhooks/0/failurePolicy --- apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istiod namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: istiod targetRevision: 1.13.4 helm: releaseName: istiod destination: server: https://kubernetes.default.svc namespace: istio-system ignoreDifferences: - group: admissionregistration.k8s.io kind: MutatingWebhookConfiguration name: istio-sidecar-injector jsonPointers: - /webhooks/0/clientConfig/caBundle - /webhooks/1/clientConfig/caBundle - /webhooks/2/clientConfig/caBundle - /webhooks/3/clientConfig/caBundle --- apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istio-ingress namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: gateway targetRevision: 1.13.4 helm: releaseName: istio-ingress destination: server: https://kubernetes.default.svc namespace: istio-ingress
- 上述のApplication CRについてArgo CDのWeb UIからsyncを実行してIstioをデプロイします。
- syncは
istio-base
→istiod
→istio-ingress
の順に実行します。 - 本記事ではArgo CDのWeb UIのアクセス方法および操作方法に関する説明は割愛します。詳細は Argo CDの公式ドキュメント をご参照ください。
- syncは
サンプルアプリケーション
本記事ではサンプルアプリケーションとして default
namespaceにIstio公式のサンプルアプリケーションである Bookinfoアプリケーション がデプロイされているものとします。
default
namespaceに automatic sidecar injection を有効にするためのlabelを設定します。
$ kubectl label namespace default istio-injection=enabled
- Bookinfoアプリケーション をデプロイします。
$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/1.13.4/samples/bookinfo/platform/kube/bookinfo.yaml $ kubectl apply -f https://raw.githubusercontent.com/istio/istio/1.13.4/samples/bookinfo/networking/bookinfo-gateway.yaml $ kubectl apply -f https://raw.githubusercontent.com/istio/istio/1.13.4/samples/bookinfo/networking/destination-rule-all.yaml
- Gateway
bookinfo-gateway
の.spec.selector
をistio=ingressgateway
からistio=ingress
へ変更します。
$ kubectl patch gateways.networking.istio.io bookinfo-gateway --type=merge -p '{"spec":{"selector":{"istio":"ingress"}}}'
手順1. Canary upgradeが可能か確認する
以下の条件を満たしているか確認します。
- Istioのバージョンアップ前後のバージョン差異が2マイナーリリース以内であること。
- 例えば、現在のバージョンが
1.13.x
の場合、1.14.x
と1.15.x
へバージョンアップできます。
- 例えば、現在のバージョンが
istio/base
、istio/gateway
、CRDに破壊的変更がないこと。- これらのリソースはバージョンアップ前後で共有されるためです。
istio/istiod
がバージョンアップ前後で独立しており同じリソースを共有しないこと。- 古いバージョンの
istio/istiod
を安全に削除するためです。 - なお
istio/istiod
のパラメータrevision
にはバージョンアップ前後で異なる値を設定します。
- 古いバージョンの
kubectl rollout restart
コマンドでアプリケーションのPodを安全に再作成できること。- PodがGraceful Shutdownするよう実装・設定されているか。
- PodのUpdate strategyが適切に設定されているか。
- 以下の手順でバージョンアップ前後の互換性が確認できていること。
- 更新後のバージョンの
istioctl
を GitHubのリリース からダウンロードする。 istioctl x precheck
コマンドを実行して互換性を確認する。
- 更新後のバージョンの
$ istioctl x precheck ✔ No issues found when checking the cluster. Istio is safe to install or upgrade! To get started, check out <https://istio.io/latest/docs/setup/getting-started/>
手順2. istio/base
(CRDを含む)を更新する
- Application CR
istio-base
のtargetRevision
を更新します。これによりCRDなどが更新されます。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istio-base namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: base targetRevision: 1.15.3 helm: releaseName: istio-base destination: server: https://kubernetes.default.svc namespace: istio-system ignoreDifferences: - group: admissionregistration.k8s.io kind: ValidatingWebhookConfiguration name: istiod-default-validator jsonPointers: - /webhooks/0/failurePolicy
本来、 helm upgrade
コマンドや helm uninstall
コマンドでhelm chartを更新/削除しても、CRDは更新/削除されません。7
ただし、Argo CDは helm template
で生成したマニフェストを kubectl apply
しているため、Helm chartを更新することで、CRDを更新できます。
手順3. 新しいバージョンの istio/istiod
を追加する
- 新しいバージョンの
istio/istiod
のApplication CRをデプロイします。- このとき、以下のフィールドは更新後のバージョンにあわせて変更します。
.metadata.name
.spec.source.targetRevision
.spec.source.helm.values
のrevision
(*1).spec.ignoreDifferences
8
- このとき、以下のフィールドは更新後のバージョンにあわせて変更します。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istiod-1-15-3 namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: istiod targetRevision: 1.15.3 helm: releaseName: istiod values: | revision: "1-15-3" destination: server: https://kubernetes.default.svc namespace: istio-system ignoreDifferences: - group: admissionregistration.k8s.io kind: MutatingWebhookConfiguration name: istio-sidecar-injector-1-15-3 jsonPointers: - /webhooks/0/clientConfig/caBundle - /webhooks/1/clientConfig/caBundle
istio-system
namespaceに新しいバージョンのistiod
が作成されたことを確認します。
$ kubectl -n istio-system get pods,svc,mutatingwebhookconfigurations NAME READY STATUS RESTARTS AGE pod/istiod-1-15-3-59d4cf9474-gklrs 1/1 Running 0 11s pod/istiod-579df55f96-n4tk8 1/1 Running 0 21m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/istiod ClusterIP 172.20.91.227 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 21m service/istiod-1-15-3 ClusterIP 172.20.213.98 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 11s NAME WEBHOOKS AGE mutatingwebhookconfiguration.admissionregistration.k8s.io/istio-sidecar-injector 4 21m mutatingwebhookconfiguration.admissionregistration.k8s.io/istio-sidecar-injector-1-15-3 2 11s mutatingwebhookconfiguration.admissionregistration.k8s.io/pod-identity-webhook 1 38m mutatingwebhookconfiguration.admissionregistration.k8s.io/vpc-resource-mutating-webhook 1 37m
手順4. データプレーンを更新する
アプリケーションのPodのサイドカーコンテナとして起動しているEnvoy(以降では istio-proxy
と呼びます)を更新します。
今回は automatic sidecar injection を有効にしているため、 istio-proxy
はPod作成時にサイドカーコンテナとして自動的に追加されます。
この場合、 automatic sidecar injection が有効なnamespaceについて、namespaceのlabelを更新した後、Podを再作成することで、 istio-proxy
を更新できます。
今回対象となるnamespaceは以下の2つです。
default
namespaceistio-ingress
namespace
まず default
namespaceに対して以下の手順を実施します。
- 現在の
istio-proxy
の状態を確認します。
$ istioctl -n default proxy-status NAME CLUSTER CDS LDS EDS RDS ECDS ISTIOD VERSION details-v1-6bd666858f-wq2fr.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-579df55f96-n4tk8 1.13.4 productpage-v1-7f6655c647-s8gdf.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-579df55f96-n4tk8 1.13.4 ratings-v1-7cc7df5fd5-slqgd.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-579df55f96-n4tk8 1.13.4 reviews-v1-68c7d56667-nvv5q.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-579df55f96-n4tk8 1.13.4 reviews-v2-759496d8df-gkgdh.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-579df55f96-n4tk8 1.13.4 reviews-v3-7545ff7c75-68n7b.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-579df55f96-n4tk8 1.13.4
- namespaceのlabelを更新します。
istio.io/rev=<(*1)と同じ文字列>
labelを設定します。istio-injection
labelが存在する場合は削除します。
$ kubectl label namespace default istio.io/rev=1-15-3 $ kubectl label namespace default istio-injection-
- 先程のnamespaceのPodを再作成します。
$ kubectl -n default rollout restart deployment
- 変更後の
istio-proxy
の状態を確認します。- 特に
ISTIOD
列とVERSION
列が新しくなっていることを確認します。
- 特に
$ istioctl proxy-status NAME CLUSTER CDS LDS EDS RDS ECDS ISTIOD VERSION details-v1-5954bb9d8-xn5j6.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-15-3-59d4cf9474-gklrs 1.15.3 productpage-v1-7f6bff5ddd-ms4b4.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-15-3-59d4cf9474-gklrs 1.15.3 ratings-v1-6f8d5bf8d4-f2jmm.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-15-3-59d4cf9474-gklrs 1.15.3 reviews-v1-785b65d7c4-6j4wq.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-15-3-59d4cf9474-gklrs 1.15.3 reviews-v2-86b446779b-9wx5q.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-15-3-59d4cf9474-gklrs 1.15.3 reviews-v3-5b5b976fbb-cc2j9.default Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-15-3-59d4cf9474-gklrs 1.15.3
次に istio-ingress
namespaceに対しても同様の手順を実施します。
default
namespaceと同じ内容のため詳細は割愛します。
Canary upgradeではこのようにnamespace単位で徐々にデータプレーンを更新できます。 また、もし問題が発生した場合はnamespaceのlabelをもとに戻してPodを再作成することでデータプレーンの更新をロールバックできます。
手順5. istio/base
の defaultRevision
を更新する
- Application CR
istio-base
の.spec.source.helm.values
のdefaultRevision
を(*1)と同じ文字列へ更新します。 これによりValidatingWebhookConfigurationistiod-default-validator
の宛先が古いバージョンのistiod
から新しいバージョンのistiod
へ変更されます。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istio-base namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: base targetRevision: 1.15.3 helm: releaseName: istio-base values: | defaultRevision: "1-15-3" destination: server: https://kubernetes.default.svc namespace: istio-system ignoreDifferences: - group: admissionregistration.k8s.io kind: ValidatingWebhookConfiguration name: istiod-default-validator jsonPointers: - /webhooks/0/failurePolicy
手順6. istio/gateway
を更新する
- Application CR
istio-ingress
のtargetRevision
を更新します。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istio-ingress namespace: argocd spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: gateway targetRevision: 1.15.3 helm: releaseName: istio-ingress destination: server: https://kubernetes.default.svc namespace: istio-ingress
手順7. 古いバージョンの istio/istiod
を削除する
- 古いバージョンの
istio/istiod
のApplication CRにfinalizerを設定します。- Application CRの削除と同時に関連するリソースを削除するためです。9
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: istiod namespace: argocd finalizers: - resources-finalizer.argocd.argoproj.io spec: project: default source: repoURL: https://istio-release.storage.googleapis.com/charts chart: istiod targetRevision: 1.13.4 helm: releaseName: istiod destination: server: https://kubernetes.default.svc namespace: istio-system ignoreDifferences: - group: admissionregistration.k8s.io kind: MutatingWebhookConfiguration name: istio-sidecar-injector jsonPointers: - /webhooks/0/clientConfig/caBundle - /webhooks/1/clientConfig/caBundle - /webhooks/2/clientConfig/caBundle - /webhooks/3/clientConfig/caBundle
- 古いバージョンの
istio/istiod
のApplication CRを削除します。 istio-system
namespaceから古いバージョンのistio/istiod
が削除されたことを確認します。
$ kubectl -n istio-system get pods,svc,mutatingwebhookconfigurations NAME READY STATUS RESTARTS AGE pod/istiod-1-15-3-59d4cf9474-gklrs 1/1 Running 0 6m1s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/istiod-1-15-3 ClusterIP 172.20.213.98 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 6m1s NAME WEBHOOKS AGE mutatingwebhookconfiguration.admissionregistration.k8s.io/istio-sidecar-injector-1-15-3 2 6m1s mutatingwebhookconfiguration.admissionregistration.k8s.io/pod-identity-webhook 1 43m mutatingwebhookconfiguration.admissionregistration.k8s.io/vpc-resource-mutating-webhook 1 43m
おわりに
この記事ではArgo CDを使ってIstioをバージョンアップする方法を紹介しました。
バージョンアップはシステムをセキュアな状態に維持するために欠かせない作業です。 一方でIstioのバージョンアップは、サービスメッシュ上の全アプリケーションに影響のある作業でもあります。 安全かつ効率的なバージョンアップ方法を確立していきたいですね。
最後までお読みいただき、ありがとうございました。
私たちは同じチームで働いてくれる仲間を探しています。クラウドアーキテクトの業務に興味がある方のご応募をお待ちしています。
執筆:@shibata.takao、レビュー:寺山 輝 (@terayama.akira) (Shodoで執筆されました)
- 図は https://istio.io/latest/about/service-mesh/ より引用しました。↩
- 図は https://argo-cd.readthedocs.io/en/stable/ より引用しました。↩
- 詳細は https://istio.io/latest/docs/setup/upgrade/in-place/#upgrade-prerequisites をご参照ください。↩
- 詳細は https://istio.io/latest/docs/setup/upgrade/canary/#before-you-upgrade をご参照ください。↩
- 詳細は https://istio.io/latest/docs/setup/upgrade/in-place/ をご参照ください。↩
- 詳細は https://argo-cd.readthedocs.io/en/stable/user-guide/helm/ をご参照ください。↩
- 詳細は https://helm.sh/docs/chart_best_practices/custom_resource_definitions/ をご参照ください。↩
- 詳細は https://argo-cd.readthedocs.io/en/stable/user-guide/diffing/ をご参照ください。↩
- 詳細は https://argo-cd.readthedocs.io/en/stable/user-guide/app_deletion/ をご参照ください。↩