Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

Istio Operatorやめました

はじめに

こんにちは。広告技術部のjohnmanjiroです。普段は広告配信のAPIや管理画面を作っています。ピーナッツくんのライブビューイングに当選したので当日が楽しみです。

広告技術部ではマイクロサービス間の通信を簡単に行うために、サービスメッシュとしてIstioを利用しています。先日、Istioの管理をIstio OperatorからHelmに移行したのでご紹介します。Istioに関する記事はすでに本ブログでもいくつか公開しているので、興味があればぜひご覧ください。 tech.gunosy.io

tech.gunosy.io

なお、これは公式から出ている移行方法ではありません。あらかじめご了承ください*1

チーム内での概要の共有に使用したスライドもあるので、ご興味のある方は参考にしていただけると幸いです。

speakerdeck.com

用語

本題に入る前に、この記事で扱うIstio関連の用語についてあらかじめ定義しておきます。

用語 意味
Istio Operator Istioを管理する方法のひとつ
IstioOperator istio-operatorが管理するカスタムリソース
istio-operator Kubernetes上でPodとして動作しているIstio Operatorのカスタムコントローラー
Istioctl 公式から提供されるIstio管理用のCLI

Istio OperatorはIstioを管理する方法のひとつで、IstioOperatorというカスタムリソースとistio-operatorというカスタムコントローラーによりIstioを管理します。いわゆるOperatorパターンです。

IstioOperatorはKubernetes上にapplyされるカスタムリソースです。実際のIstioの設定はこのリソースに記述し、istio-operatorによって管理されます。

istio-operatorはKubernetes上でPodとして動作するカスタムコントローラーです。istioctl operator init によってapplyされ、IstioOperatorの記述にしたがってKubernetesクラスタ上にIstioのリソースを展開します。

Istioctlは公式から提供されるIstio管理のためのCLIです。

より詳細な内容に関しては、ドキュメントをご確認ください。

なぜIstio Operatorをやめるのか

結論から述べると、Istio Operatorでのインストールが非推奨になったからです。ドキュメントのIstio Operator Installには次のように記載されています。

Use of the operator for new Istio installations is discouraged in favor of the Istioctl and Helm installation methods. While the operator will continue to be supported, new feature requests will not be prioritized.

Istioの新規インストールにオペレーターを使用することは推奨されず、IstioctlとHelmのインストール方法が優先されます。オペレータは引き続きサポートされますが、新しい機能のリクエストは優先されません(DeepLによる翻訳)。

サポート自体は継続するものの、今後新しい機能が追加されないであろうことと、非推奨になった機能を使い続けることのリスクを考え、Istio Operatorによる管理をやめてHelmへの管理に移行することにしました。

ではなぜIstioctlでなくHelmを採用したのかについて説明します。

IstioctlかHelmか

Istioの管理方法には次の3種類の方法があります。

  • Istioctl
    • 公式から提供されているCLI
    • IaC (Infrastructure as Code)による管理ができない
  • Istio Operator
    • istio-operatorがIstioOperatorというリソースに基づいてIstioを管理するOperatorパターン
    • IstioをTerraform経由で管理するために使っているが、非推奨になった
  • Helm
    • Kubernetes向けのパッケージマネージャー
    • Kubernetesでマニフェストを公開する際のデファクトスタンダード(だと思っている)

今回はIstio Operatorからの移行なのでIstioctlかHelmのどちらかに移行することになります。

IstioctlはCLIでIstioを管理することになるため、IaCによる管理を行うことができません。できるだけコードとして管理したいということと、広告技術部ではIstio以外のKubernetes関連のサードパーティーツールはHelm(より具体的にはhelmfile)で管理していることもあり、Helmに移行することに決めました。

Istio Operatorの挙動

そもそも、今回移行しようとしているIstio Operatorとは一体何なのでしょうか。

