銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

kubernetes の Azure Cloud Providerについてあれこれ

kubernetes2 Advent CalendarとひとりAdvent Calendar2日目の記事です。

qiita.com

adventar.org

仕事としてはOpenShiftをやっているので、OpenShift on Azureまわりでいろいろ調査するのですが、今日はkubernetes をAzureで動かす場合に利用できるAzure Cloud Providerについて、なんとなく自分の知っていることをまとめておこうかと思います。ManagedなAKSだけでなく、ACSを利用した場合やマニュアルでAzure上の仮想マシンにkubernetesをインストールした場合、またOpenShift をAzureにインストールした場合、どれでもいずれにも共通な話をします。また、ドキュメントをリンクしつつ、補足するスタイルでまとめているので、不足している点や最新の情報はリンク先を参照ください。

Azure Cloud Providerとは

kubernetesにはCloud Providerという仕組みがあり、Cloud Platformでkubernetesを動かす場合にそれぞれのCloud固有の機能をkubernetesと統合させてより便利に利用することができます。

kubernetes.io

たとえば、persistent volume(永続化ディスク)はCloud Platformごとのストレージサービスを利用する実装となっていて、AzureだとAzure DiskとAzure Fileが利用可能です。Clout Platform上で動かす場合でもCloud Providerを有効化することは必須ではないのですが、ストレージサービスを永続化ディスクに使えないなど制約が多くなってしまいます。

Azure Cloud Providerの有効化

Cloud Providerの有効化は、先程のkubernetesのドキュメントの通り、設定ファイルを作成してそのパスを指定します。設定ファイルに記載するパラメーターはCloud Providerにより異なりますが、Azureの設定についてはこのページによくまとまっています。

cloud-provider-azure/cloud-provider-config.md at master · kubernetes/cloud-provider-azure · GitHub

APIの認証設定

Cloud ProviderはCloud PlatformのAPIを実行するため認証に関する設定があります。Azureの場合はManaged Identity、Service Principal、クライアント証明書が選択できます。Service Principalの場合の作成手順は以下のドキュメントにあります。

acs-engine/serviceprincipal.md at master · Azure/acs-engine · GitHub

APIの実行権限ですが、kubernetesが存在するリソースグループに対するcontributor roleと記述されています。おそらくテストもこれで実行されているのでより細かい権限設定をしたいばあいは自分でコードを確認しテストする必要がありそうです。

ちなみにこの設定ファイルに対応するgoのコードはここになります。

kubernetes/azure.go at release-1.13 · kubernetes/kubernetes · GitHub

ドキュメントだけ古くなった場合など、設定に過不足が生じた場合はここを参照するとよいでしょう。実際、LoadBalancerSku とかいうパラメーターがソースコードにあるのですが、これはLoadBalancer Type Serviceのところで説明します。

またリソースグループに対して設定とありますが、単一のリソースグループにkubernetesクラスター全体を配置することが想定されていましたが、kubernetes 1.12からまたぐこともできる設定が追加されているようです。

cloud-provider-azure/using-cross-resource-group-nodes.md at master · kubernetes/cloud-provider-azure · GitHub

OpenShiftの場合、今のところテストされてドキュメントに記載されているのはService Principalのみとなっています。

Configuring for Azure | Configuring Clusters | OpenShift Container Platform 3.11

その他の設定

その他の設定は記載されている通りの値を指定すればよいです。ネットワーク設定やロードバランサー関連の設定はLoadBalancer-typeなサービスに利用されます。cloudProviderBackoffcloudProviderRateLimitとそれに関連する値は、Azure API実行時のリトライやレート制限を設定する際に利用します。巨大なkubernetes クラスターの場合、APIの実行頻度もかなり高くなるので、レート制限にかかったり、一度失敗したあとのエラーの頻度も高くなったりすることがあります。そのような場合に備えた設定となっているようです。

Azure Cloud Providerの主な機能

