はじめに
MS Ignite 2019というMicrosoft社のイベントで
Mohammad Nofalさんにより話されていた、
AKSのクラスタ管理と高可用性に関するベストプラクティス
(原題: Applying best practices to Azure Kubernetes Service (AKS))
について内容を紹介します。
前編では高可用性設計について説明します。
大まかにはMohammad Nofalさんの説明に沿ってますが、
自分が説明するとしたらこんな感じかな…という風に作成したので
Nofalさんのセッションもご参照いただけると幸いです。
参考資料
映像
https://myignite.techcommunity.microsoft.com/sessions/81598?source=SessionDeck
ソースコード等(スライドもあります)
翻訳したスライド
概要
セッションの内容は次の二つの観点からベストプラクティスについて説明した内容です。
1. 高可用性設計に関するベストプラクティス
SLAを高いレベルに保つためには高可用性設計(Availability)は欠かせません。そしてそれはAKS単体ではなく、AKSを含むシステム全体の設計をどのように構成すればいいかという巨視的な視点から考える必要があります。さらにはAKSで動くサービスがステートレスかどうかにより、設計の考慮すべきポイントは広がります。
セッションではそのような観点を踏まえて高可用性設計のベストプラクティスを説明します。
2. クラスタ管理に関するベストプラクティス
AKSに限らずKubernetesを運用するには、Kubernetesの開発スピード…三ヶ月おきにマイナーバージョンが更新される頻繁なバージョン更新と足並みを揃えてアップグレードを行う必要があります。また、セキュリティパッチなどワーカーノードを構成するマシンへの定期的な保守も欠かせません。
AKSのクラスタ管理(Cluster Management)に関するベストプラクティスとして、アップグレードやセキュリティパッチの更新をAKS上で運用するアプリに影響を与えないで行う方法について説明します。
高可用性設計に関するベストプラクティス
高可用性設計に関するベストプラクティスを説明する前に、
AKSのベースであるKubernetesのアーキテクチャについて確認しましょう。
Kubernetesのアーキテクチャは主にコントロールプレーン(マスターノード)と呼ばれるKubernetes上の司令塔にあたるものと、ワーカーノードと呼ばれるコンテナの実行環境の二つに大きく分かれます。
では、それぞれについてAKSの可用性を担保しようとしたらどうすればいいでしょうか?まずはコントロールプレーンについて見てみましょう。
AKSの可用性(コントロールプレーン/マスター)
AKSのコントロールプレーンは課金されません。実際にワーカーノードを構成するMC_から始まるリソースグループのVMを全て停止するとわかるのですが、あくまでVMを含むコンポーネントにのみ、AKSは課金されます。したがって、AKSはSLOとして99.5%の稼働率を定めているものの、SLAのように確約ではありません。
では、コントロールプレーンが停止したらどうなるのでしょうか?kube-apiは停止されるため、Podのスケールや新たなデプロイなどは確かにできません。しかし、現在動いているアプリケーションには影響を与えません。(注: データスパイクが発生して、今すぐ ACIを借りなくては!!みたいな自体でもなければ)
したがって、AKSの可用性設計を考えるときは後述するワーカーノードに対してどれくらいのSLAを要求するかを基準に可用性設計を考えた方がいいでしょう。
AKSの可用性 (Kubernetes ワーカーノード)
AKSはVMのSLAを最低限担保しているため、ワーカーノードについてはデフォルトで99.5%のSLAを担保しています。
基本的にAKSのワーカーノードは複数台のVMで構成されるため(VMAS、VMSS)、99.95%のSLAを得られます。さらにマルチAZに対応したクラスタ構成では、99.99%のSLAを得られます。
これらのSLAはどのようにAKSのワーカーノードを構成すれば担保されるのでしょうか?
AKS上で動くサンプルアプリケーションを用意しました。
LB — サーバーサイドのアプリケーション — DBで構成された
シンプルなアプリケーションです。
可用性の考慮事項はスライドのようにたくさんありますが…
この中で最も重要なのは、状態管理が必要か、つまりステートフルかステートレスのどちらかであることです。
例えばサンプルアプリケーションを例にとった場合、DBに対して次の操作を行うユースケースが考えられます。
- 問い合わせに応じて単純にDBを検索し、データを返すサービス
2. 状況に応じて書き込みを行いデータを逐次更新しながら、参照結果とステータスを返すサービス
前者のサービスはただデータを返すだけです。つまり状態が必要ないステートレスなサービスと言えます。
後者のサービスではデータの書き込みが発生します。
書き込むリクエストが単一ならば状態管理は不要ですが、常に複数の書き込みと参照が発生するとしたらどうでしょうか?
データベースのデータは時々刻々と変わっていきます。そしてそれはタイミングにより常に違う値を返します。
トランザクション管理と一般的には言われますが、状態を変化させる処理に対して制御が欠かせません。
つまり、状態管理が必要なステートフルなサービスと言えます。
AKS上で動かしたいサービスがステートレスかステートフルか、
AKSの可用性を考慮する上で非常に大きな問題となります。
クラスターノードの可用性オプション
さて、それではAKSのワーカーノードの可用性をどうやって担保するか、
具体的な方法を探していきましょう。
大きく四つの方法を紹介します。
- バックアップ&リストア
- Availability Zonesにまたがってワーカーノードを構成する
- リージョン内に複数のクラスタを構築する
- リージョン間で複数のクラスタを構築する
AKSの可用性を考えるうえで、コストや設計や運用を複雑にしたくない場合は1>2>3>4です。後者になるにつれて、コストは高くなり、より設計や運用は複雑になります。
一方でシステムの障害時、可用性が求められるシーンではどうでしょう。
4>3>2>1の順番で推奨します。後の方がシステム復旧により時間がかかり、また完全にはデータが戻らない可能性があります。
このようにメリット、デメリットがそれぞれ相反するので、
AKSの可用性を考慮するうえで、SLAがどこまで求められるか、そしてサービスはステートフルかどうかはよくよく考えたほうがよいでしょう。
バックアップとリストア
バックアップとリストアは可用性を担保できるお手軽な方法です。
サービスがステートレスクラスタかステートフルクラスタにより違いがありますが、どちらの場合でもcluster deployment as code …つまり、コードによりクラスタのデプロイ方法を記述することで、迅速にアプリケーションをデプロイできる体制を整える必要があります。
ステートフルクラスタの場合、アプリケーションに加えてステートの復旧が必要です。
例えば、ストレージに保存したデータの復旧を行いたい場合、どうすればよいでしょうか?
AKSでは次の二つの手段が考えられます
- Azure Snapshot API
VMのディスクのスナップショットを取得する方法です。ただし、いくつか制約事項があります。Kubernetes nativeなサービスではありませんし、APIを呼び出すにはPowershellのコマンドを利用するしかありません。 - Heptio/VMwareのVeleroというOSS
今回はこちらを紹介します。VeleroはKubernetesクラスタのアプリケーションと永続化ストレージのバックアップ&リストアを行うことができるOSSです。Kubernetesネイティブなソリューションなので、AKSと一貫した操作が可能です。
もしVeleroを使用する場合、バックアップ処理を自動化することを推奨します。
Veleroを使用した具体的な事例を一つ紹介します。
その他、Veleroの使い方は https://velero.io/ を参照してください。
Availability Zones
AZ(アヴェイラビリティゾーン)を超えてノードを分散配置したAKSを作成するとより高い可用性を得ることができます。
※日本では東日本リージョンのみ、AZをサポートしています。
西日本は対象ではないのでご注意ください。
ワーカーノードをAZに分散配置した図です。
構築するためにはコマンドでzoneを指定する必要があります。
az group create --name myResourceGroup --location eastus2az aks create \
--resource-group myResourceGroup \
--name myAKSCluster \
--generate-ssh-keys \
--vm-set-type VirtualMachineScaleSets \
--load-balancer-sku standard \
--node-count 3 \
--zones 1 2 3 #Multiple AZs 対応
複数のクラスタ/複数のリージョン
複数のクラスタにより可用性の構成を組みたい場合、データベースに対する責務をサービスごとに分けた方が良いでしょう。
基本的にはAzureのサービスであるTraffic Managerを使用して読み込み専用のクラスタと書き込み/読み込みを行うクラスタを分けて、読み込み専用クラスタは障害発生時のバックアップとして備えます。
”Multiple Clusters-Same Region” は一つのリージョン内に複数のAZにワーカーノードを分散配置した例です。ヒューマンエラーによる障害にのみ可用性を持つことに注意指定ください。リージョンでの障害に対しては無力です。
“Multiple Clusters-One Master Hot” は複数のリージョンにワーカーノードを分散配置した上で、一つのリージョンのみ書き込み機能を持たせた例です。
二つのリージョンに書き込み機能を持たせた場合、トランザクション管理という永遠の課題にぶつかるのでできません…またACRへのコンテナイメージのデプロイはリージョンごとに必要です。
“Multiple Clusters-Cold/Scaled Down”はコストを節約したパターンになります。普段は停止しておき、障害発生時に他のリージョンで読み込みだけ行える縮退運転を行います。
”Multiple CLusters-Cross Region-Multiple Masters”はCosmos DBをバックエンドのDBに用いることでリージョンを問わず、書き込みを可能にしています。Cosmos DBを使用すれば、どのリージョンにあるクラスタからも書き込み操作を行えますが、一番コストがかかります。
後編(クラスタ管理)に続きます。
Thank you!!