何度も述べている通り、カスタムリソースとカスタムコントローラーによるOperatorパターンです。カスタムコントローラーであるistio-operatorがIstioOperatorの設定を読み、それに応じてKubernetesクラスタ上へIstioのリソースを展開します。それでは、どうやってIstioOperatorの設定から実際のIstioのリソースをapplyしているのでしょうか。

次はIstioOperatorのマニフェストの例です。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: default-istiocontrolplane
spec:
  profile: minimal
  values:
    global:
      imagePullPolicy: IfNotPresent
  components:
    pilot:
      k8s:
        resources:
          requests:
            cpu: 500m
            memory: 2Gi
          limits:
            cpu: 500m
            memory: 2Gi

実は、istio-operatorは内部にIstioのHelm Chartを持っており、IstioOperatorの設定を読み込んだら、それをvaluesとしてHelm ChartからマニフェストをRenderし、Kubernetes上へapplyしています。したがって、IstioOperatorのspec以下に書かれている設定は、Helmのvaluesをそのまま記載していることになります(profileなどの一部を除きます)。

istio-operatorが内部にHelm Chartを持っているということは、結局は今回移行しようとしている先のHelmと同じものを使っているということです。このことから、Istio Operatorによって管理しているIstio関連のリソースをそっくりそのままHelmに管理させれば、Helmによる管理に移行できるということがわかります。

既存のリソースをHelmに認識させる

Istio Operatorによって管理されているリソースをHelmに移行するには、既存のリソースをそのままHelmに認識させればよいということがわかりました。それでは、どうすれば既存のリソースをHelmに認識させることができるでしょうか。

HelmはKubernetes上のリソースを、次のラベルとアノテーションで認識しています。

  • ラベル
    • app.kubernetes.io/managed-by=Helm
  • アノテーション
    • meta.helm.sh/release-name=<release_name>
    • meta.helm.sh/release-namespace=<release_namespace>

ここで、release_nameはインストールするReleaseの名前で、release_namespaceはインストールするnamespaceです。

IstioをHelmでインストールする場合、複数のHelm Chartを利用する必要があります*2。広告技術部ではIstioの最低限の機能しか利用していないため、次の2つのインストールが必要でした。

  • istio-base
    • Istio全体で必要になるリソースをまとめたChart
    • どのChartよりも先にインストールする必要がある
  • istiod
    • IstioのコントロールプレーンであるIstiodに関連するリソースをまとめたChart

もしGatewayなどほかの機能を使っている場合は、必要に応じてgatewayなどのインストールが必要になります。

以上から、istio-baseに含まれるリソースに対してistio-baseに合わせたラベルとアノテーションを付与し、istiodに含まれるリソースに対してそれに合わせたラベルとアノテーションを付与することで、既存のリソースをそのままHelmのリソースとして認識させ、helm installを実行することができます。

実際に使用したスクリプトはGistで公開しているので、参考にしていただければ幸いです(Istioのバージョンは1.15.6です)。

ここまでで既存のリソースをHelmに認識させることができるとわかりました。ではこのまま helm install を実行してIstioOperatorを削除すれば移行は完了するのでしょうか。

実は、カスタムリソースであるIstioOperatorを削除してしまうと、IstioOperatorの設定によって作成されたリソースがすべて削除されてしまいます。つまりこのままでは、せっかくHelmに認識させたリソースがすべて消え去ってしまうことになります。そこで、動いているIstioのリソースを削除せずにIstioOperatorを削除するということが必要になります。

リソースを消さずにIstioOperatorを消すには

稼働しているIstioのリソースを削除せずにIstioOperatorを消すには二つの方法があります。

  • istio-operatorが利用しているラベルをリソースからすべて剥がしてからIstioOperatorを消す
  • あらかじめistio-operatorを止めてからIstioOperatorを消す

istio-operatorが利用しているラベルを剥がしてから消す

istio-operatorは、次のラベルがついているかをみてKubernetes上で動いているリソースが自分が管理しているものかどうか判断しています。

  • install.operator.istio.io/owning-resource
  • install.operator.istio.io/owning-resource-namespace
  • operator.istio.io/managed
  • operator.istio.io/component
  • operator.istio.io/version