Azure Cloud Providerを有効化することで利用できるようになる大きな機能としては、ストレージサービスとLoadBalancer-typeサービスです。この2つを少し掘り下げてみます。(あと、VMSSによるauto scaleのサポートなどもCloud providerがないと動かないはずですが、この記事からは割愛させてください)

ストレージサービス

Azure DiskとAzure Fileがkubernetesのpersistent volumeとして利用できます。AKSのドキュメントですがAKS固有の話はあまりないので、このページがわかりやすいです。

docs.microsoft.com

具体的な使い方はkubernetesのドキュメントに記載があります。

Persistent Volumes - Kubernetes

Storage Classes - Kubernetes

Azure DiskはDiskの作成や管理、podが配置されたnodeのVMへのDiskの接続などAzure REST APIを実行する必要があるのがわかりそうですが、Azure Fileは接続情報をStorageClassやPersistent Volumeに記載するのでCloud Provideは有効化する必要はない気もします。が、いまの実装を読む限り、Cloud Providerが有効化されないとAzure Fileの機能が有効化されないようになっていそうです。

Azure Diskの利用はエラーが発生することもままあるのですが、ここに既知の問題がまとまっているのでここを確認するのがいいでしょう。

cloud-provider-azure/azuredisk-issues.md at master · kubernetes/cloud-provider-azure · GitHub

Azure Fileの場合はこちらです。

cloud-provider-azure/azurefile-issues.md at master · kubernetes/cloud-provider-azure · GitHub

またOpenShiftの場合は、有効なサブスクリプションを持っているアカウントでレッドハットのナレッジベースを御参照ください。

Azure Fileの方が御気軽に使える感はあるのですが、Azure FileをLinuxシステムからマウントする場合にいくつか注意点があるので確認しておくのがよいです。例えばデフォルトのマウントオプションのままだとsymbolic linkが作れません。

docs.microsoft.com

そのデフォルトのマウントオプションの権限もバージョンによって異なっているので注意が必要です。1.10以降は変更が今のところないので、その意味でも1.10以降がおすすめです。

f:id:tanaka733:20181126003545p:plain

そもそもDBMSやCassandraなどの製品はAzure Fileのような種類のストレージをサポートしないもしくは推奨しないことがあるので、そのような場合はAzure Diskを使うことになるでしょう。

Type LoadBalancer Service

kubernetesのServiceにLoadBalancer Typeというのがあり、Cloud Platform上では固有のLoadBalancerサービスをプロビジョニングして利用できます。AzureではALBが利用できます。

Services - Kubernetes

なぜかkubernetesのドキュメントはAWSについてのみ詳細な機能の説明がありますが、ALBでも詳細な機能が設定できます。こちらのドキュメントが確認できます。

cloud-provider-azure/development-loadbalancer.md at master · kubernetes/cloud-provider-azure · GitHub

最初にも書いていますが、Load Balancer as a Serviceについては各Cloud Platformで機能や制約が異なっており、そこに注意しないと嵌ることがあります。Azure Load Balancerの場合、まずStandardとBasicの2つのSKUがあります。デフォルトではBasicが使われるようになっており、Standardを使いたい場合はAzure Cloud Providerの設定ファイルに次のように追加します。ExcludeMasterFromStandardLBをtrueにすると、Load Balancerのバックエンドプールからmasterの仮想マシンを除外できます。

LoadBalancerSku: standard
ExcludeMasterFromStandardLB: true

ここからは、デフォルト設定であるBasic SKUの場合として説明します。Basic SKUで問題となるのが、ALBのバックエンドプールは単一の仮想マシンもしくは可用性セットでなくてはならない、という制約になります。そのため、LoadBalancer type Serviceを使う場合、kubernetesのnode群は単一の可用性セットに配置する必要があります。また、kubernetesのmasterをHA構成しそのLoad BalancerとしてALBを使う様な場合、masterの所属する可用性セットとnodeの所属する可用性セットは別にする必要があります。このような制約はありますが、その代わりにALBは複数のフロントエンドIPを持つことができるので、複数のPodに対しそれぞれ別のフロントエンドIPを割り振りルーティングさせることができます。このあたりの仕組みはAWSやGCEのCloud Providerを使った場合と異なると思います。

