この記事は、Cloud Nativeアプリケーション開発のTips!日本マイクロソフト Advent Calendar 2020 の 15 日目 の記事です。
qiita.com
1年ほど前の Microsoft Ignite The Tour で、「Azure Kubernetes Service を活用したマイクロサービス開発」というタイトルでブレイクアウト セッションに登壇したのですが、現在でも通用するベストプラクティスだと思いますので、文章に起こしてみました。
- Helm でマイクロサービスの構成を管理する
- Nginx Ingress Controller で外部向けエンドポイントを公開する
- アップグレード戦略には Blue / Green デプロイを採用する
- Pod と Node のスケーリングを組み合わせて構成する
- 障害が発生する前提で構成を決める
- Azure Monitor でマイクロサービスを監視する
- まとめ
- 参考リンク
Helm でマイクロサービスの構成を管理する
Helm は、Kubernetes のパッケージマネージャーです。1つのマイクロサービスは Service や Deployment など複数のリソースで構成されますが、それらの YAML をパッケージにまとめて管理できます。
このパッケージを Helm Charts と呼びます。YAML の可変部を引数として定義できるので、CI / CD パイプラインで環境に合わせたデプロイを実現できます。
Helm Charts の管理方式は、アプリケーションのリポジトリに Charts ディレクトリを含めることが多いです。
3年前の記事ですが、基本的な使い方は変わらないので参考にしてください。(以前はサービス名が ACS だったので、AKS に読み替えてください・・・)
gooner.hateblo.jp
Nginx Ingress Controller で外部向けエンドポイントを公開する
Kubernetes Cluster の外部向けエンドポイントを1つに集約し、マイクロサービスへのリクエストをルーティングすべきです。
よくあるサンプルでは、マイクロサービスごとに Service の type で LoadBalancer を設定して Public IP Address を公開していますが、これはあくまでチュートリアルです。
いくつか実現方式はあるのですが、私の経験では Nginx Ingress Controller を使うことが多いです。Nginx Ingress Controller は、Helm のリポジトリで公開されている Charts を使ってデプロイし、Ingress はマイクロサービス側で管理するようにしています。
Azure ポータルから設定できる HTTP Application Routing アドオンのほうがお手軽ですが、本番運用は非推奨となっています。
アップグレード戦略には Blue / Green デプロイを採用する
マイクロサービス のアップグレード
変更頻度の高いものをマイクロサービスとして切り出すわけですから、マイクロサービス のアップグレードをどのように実現するのかは非常に重要です。
Blue / Green デプロイにより、更新中の一時的な Pod 数の減少を回避し、障害発生時に素早く切り戻せるようにしておきます。
いくつか実現方式はあるのですが、私の経験では Label Selector の Version を変更して、アクセスする Pod を切り替えることが多いです。
Blue / Green デプロイのためだけにサービスメッシュ(Istioなど) を導入するには、コストが高く、複雑になりすぎると考えています。
Kubernetes Cluster のアップグレード
意外と考慮事項から漏れてしまうのが、Kubernetes Cluster のアップグレードです。Kubernetes の更新サイクルの速さにどのように追随していくのか、しっかりと検討しておくべきです。
AKS には Kubernetes Cluster をインプレースでアップグレードする方法が提供されていますが、本番運用ではリスクが大きいので採用したくありません。
Blue / Green デプロイにより、動作確認済みの Kubernetes Cluster を Production として利用し、障害発生時に素早く切り戻せるようにします。
この方式をシンプルに実現するため、あえて AKS の構成に制約を持たせています。
- Kubernetes Cluster 内ではデータを永続化せず、外部のストレージを利用する
- Application Gateway V2 を配置し、Kubernetes Cluster のフロントでエンドポイントを切り替える
この制約を持たせることで得られるメリットの方が圧倒的に大きいという判断です。
Pod と Node のスケーリングを組み合わせて構成する
Horizontal Pod Autoscaler
Horizontal Pod Autoscaler は、Metrics Server を利用した Pod のオートスケーリングです。Pod の CPU 利用率を閾値として、Pod 数を最大最小の範囲内で自動的に増減できます。
$ kubectl autoscale deployment <DeploymentName> --cpu-percent=50 --min=1 --max=3
Deployment の YAML で、Resources の requests と limits の設定していることが前提となります。
resources: limits: cpu: 200m memory: 256Mi requests: cpu: 100m memory: 128Mi
Cluster Autoscaler
Cluster Autoscaler は、高速なスケーリングを可能にするため、仮想マシンスケールセット(VMSS)を利用しています。
- Status が「Pending」の Pod があると、Node を上限数まで増やしてくれる
- Pod の Requests 合計が 50% を下回る Node を削除候補に、下限数まで減らしてくれる
$ az aks create \ --resource-group <ResourceGroupName> \ --name <AKSClusterName> \ --node-count 1 \ --vm-set-type VirtualMachineScaleSets \ --load-balancer-sku standard \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 3
導入時は Cluster Autoscaler を使わずに、Node 数を固定して運用を開始する方法もありだと思います。
障害が発生する前提で構成を決める
Master Node
Master Node は、マネージドサービスとして隠蔽されているため、Azure 側に管理を任せます。AKS としてマネージドサービスで利用する大きなメリットの1つです。
Node
障害によって非アクティブと判断された Node に配置されている Pod は、別の Node に再デプロイされるため、余裕を持たせた Node 数で運用する必要があります。
仮想マシンスケールセット(VMSS)の可用性セットによって、Node の仮想マシンは異なるラックに配置されています。Availability Zone を利用すると、1リージョン内で物理的に分離して Node の仮想マシンを配置することができます。
AKS Cluster はリージョンをまたげないので、大規模な DR を構成する場合には、複数の AKS と他のサービスを組み合わせた対応が必要となります。
- Azure Traffic Manager
- Azure Cosmos DB
Pod
Pod については、Deployment の YAML で下記の3つの項目を設定しておきます。
リソース | 説明 |
---|---|
Replica Set | 指定した Pod 数に満たない場合、自動的に新しい Pod を作成します。 |
Liveness Probe | Pod(Container)の死活監視です。応答が返ってこない場合、自動的に Pod が再起動されます。 |
Readiness Probe | Pod(Container)がリクエストを受け付けられる状態の監視です。エラーを返す場合、Kubernetes がリクエストを送信しません。バックエンドのデータストアをチェックする API などを作ります。 |
livenessProbe: httpGet: path: / port: 80 readinessProbe: httpGet: path: /readiness port: 80
Azure Monitor でマイクロサービスを監視する
マイクロサービス全体で何が起きているのかを把握するため、Azure Monitor for Containers と Application Insights を使ってメトリクスとログを収集します。AKS としてマネージドサービスで利用する大きなメリットの1つです。
Azure Monitor for Containers
Kubernetes Cluster の Node や Pod から、メトリクス(Memory / CPU)とログ(stdout / stderr)を収集し、Log Analytics へ送信します。KQL(Kusto Query Language)のクエリで抽出できるので、必要に応じてアラート通知を設定します。
Application Insights
アプリケーションにライブラリを追加し、テレメトリデータを送信します。分散トレーシングにより、マイクロサービス におけるパフォーマンスのボトルネックやエラーの根本原因を追跡できます。
まとめ
Azure Kubernetes Service を活用したマイクロサービス開発のベストプラクティスを紹介しました。
マイクロサービスを実現する手段は、Kubernetes だけではありません。本当に Kubernetes が必要かどうかを十分に検討しましょう。
- リリース後、サービスが頻繁にアップデートされますか?
- 新しいサービスが頻繁に追加され、サービスの数が増えていきますか?
Kubernetes を採用するなら、シンプルな構成から始めることを推奨します。すべての機能を使わず、必要な機能を選択して利用しましょう。あえて制約を課すことで、シンプルさを優先する選択もあります。
参考リンク
Helm を使用して Azure Kubernetes Service (AKS) で開発する - Azure Kubernetes Service | Microsoft Docs
イングレス コントローラーを作成する - Azure Kubernetes Service | Microsoft Docs
概念 - Azure Kubernetes Service (AKS) でのアプリケーションのスケーリング - Azure Kubernetes Service | Microsoft Docs
Azure Kubernetes Service (AKS) での可用性ゾーンの使用 - Azure Kubernetes Service | Microsoft Docs
Liveness Probe、Readiness ProbeおよびStartup Probeを使用する | Kubernetes
Azure Monitor for containers での Kubernetes の監視 - Azure Monitor | Microsoft Docs