つまり、これらのラベルをすべのリソースから剥がすことで、istio-operatorはそれらを自身が管理するものとは判断しなくなります。Kubernetes上にIstioOperatorに関連するリソースが存在しないことになるので、その後はIstioOperatorを削除してもIstioのリソースが消されることはありません。

この方法のデメリットはすべてのリソースからラベルを剥がす必要があるということです。もしラベルを剥がし忘れたリソースがあれば、そのリソースはIstioOperatorを削除したタイミングで消されてしまいます。

抜け漏れなくスクリプトを組むこと自体が大変ですし、実施する際の精神的負担も大きくなります。

あらかじめistio-operatorを止めてから消す

もう一つの方法は、あらかじめistio-operatorを止めてからIstioOperatorを削除する方法です。 具体的には、istio-operatorのDeploymentのreplica数を0にしたうえでIstioOperatorを削除します。

IstioOperatorはあくまでIstioの設定を記述したカスタムリソースであり、実際のリソースの展開はistio-operatorが行なっています。ということは、istio-operatorのPodをあらかじめすべて停止してしまえば、IstioOperatorを削除したとしてもリソースの削除は行われないということになります*3

この方法のメリットは、ラベルを残したまま実施することができるという点です。もしistio-operatorのPodを止めた時点で何か問題が起きたとしても、Pod数をもとに戻すだけで対応することができます。

注意点として、IstioOperatorにはfinalizerが設定されています。本来はistio-operatorがリソースを削除したのちに剥がされるものですが、Podがいない状態で削除するため、あらかじめfinalizerを剥がしておく必要があります。

今回は安全面を考慮して、後者の方法を取ることにしました。

更新手順

今までの話をもとにすると、具体的な更新手順は次のようになります。

  1. 各Helm Chartに対応したvalues.yamlを用意する
    1. IstioOperatorの設定に合わせて記述する
    2. Pull Requestにできるとなおよい
  2. istio-operatorのPod数を0にする
  3. 既存のリソースに対してHelm用のラベルとアノテーションを付与するスクリプトを実行
  4. helm install
    1. istio-baseから順にインストールしていく
  5. 動作確認
    1. エラーが出ていないか
    2. Podを新規に起動したときIstio Proxyが注入されるか
  6. istio-operatorの削除
    1. istioctl operator remove
  7. IstioOperatorの削除
    1. finalizerを消した上で削除を実行する

このような流れでIstio OperatorからHelmへ移行することができました。実際にはhelmfileやTerraformを利用している部分があるので、一部自動化されています。

Helmにしてよかったこと

なんといっても、Istioの更新作業が楽になりました。

Terraformで管理しているとはいえ、更新時にはIstioctl経由でIstio Operatorを更新していたのですが、手動による作業があることと、具体的にどのリソースが変更されるかを簡単に知ることができないという問題点がありました。

広告技術部ではHelm Chartのコード管理にhelmfileを使っているため、IstioをHelmに移行したことで、更新が helmfile apply で自動で行われるようになったほか、helmfile diff であらかじめ差分を取得することができ、リソースの変更点もわかりやすくなりました。

全体として、Istio OperatorからHelmに移行してよかったなと感じています。

まとめ

今回、Istioの管理をIstio OperatorからHelmへ移行しました。

あらかじめistio-operatorのPodを止めた上で既存のリソースをHelmに認識させ、helm install後にistio-operatorを削除するという方法で移行することができました。 公式から出ている移行方法ではありませんが、今のところ問題なく動作しています。

Istio OperatorからHelmへ移行したいと考えている方の参考になれば幸いです。

*1:公式では一度Istioをアンインストールしてからインストールしなおすという方法を勧められていますが、本番環境で行うことは難しいので採用していません。

*2:https://istio.io/latest/docs/setup/install/helm/

*3:istio-operatorを消せばIstioOperatorを消さなくてもHelmへの移行は終わりではあるのですが、不要なリソースは極力残したくないという観点からIstioOperatorの削除まで行なっています。