また、Cloud Platformのmanaged Load Balancerサービスはそれぞれ別の機能があるのですが、その機能をkubernetesから利用するためにannotationを使うことができます。Azureの場合の利用例は先程のページにあります。

cloud-provider-azure/development-loadbalancer.md at master · kubernetes/cloud-provider-azure · GitHub

service.beta.kubernetes.io/azure-load-balancer-internalservice.beta.kubernetes.io/azure-load-balancer-internal-subnetはInternal Azure Load Balancerを指定したsubnetに配置することができます。kubernetes clusterをprivate VNetに配置している場合などに便利です。

service.beta.kubernetes.io/azure-load-balancer-modeは少し変わった機能ですが、ノードが単一の可用性セットに配置できないため、複数の可用性セットにまたがっている大規模クラスターを利用している場合には有益な機能です。使わない場合にはこのアノテーション自体を指定しません。その場合、Load Balancerは設定ファイルのprimaryAvailabilitySetNameで指定された可用性セットをバックエンドプールに追加します。指定する場合、autoもしくは{name1},{name2}という値を指定できます。autoの場合は適当に1つ選ばれた可用性セットにLoad Balancerが配置されます。{name1},{name2}では可用性セットの名前をコンマ区切りで指定し、指定された可用性セットごとにAzure Load Balancerを配置します。

service.beta.kubernetes.io/azure-dns-label-nameはフロントエンドのIPにDNSラベルを設定することができます。他にもアノテーション経由で設定できる項目があり、今後も増える可能性があるのでリリースノートをチェックするのがおすすめです。

AADによる認証

Azure Cloud Providerに関係しそうで、しない機能の紹介です。kubernetesのmasterへの認証をAAD OpenID Connectを利用することができるのですが、これはCloud providerを無効化していても利用できます。また、そもそもAzure上でない kubernetesクラスターからも利用できるはずです*1

仕組みとしてはkubernetesがOpenID Connectに対応しており、OpenID ConnectのproviderとしてAAD OpenID Connectが利用できる、という流れになります。

Authenticating - Kubernetes

ですので、AADではなくADFSのOpenID Connectも利用できますし、ADに限らない一般的なOpenID Connectと同様の設定手順となります。

Azure Stack

Azure StackでのCloud Providerの有効化については、表に出ている情報としてはできないはず、です、多分。最初の設定のところにcloudというパラメーターがあるのですが、これが取り得る値は次の4つとなっています。

go-autorest/environments.go at v9.9.0 · Azure/go-autorest · GitHub

AZUREPUBLICCLOUDAZUREGERMANCLOUDAZURECHINACLOUDAZUREUSGOVERNMENTCLOUDとAPIのエンドポイントそのものではなく、その名前を指定することになっています*2。Azure Stackの場合、その環境毎のエンドポイントの設定が必要なはずなのですが、そのエンドポイントを設定する場所がないのではというのが私の見解です。

が、Azure Stackのドキュメントによれば次のように記載されているので実はできるようになっているのかもしれません。ちなみにこのドキュメント先頭に書いてますが、AKSではなくてACS Engineを使ったkubernetesテンプレートをAzure Stackに展開しています。

Service Principal ClientId を入力します。これは、Kubernetes Azure クラウド プロバイダーによって使用されます。

docs.microsoft.com

残念ながら私は検証できる環境がないので、検証可能な方のレポートを待ちたいと思います。

*1:確認したことはないが原理的にはできるはず

*2:逆にいうと、ドイツ、中国、US政府向けのAzure上ではCloud Providerを有効にできるはずです