ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure Kubernetes Service を活用したマイクロサービス開発のベストプラクティス

この記事は、Cloud Nativeアプリケーション開発のTips!日本マイクロソフト Advent Calendar 2020 の 15 日目 の記事です。
qiita.com

1年ほど前の Microsoft Ignite The Tour で、「Azure Kubernetes Service を活用したマイクロサービス開発」というタイトルでブレイクアウト セッションに登壇したのですが、現在でも通用するベストプラクティスだと思いますので、文章に起こしてみました。

gooner.hateblo.jp

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 はマイクロサービス側で管理するようにしています。

f:id:TonyTonyKun:20201213113446p:plain

Azure ポータルから設定できる HTTP Application Routing アドオンのほうがお手軽ですが、本番運用は非推奨となっています。

アップグレード戦略には Blue / Green デプロイを採用する

マイクロサービス のアップグレード

変更頻度の高いものをマイクロサービスとして切り出すわけですから、マイクロサービス のアップグレードをどのように実現するのかは非常に重要です。
Blue / Green デプロイにより、更新中の一時的な Pod 数の減少を回避し、障害発生時に素早く切り戻せるようにしておきます。

いくつか実現方式はあるのですが、私の経験では Label Selector の Version を変更して、アクセスする Pod を切り替えることが多いです。

f:id:TonyTonyKun:20201213113616p:plain

Blue / Green デプロイのためだけにサービスメッシュ(Istioなど) を導入するには、コストが高く、複雑になりすぎると考えています。

Kubernetes Cluster のアップグレード

意外と考慮事項から漏れてしまうのが、Kubernetes Cluster のアップグレードです。Kubernetes の更新サイクルの速さにどのように追随していくのか、しっかりと検討しておくべきです。
AKS には Kubernetes Cluster をインプレースでアップグレードする方法が提供されていますが、本番運用ではリスクが大きいので採用したくありません。
Blue / Green デプロイにより、動作確認済みの Kubernetes Cluster を Production として利用し、障害発生時に素早く切り戻せるようにします。

f:id:TonyTonyKun:20201213113716p:plain

この方式をシンプルに実現するため、あえて 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つです。

f:id:TonyTonyKun:20201213113820p:plain

Azure Monitor for Containers

Kubernetes Cluster の Node や Pod から、メトリクス(Memory / CPU)とログ(stdout / stderr)を収集し、Log Analytics へ送信します。KQL(Kusto Query Language)のクエリで抽出できるので、必要に応じてアラート通知を設定します。

f:id:TonyTonyKun:20201213113915p:plain

Application Insights

アプリケーションにライブラリを追加し、テレメトリデータを送信します。分散トレーシングにより、マイクロサービス におけるパフォーマンスのボトルネックやエラーの根本原因を追跡できます。

f:id:TonyTonyKun:20201213114032p:plain

まとめ

Azure Kubernetes Service を活用したマイクロサービス開発のベストプラクティスを紹介しました。
マイクロサービスを実現する手段は、Kubernetes だけではありません。本当に Kubernetes が必要かどうかを十分に検討しましょう。

  • リリース後、サービスが頻繁にアップデートされますか?
  • 新しいサービスが頻繁に追加され、サービスの数が増えていきますか?

Kubernetes を採用するなら、シンプルな構成から始めることを推奨します。すべての機能を使わず、必要な機能を選択して利用しましょう。あえて制約を課すことで、シンプルさを優先する選択もあります。