AI 事業本部の長谷川(@makocchi)です。
サイバーエージェントでは全社横断でゼミ制度があり、業務時間の一部をゼミ活動に割り当てることが可能な制度があります。
日々色々なエンジニアが研究したいテーマに沿って活動しているのですが、自分はそのゼミ制度を活用して「Cloud Native Experts ゼミ」を立ち上げています。
本ゼミではいろいろな活動をしているのですが、最近 Google 社が掲げている Anthos という Platform について Google 社エンジニアの方々のご協力のもと検証しましたので、この場を借りて報告させて頂きたいと思います。
Anthos とは?
Anthos については簡単に言うと、ハイブリッドクラウドやマルチクラウドを推進させるためのプラットフォームというところでしょうか。
詳しくは公式の HP を見て頂けるとイメージが湧きやすいと思います。
Anthos は上記の通りプラットフォームとなっていますので、その中に様々な機能がコンポーネントとして提供されています。
代表的なコンポーネント(コアコンポーネント)として定義されているのは
-
- Anthos GKE
- Anthos Config Management
- Anthos Service Mesh
- Anthos security
となっていますが、それ以外にも様々な機能が提供されています。
今回はその機能の 1 つである「Ingress for Anthos」について検証をしました。
Ingress for Anthos | Google Cloud
Ingress for Anthos とは?
簡単に言ってしまうと 1 つの LoadBalancer 配下に複数の GKE クラスターを配置することができるサービスです。当然マルチリージョン、マルチゾーンで展開させることができます。
具体的な例を挙げますと、1 つの LoadBalancer(Global IP)配下に例えば 3 つのリージョン、東京(ap-northeast1)、アメリカ(us-central1)、ヨーロッパ(europe-north1) の GKE クラスターを並べることができます。利用者は距離的に一番近い GKE クラスターにアクセスすることになります。
アーキテクチャ図を見ると分かるのですが、Anthos Ingress Controller が GCP 内部でマネージドで動いています。クラスターを “Hub” という概念で束ねています。それぞれのクラスターは “membership” として Hub に登録されることになります。
実は、同じような機能(Multi Cluster Ingress 通称 mci)を提供するソフトウェアが以前 k8s-multicluster-ingress(kubemci) といった名前で公開されていました。もしかしたら kubemci の名前を聞いたことがある方がいらっしゃるかもしれませんね。現在では k8s-multicluster-ingress は既に開発が止まっており、注力は Ingress for Anthos の方に向いているようです。
[DEPRECATED] This has now been deprecated in favor of Ingress for Anthos. Ingress for Anthos is the recommended way to deploy multi-cluster ingress.
※ k8s-multicluster-ingress の README より
Ingress for Anthos を有効にするには
詳しい手順は公式の Document がありますので、それに従っていけば問題なく設定することができると思います。
クラスタ間での Ingress のデプロイ | Kubernetes Engine ドキュメント | Google Cloud
有効にするまでの大まかな流れを書くと
-
- 使用する各種 API を有効にする (必要に応じて)
- GKE クラスターを作成する
- GCP のサービスアカウントを作成する
- 作成した GKE クラスター達を登録する(gcloud container hub memberships register)
- 作成した GKE クラスター達に対して、それぞれ同じ Deployment や Statefulset 等を展開させる
- 構成クラスター(config cluster)を決める
- 構成クラスターに対して MultiClusterIngress 及び MultiClusterService を定義する(CRD)
のようになります。
少し具体的に手順を追ってみましょう。
見慣れない手順としてクラスターの登録(gcloud container hub memberships register)がありますので、まずはこちらの挙動を見ていきます。
具体的には Document の手順通りやればいいだけなのですが、
$ gcloud container hub memberships register gke-tokyo \
> --project=your-project \
> --gke-uri=https://container.googleapis.com/v1/projects/your-project/zones/asia-northeast1-a/clusters/gke-tokyo \
> --service-account-key-file=./your-service-account.json
kubeconfig entry generated for gke-tokyo.
Waiting for membership to be created...done.
Created a new membership [projects/your-project/locations/global/memberships/gke-tokyo] for the cluster [gke-tokyo]
Generating the Connect Agent manifest...
Deploying the Connect Agent on cluster [gke-tokyo] in namespace [gke-connect]...
Deployed the Connect Agent on cluster [gke-tokyo] in namespace [gke-connect].
Finished registering the cluster [gke-tokyo] with the Hub.
このようなコマンドを Ingress for Anthos の対象にしたいクラスター分叩く必要があります。(もしくは GCP のコンソールから登録することもできます)
このコマンドが叩かれると、対象にクラスターにはログに出ている通り
-
- gke-connect という Namespace が作成される
- gke-connect Namespace 内に creds-gcp という Secret が作成される(中身は先程指定したサービスアカウントの json ファイル)
- gke-connect Namespace 内に gke-connect-agent という Deployment が 作成される
といった事が行われます。
ちなみに gke-connect-agent は “gcr.io/gkeconnect/gkeconnect-gce:<tag>” のコンテナイメージが使われています。
おそらくクラスターを登録した時点での最新のイメージタグが使用されることになると思います。(執筆時点では 20200515-02-00 でした)
イメージタグはこちらから確認することができます。結構頻繁に更新されていますね。
特に問題なく登録することができたら、このように gcloud container hub memberships list で確認することができると思います。
下記の例は東京(ap-northeast1)、大阪(ap-northeast2)、韓国(ap-northeast3)で登録してみた結果になります。
$ gcloud container hub memberships list
NAME EXTERNAL_ID
gke-korea 21b8adad-30b5-4903-9e4a-94ca625203af
gke-tokyo 6ab7e4a5-c3a9-4af1-8431-f88cff13f30d
gke-osaka 41554e05-9fb2-45f4-a62d-7ea7c80d2b5c
# --uri も使うことが出来るみたいです
$ gcloud container hub memberships list --uri
https://gkehub.googleapis.com/v1/projects/your-project/locations/global/memberships/gke-korea
https://gkehub.googleapis.com/v1/projects/your-project/locations/global/memberships/gke-tokyo
https://gkehub.googleapis.com/v1/projects/your-project/locations/global/memberships/gke-osaka
ここでは構成クラスター(config cluster)は東京のクラスターにしておきます。
$ gcloud alpha container hub ingress enable \
--config-membership=projects/your-project/locations/global/memberships/gke-tokyo
ここまで来たらあとは各クラスターに対して Deployment 等を作成し、MultiClusterIngress と MultiClusterService を定義するだけです。
公式 Document では例として zoneprinter といったアプリケーションを展開させています。
英語の Document では zoneprinter:0.2 が使われているのですが、日本語 Document だとちょっと古くて zoneprinter:0.1 が使われています。
どちらでも動作確認は問題ないでしょう。但し使用 Port が 80 と 8080 で変わってますので注意してください。
この zoneprinter ですが、対応している zone 情報が古く、比較的新しい zone(大阪 ap-northeast2 や 韓国 ap-northeast3 等)に対応していなかったので PR を送って見たところ無事に merge してくれました!
しかしながら gcr.io に配置されているイメージは更新されていないのです・・
なので自分で build(zoneprinter:0.3) して up しておきましたので、もしよかったら使ってみて下さい。
https://hub.docker.com/r/makocchi/zone-printer/tags
大抵の場合はクラスター上に Deployment 等を作成すると、それに対応した Service も同時に作ったりすることがほとんどのケースだと思います。
Ingress for Anthos の場合は各クラスターには Service を作る必要がありません。というのも MultiClusterService という共通のリソース(CRD)で管理することになるのですが、MultiClusterService を作成すると各クラスターに自動的に Service が作られます。
自動で作成された各クラスターの Service は “mci-<service 名>-svc-<ランダム文字列>” の形式で作成されており、annotation に “cloud.google.com/neg” があることから、Service と同時に NEG も作成されることになります。(ちなみにこの Service は直接変更したり削除したりしても Reconcile されて元の状態に戻ります。)
MultiClusterService 及び MultiClusterIngress のリソースは manifest で定義する際は中身はそのまま Service と Ingress の書き方で大丈夫ですので、特に悩むことなく直感的に定義することができると思います。
注意点としては、この MultiClusterService 及び MultiClusterIngress のリソースは構成クラスターでのみ適用するという点です。先程の例でいいますと東京のクラスターということになります。繰り返しになりますが、東京のクラスターに対して MultiClusterService を設定すると、各クラスターに “mci-<service 名>-svc-<ランダム文字列>” の Service が作られる、といった仕組みになっています。
MultiClusterService を設定してクラスターへのアクセスを制御してみよう
MultiClusterService を定義する際には、先程の登録したクラスター達の中から実際にアクセスさせるクラスターを選択することができます。
例えば先程の例で言いますと、東京(ap-northeast1)、大阪(ap-northeast2)、韓国(ap-northeast3)で展開しているところから大阪だけを外す(戻す)といった作業や、東京と韓国の組み合わせから東京と大阪の組み合わせへの変更も簡単に行なえます。
やり方はとても簡単で、対象のクラスターを絞るには MultiClusterService 内の定義の spec.clusters にて行います。
特に指定をしない場合は、登録されたクラスターすべてがアクセス対象になります。
この機能を上手く使えば、例えば 1 クラスターずつ安全に Kubernetes のバージョンアップを行うといったことも可能になります。
しかしながらこのクラスターの対象の操作に関しては運用上注意すべき点がありますので、これは後ほど説明します。
ちなみに、まったく同じリージョン、ゾーンのクラスターを複数登録できるのか?というと問題なくできます。
まったく同じリージョンとゾーンのクラスターのみの構成でも、アクセスはちゃんと複数のクラスタへ分散してくれます。
MultiClusterService の対象から外したクラスターは先程説明した自動で作成される “mci-<service 名>-svc-<ランダム文字列>” の Service は削除されるようです。(対象に戻せばまた作成されます)
とあるクラスターで障害が起きた場合はどうなるのか?
例えば東京、大阪、韓国で展開しているとした時に、東京だけクラスターレベルの障害があった場合にはどうなるのでしょうか。
その場合は本来東京へ行くはずのアクセスは他のクラスターに流れることになります。
クラスターレベルでは無いものの、例えば Deployment が削除された、とかの場合も同じように他のクラスターへアクセスを流してくれます。
Pod 単体の問題、例えば readinessProbe が失敗している場合はどうなるのかといいますと MultiClusterService はそこまで考慮してくれないようでした。
ですので readinessProbe が失敗しても Pod へのアクセスは止まりませんので注意が必要です。
但し、Pod 単体の Probe は考慮してくれないのですが、作成された LoadBalancer からのヘルスチェックも同時に行われており、こちらのヘルスチェックが失敗した場合には正常に切り離されます。ですので LoadBalancer からのヘルスチェックと Probe は合わせておいたほうがいいでしょう。
LoadBalancer からのヘルスチェックは BackendConfig を使って定義することができます。特に定義していない場合にはデフォルトの設定が入りますので、例えばヘルスチェックの PATH を変更したい等の要望がある時には必ず設定しましょう。(デフォルトでは PATH は “/” です)
運用上気をつけたいところ
ここでは検証した結果、運用するにあたって気をつけたほうが良さそうなポイントを纏めます。
クラスターの出し入れは慎重に
クラスターの対象を操作する際に気をつけたいポイントがあります。
例えば東京と大阪の 2 クラスターで展開していた場合に、MultiClusterService の定義を変更して韓国 1 クラスターだけに変更した場合はどうなるでしょうか。
最終的には韓国 1 クラスターだけにアクセスが行くようにはなるのですが、切り替わりの段階で LoadBalancer が 502 Server Error を返す時間帯が発生してしまいます。
これは東京と大阪のアクセスを止めるタイミングと、韓国へのアクセスを始めるタイミングは内部的には非同期で行われており、タイミングによってはどのリージョンにもアクセスを流すことができない時間帯が発生してしまうことによるものだと推測しています。
ですのでこのような作業を行いたい場合は、まず韓国のクラスターを参加させ、その後に東京と大阪を縮退させる、もしくは東京と大阪の構成から東京と韓国の構成に変更し、その後東京を縮退させる、といったワークアラウンドでサービス無停止で切り替えることが可能です。
設定反映にはある程度時間がかかる
クラスターの出し入れの際に、MultiClusterService の manifest を apply してから、実際にどのくらいでクラスターへのアクセスが変更されるのかというと、体感的には 5 分から 10 分ほどかかっていました。(きっと全世界に展開しているからそれなりに時間がかかるんでしょう・・・)
クラスターへのアクセスの変更はすぐには反映されないので、例えば日付が変わった瞬間に切り替えたいみたいな要望は難しいのかなと思いました。
BackendConfig をきちんと設定する
これは先程も述べましたが、Pod に対する Probe の設定だけでは不十分なところがあります。NEG が使われることになるので、LoadBalancer からのヘルスチェックもきちんと設定し、設定を合わせておくのがいいでしょう。
登録されたクラスターを削除しても登録された状態は変わらない
こういうケースはほとんど無いと思うのですが、hub に登録済みのクラスターを削除(delete)した場合でも登録状態は削除されません。手動で登録を解除してあげる必要があります。
1 GCP project に対して 1 つしか memberships を作ることが出来ない
クラスターを登録することで、gcloud container hub memberships list のコマンドを実行した際に登録されたことを確認することができるようになるのですが、この memberships 自体は 1 GCP project に対して 1 つしか作れないようです。(Global 扱い)
例えば 1 つの GCP project 内で複数の環境(Production、Staging のような)の memberships を定義する、といったことは出来ないのが現状です。複数の memberships で管理したい場合は、素直に GCP project を分けて作る必要がありますね。
まとめ
いかがだったでしょうか。
今回検証してみて Ingress for Anthos はとても使いやすく、直感的に定義することができるので非常に強力な機能だと思いました。
特にクラスターを本格的に冗長構成にしたいといった要望にはうってつけだと思います。
クラスターへのアクセス変更は少し時間がかかりますが、クラスター単位で Blue/Green(Red/Black)切り替えも可能ですので、興味がある方は是非触ってみて下さい!
あ 最後に重要なことを書くのを忘れてました。
Ingress for Anthos を使う為には Anthos のライセンス(Anthos on Google Cloud)が別途必要になります。検討する際にはご注意下さい。執筆時点ではサブスクリプションの課金体系になりますが、pay-as-you-go での課金体系も始まるようです。
Anthos の料金体系はこちらになります。
Pricing | Anthos | Google Cloud
Portions of this page are reproduced from work created and shared by Google and used according to terms described in the Creative Commons 4.0 Attribution License.