Kubernetes CloudService Operatorがもたらす未来について

公開:2020/09/28
更新:2020/10/05
9 min読了の目安(約8500字IDEAアイデア記事

前置き

鳥さんによるプラットフォームの上でものを作るということの記事を一読した後でこちらのエントリ記事を読むと理解が捗ります。

Kubernetes CloudService Operatorとは?

下記のクラウドプロバイダーによるプロダクト(OSS)の総称です。自分が勝手に名前をつけました。

これらのサービスに共通する機能とは何でしょうか?

  • クラウドプロバイダーのサービス(VMやBlob Storage)をKubernetesから操作するIaCツール
  • 操作は、Kubernetes上のリソースファイルと同じようにyamlファイルをデプロイして行う
  • Custom Controller/Operatorと呼ばれる、Kubernetes固有のフレームワークを利用している

これらのプロダクトが開発された背景を掌握せずに、単純に機能だけを見たら『Kubernetesからクラウドプロバイダーのサービスを呼び出すだけじゃん』と思われる方がいらっしゃるかもしれません。

しかし、これはKubernetesと各クラウドプロバイダーの設計、要件、思想が異なるプラットフォーム同士を円滑に結ぶために重要なプロダクトです。さもなければ、単純に横並びでクラウドプロバイダーがこの機能を実装するはずもありません。

これからKubernetes CloudService Operator for Kubernetes(以下、k8s CloudService Operator)の目的について説明したいと思います。

ちなみにAWSはService Operator、AzureはService Brokerという似たようなサービス管理ツールがあったのですが再設計、deprecatedにしてこちらのプロダクトを開発しています。

Kubernetes CloudService Operatorの目的とは?

Kubernetes CloudService Operatorの目的は、クラウドサービス上に二つのプラットフォームが乗っているということを踏まえて、両者を接続することです。

プラットフォームとはシステムを動かし、ビジネスの課題を解決するための基盤と定義します。すると、Kubernetesもクラウドもそれ自体が単体でプラットフォームになりえることに気づくでしょう。片方は複数のコンテナを動かして"システム"を作り出し、クラウドでは一つ一つのサービスを組み合わせることで"システム"を作り出し、その結果、ビジネス課題を解決するための目的に応じた処理を行います。

両者は結果として同じ目的を果たしますが、出自の違いゆえに大きな違いがあります。特に自動化に関してKubernetesの設計思想である「宣言的設定」と「リコンサイルループ」は自動化のあり方を大きく変えました。説明はKubernetesがいかに自動化の考え方を変えたか?に譲りますが、端的に言えばKubernetesの自動システム構築機能、それに付随する自動修復機能は超凄いのです。

そこで立場があやふやになるのがAKS, EKS, GKEなどクラウドプロバイダーが提供するManagedなKubernetesです。彼らはクラウド上にあるのでコンテナランタイム環境に必要なVMやVM間の仮想ネットワーク、外部に接続する際のLoadBalancerはクラウドプロバイダーに頼っています。一方でKubernetesのプロダクトはコアはKubernetesのコミュニティが開発し、クラウドベンダーでは k8s-cloud-provider (名前がややこしくてすみません)と呼ばれる適合部分を開発しているにすぎません。

このクラウドベンダーによるManaged Kubernetesを活用してシステムを作った時、何が起きるでしょうか。クラウドとKubernetesのいいとこどりと言えばいいですが、出自の違うプラットフォームを組み合わせて長時間使うと問題を生じさせます。

AzureのAKSを軸としたマイクロサービスアーキテクチャ図を見てみましょう。

Microservices architecture on Azure Kubernetes Service

参照: https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/containers/aks-microservices/aks-microservices

この絵で中心となるのはAKSです。AKS上で主要なアプリケーションが動いていますが、実際はAKS単体で完結できず、その周りにアプリケーションを支える様々なクラウドサービスが動いていることがわかります。

  • AKSに外部からリクエストを送る際にAzure Load Balancerを経由
  • AKSとの管理にAzureAD認証やRBACを適用
  • AzureMonitorで監視
  • AzureCosmosDBやAzureSQLDatabaseなどのデータストアを活用

これらのサービスで次々にインシデントとなる障害が発生したとしましょう。SREチームの担当者はAzureのManaged Service, Kubernetesの操作知識を要求された上でAzureMonitorを通してそれらのどこに原因があるのか、サービスを横断して参照する必要があります。非常に難易度が高いと言えるのではないでしょうか。

どうしてこのようなことになるのでしょう。

  • ビジネスを担うロジックはKubernetes上へ集約
  • 一方で運用目線で必要とされる各サービスのIFは共通化できていない
  • 共通化しようにも、出自が異なるプラットフォームなのでそれぞれの観点がおのずと異なる
  • その結果、全てのサービスを知った上で最大公約数な知識と動きを求められる

障害時を例に挙げましたが、単純にライフサイクル上、バージョンアップなどを伴うときも同様だと考えてください。
つまり、プラットフォームという作られた思想背景が違うモノ同士が合わさった結果、開発時はともかく、継続的な運用を行うにあたり、幅広く知識を押さえることは避けられません。

そこで、k8s CloudService Operatorの登場です。
k8s CloudService Operatorでは、Kubernetesの運用を自動化するための「宣言的設定」と「リコンサイルループ」という思想に従って、クラウドリソースの運用の自動化を実現します。

Kubernetes側の運用者の思想をクラウドサービスに持ち込んだサービスと言えます。そのうえで、マニフェストファイルなど操作を全てKubernetes側に寄せることにより、プラットフォーム、作られた出自が異なる両者をうまく融合しています。

わかったところで使ってみようぜ

冒頭でも説明しましたが、各クラウドプロバイダーがプロダクトを出しています。

各クラウドプロバイダーごとに細かいお作法の違いがあると思いますが、ここではAzure Service Operatorを取り上げます。

認証周り

手順書を書いていて、そういえばと思ったので先に記載します。
各クラウドプロバイダーが自社のサービスを呼び出すためにCloud Service Operatorを展開していますが、基本的に各社のManaged Kubernetes以外でも動きます。つまり、Managed Kubernetesにロックインされていないので、各クラウドサービスとの認証周りは自分で用意、セットアップする必要があります。

例えばAzure Service Operatorは次の選択肢があります。

  • サービスプリンシパル
    • Azure以外のKubernetes環境からAzure Service Operatorを使うときはこれを使用します。
    • いわゆるアクセストークンです。Azureでは、サービスプリンシパルという踏み台代わりの認証を行うアカウントを用意してそこ経由でAzureリソースにアクセスできます。
    • アクセストークンを腹持ちする必要があるため、kubernetes上でベタにトークンを扱うのではなく、secretstoreなど別途サービスを利用したほうがいいでしょう。
  • ManagedID
    • AzureKubernetesServiceなど、Azureリソース内部から別のAzureリソースにアクセスするときに使用します。
    • AWS畑の人ならS3にアクセスするときのIAMロールって言えば大体通じるかと...
  • AzureAD Pod Identity
    • Microsoftが開発しているManaged IDをさらにAKS内で使いやすくしたOSSです
    • ManagedIDを使用した場合、VM, VMSS単位で権限を割り振るため、Podごとに細かくリソースのアクセス権限を制御したいという要求にはこたえられません。そのため、このプロダクトが開発されました。
    • Azure AD Pod Identityの簡単な紹介 の資料で以前ざっくり説明しているのでお時間があればこちらもご参考になれば幸いです。

Kubernetesから、とはいえ、クラウドサービスのリソースは対応するものであれば基本何でも作れてしまうので、プロジェクトの要求するセキュリティレベルと運用現場(マルチテナントか、運用しているチームは複数か等)に応じて適切な認証方法を選んでください。

Azure Service Operatorのセットアップについて

基本的に README.md を読めばサービスプリンシパルを利用する形で簡単にAzure Service Operatorのセットアップができます。

Azure Service Operatorの利用方法について

リージョン westusresourcegroup-azure-operators という名前のリソースグループを作りたい場合、下記の通りyamlを用意してapplyするだけです。

$ cat <<EOF | kubectl apply -f -
apiVersion: azure.microsoft.com/v1alpha1
kind: ResourceGroup
metadata:
  name: resourcegroup-azure-operators
spec:
  location: "westus"
EOF

ログでは下記の通り出力されます。

$ kubectl logs -f azureoperator-controller-manager-6db75f56fd-gn2tr -c manager  -n azureoperator-system
(中略)
2020-10-05T07:01:43.742Z        DEBUG   controller-runtime.manager.events       Normal  {"object": {"kind":"ResourceGroup","namespace":"default","name":"resourcegroup-azure-operators","uid":"7abf2be6-8152-403d-ab50-a9d4cafb8a86","apiVersion":"azure.microsoft.com/v1alpha1","resourceVersion":"16641"}, "reason": "Added", "message": "Object finalizer is added"}
2020-10-05T07:01:43.751Z        DEBUG   controller-runtime.controller   Successfully Reconciled {"controller": "resourcegroup", "request": "default/resourcegroup-azure-operators"}
2020-10-05T07:01:43.751Z        INFO    controllers.ResourceGroup       reconciling object      {"Info Type": "status", "Component": "ResourceGroup", "Instance": "default/resourcegroup-azure-operators"}
2020-10-05T07:01:45.120Z        INFO    controllers.ResourceGroup       success {"Info Type": "reconciling", "Component": "ResourceGroup", "Instance": "default/resourcegroup-azure-operators"}
2020-10-05T07:01:45.120Z        DEBUG   controller-runtime.manager.events       Normal  {"object": {"kind":"ResourceGroup","namespace":"default","name":"resourcegroup-azure-operators","uid":"7abf2be6-8152-403d-ab50-a9d4cafb8a86","apiVersion":"azure.microsoft.com/v1alpha1","resourceVersion":"16649"}, "reason": "Reconciled", "message": "Successfully reconciled"}
2020-10-05T07:01:45.121Z        INFO    controllers.ResourceGroup       duration        {"Info Type": "duration", "Component": "ResourceGroup", "Time": "2.120666 seconds"}
2020-10-05T07:01:45.121Z        INFO    controllers.ResourceGroup       exiting reconciliation  {"Info Type": "status", "Component": "ResourceGroup", "Instance": ""}
2020-10-05T07:01:45.121Z        DEBUG   controller-runtime.controller   Successfully Reconciled {"controller": "resourcegroup", "request": "default/resourcegroup-azure-operators"}
2020-10-05T07:01:45.121Z        INFO    controllers.ResourceGroup       reconciling object      {"Info Type": "status", "Component": "ResourceGroup", "Instance": "default/resourcegroup-azure-operators"}
(中略)

障害時の挙動(未検証)

詳しい方がいらっしゃったら、まさかりください。

Azure Service OperatorはKubernetesのCustom Controllerなので自己回復能力があります。つまり、クラウドサービス側でリソースグループを誤って消してしまっても復活する...はずなのですが、一時間待っても反映されませんでした。

現状はクラウドサービスからAzure Service Operator側へのEvent通知をソースコードを見る限り行っていないため、クラウドサービス側でリソースグループを消してしまった場合、kube-controller-managerの仕組みに従って --min-resync-period の設定値(デフォルト12時間)のタイミングでresyncが入り、検知すると思われます(未検証)。

ちょっとこの辺検証するのがしんどかったので、機会があれば調査したいと思います。

まとめ

Azure Service Operatorなど各クラウドプロバイダーが自社のクラウドサービスをKubernetesから呼び出すKubernetes CloudService Operatorを開発していることを紹介しました。

一度セットアップしてしまえば、使い方は非常に簡単です。また、リソースの自己回復機能などKubernetesの機能も受け継いでいるためその機能の恩恵に授かることができます。

Kubernetes CloudService OperatorはクラウドとKubernetes、二つのプラットフォームの懸け橋として今後の機能拡充、活動が期待されます。

あとがき

Creepy Nutsの「たりないふたり」「よふかしのうた」を聞きながらヒャッハーしつつ書きました。