はじめに
こんにちは、ACS事業部の吉川です。
皆さんはIaC(Infrastructure as Code)にどんなツールを使っていますか?
今回のブログでは、AzureのリソースをKubernetesのカスタムリソースとして管理できる Azure Service Operator をご紹介します。
Azure Service Operator とは
以前にもKubernetesからAzureリソースをコントロールする仕組みとして Open Service Broker for Azure(OSBA) というものがありました。
OSBAはCloud Foundry由来のOpen Serice Broker APIの仕様に則った仕組みでしたが、現在は開発が終了しています。
OSBAに代わるKubernetes上のAzureリソースコントローラーとして、KubernetesのOperatorの形で実装されたのが Azure Service Operator(ASO) です。
ASOをAzure Kubernetes Service(AKS)に導入し、Azureリソースを作成してみましょう。
試した環境
- Azure Kubernetes Service: v1.22.6
- Azure Service Operator: v2.0.0-beta.1
ASOはバージョン1系と2系の2種類が存在していますが、
⚠️ We strongly recommend new users consider ASO v2 instead of ASO v1
とのことですのでバージョン2系を導入しました。
まだベータバージョンですので、プロダクション環境での導入には十分注意しましょう。
ASOの導入
公式サイトにインストール手順が公開されていますのでそちらに沿って進めます。
1. cert-managerのインストール
cert-managerをインストールします。
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.8.2/cert-manager.yaml
cert-manager
名前空間配下のPodがすべて起動していることを確認します。
$ kubectl get pod -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-66b646d76-6pzgj 1/1 Running 0 2m5s cert-manager-cainjector-59dc9659c7-4p8qp 1/1 Running 0 2m5s cert-manager-webhook-7d8f555998-4mqxs 1/1 Running 0 2m5s
2. ASO用サービスプリンシパルの作成
続いて、ASOがAzureリソースを作成する際に利用するサービスプリンシパルを作成します。
今回はサービスプリンシパルに サブスクリプションのContributor(共同作成者)
のロールを割り当てます。
まずはサブスクリプションのIDを確認します。次の工程でテナントIDも利用するので合わせて確認しておきましょう。
サブスクリプションのIDは以下コマンドで取得できます。
AZURE_SUBSCRIPTION_ID=$(az account show -o tsv --query id)
同様に、テナントIDは以下のとおり。
AZURE_TENANT_ID=$(az account show -o tsv --query tenantId)
以下のコマンドで azure-service-operator
という名前のサービスプリンシパルを作成します。作成と同時にロールの割り当ても行っています。
az ad sp create-for-rbac -n azure-service-operator --role contributor \ --scopes /subscriptions/$AZURE_SUBSCRIPTION_ID
作成時に表示される appId
と password
は次の工程で使用します。
以下のように変数に格納しておきましょう。
AZURE_CLIENT_ID=<appIdの値>
AZURE_CLIENT_SECRET=<passwordの値>
3. ASOのインストール
ASOのインストールにはHelmを利用します。
まずはリポジトリを追加します。
helm repo add aso2 https://raw.githubusercontent.com/Azure/azure-service-operator/main/v2/charts
前項で作成したサービスプリンシパルの情報を使用しインストールします。
helm upgrade --install --devel aso2 aso2/azure-service-operator \ --create-namespace \ --namespace=azureserviceoperator-system \ --set azureSubscriptionID=$AZURE_SUBSCRIPTION_ID \ --set azureTenantID=$AZURE_TENANT_ID \ --set azureClientID=$AZURE_CLIENT_ID \ --set azureClientSecret=$AZURE_CLIENT_SECRET
と、ここでエラーが発生しました。
Error: rendered manifests contain a resource that already exists. Unable to continue with install: CustomResourceDefinition "batchaccounts.batch.azure.com" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "aso2"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "azureserviceoperator-system"
Helmでデプロイされた CustomResourceDefinition(CRD)
に、ラベルやアノテーションが正常に入っていないことが問題のようです。
どうしたものかと思っていると、GitHub の Releaseページに対処方法が記載されていました。
以下のスクリプトを作成し、
#!/bin/bash HELM_RELEASE=aso2 HELM_RELEASE_NAMESPACE=azureserviceoperator-system set -euo pipefail echo "Annotating ASO CRDs with release-name=${HELM_RELEASE}, release-namespace=${HELM_RELEASE_NAMESPACE}" for CRD in $(kubectl get crds -o='custom-columns=Name:.metadata.name' | grep azure.com) do kubectl label crd ${CRD} app.kubernetes.io/managed-by=Helm --overwrite kubectl annotate crd ${CRD} meta.helm.sh/release-name=${HELM_RELEASE} --overwrite kubectl annotate crd ${CRD} meta.helm.sh/release-namespace=${HELM_RELEASE_NAMESPACE} --overwrite done
実行することで各CRDリソースのラベルとアノテーションが修正されます。
chmod 700 fix-crds.sh ./fix-crds.sh
Annotating ASO CRDs with release-name=aso2, release-namespace=azureserviceoperator-system customresourcedefinition.apiextensions.k8s.io/batchaccounts.batch.azure.com not labeled customresourcedefinition.apiextensions.k8s.io/batchaccounts.batch.azure.com annotated customresourcedefinition.apiextensions.k8s.io/batchaccounts.batch.azure.com annotated customresourcedefinition.apiextensions.k8s.io/components.insights.azure.com not labeled customresourcedefinition.apiextensions.k8s.io/components.insights.azure.com annotated customresourcedefinition.apiextensions.k8s.io/components.insights.azure.com annotated customresourcedefinition.apiextensions.k8s.io/configurations.dbformariadb.azure.com not labeled ~以下略~
スクリプトの実行が完了したら、もう一度Helmコマンドを実行します。
helm upgrade --install --devel aso2 aso2/azure-service-operator \ --create-namespace \ --namespace=azureserviceoperator-system \ --set azureSubscriptionID=$AZURE_SUBSCRIPTION_ID \ --set azureTenantID=$AZURE_TENANT_ID \ --set azureClientID=$AZURE_CLIENT_ID \ --set azureClientSecret=$AZURE_CLIENT_SECRET
今後はちゃんと成功しました。
NAME: aso2 LAST DEPLOYED: Wed Jul 6 21:23:45 2022 NAMESPACE: azureserviceoperator-system STATUS: deployed REVISION: 1 TEST SUITE: None
OperatorのPodが起動していることも確認しましょう。
$ kubectl get pod -n azureserviceoperator-system NAME READY STATUS RESTARTS AGE azureserviceoperator-controller-manager-79b6dbd658-nb67b 2/2 Running 0 2m16s
これでASOを使う準備は完了です。
ASOを使ったAzureリソースのデプロイ
ここからは実際にAzureリソースをASOから作成していきます。
GitHubにASOのサンプル用リポジトリがあります。
その中から、Azure PostgreSQL Votes Demo App を、一部内容を変更してデプロイします。
Azureリソースを作成するマニフェストは以下のとおりです。
--- apiVersion: resources.azure.com/v1beta20200601 kind: ResourceGroup metadata: name: rg-aso-sample namespace: default spec: location: japaneast --- apiVersion: dbforpostgresql.azure.com/v1beta20210601 kind: FlexibleServer metadata: name: asosamplepostgresql namespace: default spec: location: japaneast owner: name: rg-aso-sample version: "13" sku: name: Standard_B1ms tier: Burstable administratorLogin: myAdmin administratorLoginPassword: name: server-admin-pw # Secretの名前 key: PASSWORD # Secret内のKey storage: storageSizeGB: 32 --- apiVersion: dbforpostgresql.azure.com/v1beta20210601 kind: FlexibleServersDatabase metadata: name: sampledb namespace: default spec: owner: name: asosamplepostgresql charset: utf8 --- apiVersion: dbforpostgresql.azure.com/v1beta20210601 kind: FlexibleServersFirewallRule metadata: name: samplefirewallrule namespace: default spec: owner: name: asosamplepostgresql startIpAddress: 0.0.0.0 endIpAddress: 255.255.255.255 --- apiVersion: v1 kind: Secret metadata: name: server-admin-pw namespace: default stringData: PASSWORD: <DBに設定するパスワード>
以下のAzureリソースを作成します。
- リソースグループ
- Azure Database for PostgreSQL - Flexible Server
- PostgreSQLのデータベース(sampledb)
- ファイアウォール設定
また、ユーザーのパスワードを格納するため、KubernetesのSecretも合わせて作成します。
AKSにデプロイします。
$ kubectl apply -f postgresql.yaml
resourcegroup.resources.azure.com/rg-aso-sample created
flexibleserver.dbforpostgresql.azure.com/asosamplepostgresql created
flexibleserversdatabase.dbforpostgresql.azure.com/sampledb created
flexibleserversfirewallrule.dbforpostgresql.azure.com/samplefirewallrule created
secret/server-admin-pw created
少し時間を置いてからAzureポータルを確認すると、以下のようにリソースグループとPostgreSQLが作成されていることが確認できます。
また、kubectlからもリソースを確認できます。
$ kubectl get resourcegroup.resources.azure.com/rg-aso-sample NAME READY REASON MESSAGE rg-aso-sample True Succeeded $ kubectl get flexibleserver.dbforpostgresql.azure.com NAME READY SEVERITY REASON MESSAGE asosamplepostgresql True Succeeded
PostgreSQLの作成が完了したら、次はデータベースを利用するアプリケーションをデプロイします。 マニフェストは以下のとおりです。
--- apiVersion: apps/v1 kind: Deployment metadata: name: azure-votes-postgresql-deployment namespace: default spec: selector: matchLabels: app: azure-votes-postgresql replicas: 1 template: metadata: name: postgresql-demo labels: app: azure-votes-postgresql spec: containers: - name: azure-votes-postgresql image: mcr.microsoft.com/k8s/asodemos/postgresqlvotes:latest ports: - containerPort: 8080 env: - name: USERNAME value: myAdmin - name: PASSWORD valueFrom: secretKeyRef: name: server-admin-pw key: PASSWORD - name: SERVER value: asosamplepostgresql.postgres.database.azure.com - name: DATABASE value: sampledb - name: PORT value: "5432" --- apiVersion: v1 kind: Service metadata: name: azure-votes-svc namespace: default spec: selector: app: azure-votes-postgresql ports: - protocol: TCP port: 80 targetPort: 8080 type: LoadBalancer
$ kubectl apply -f asosampleapp-deployment.yaml
deployment.apps/azure-votes-postgresql-deployment created
service/azure-votes-svc created
デプロイが完了したらブラウザからLoadBalancerサービスのIPアドレスにアクセスしてみましょう。 dogs か cats のボタンをクリックするとそれぞれカウントアップされ、クリック結果がデータベースに記録されるというサンプルアプリが起動しています。
このように、ASOを利用することで アプリケーションのPodとアプリケーションが利用するAzureリソースをKubernetesで一括デプロイできる ようになります。
Reconciliation Loop
先に述べたように、ASOはKubernetesのOperatorとして実装されています。 これにより、Kubernetesの Reconcliation Loop (リソースが宣言したとおりの状態であることを継続して確認・修正する) という特徴が、Azureリソースに対しても適用されます。
下の画面は前項でデプロイしたPostgreSQLのファイアウォール設定画面です。
赤枠部にあるように、 マニフェストで定義したファイアウォール定義 が設定されています。
これをポータルから削除してみましょう。
削除によって一時的に設定が消えるのですが、しばらくするとASOにより再度ファイアウォール設定が追加されます。
アクティビティの履歴を見ると以下のようになっています。
このように、宣言した状態を維持してくれる という点は、他のIaCツールに比べて便利なポイントだと思います。
この特徴から、Azureリソースを削除したくなったときにポータルから削除しても、ASOが再度リソースを作成してしまいます。
ASOで作成したリソースはASOで削除する 必要があることに注意しましょう。
$ kubectl delete -f postgresql.yaml resourcegroup.resources.azure.com "rg-aso-sample" deleted flexibleserver.dbforpostgresql.azure.com "asosamplepostgresql" deleted flexibleserversdatabase.dbforpostgresql.azure.com "sampledb" deleted flexibleserversfirewallrule.dbforpostgresql.azure.com "samplefirewallrule" deleted secret "server-admin-pw" deleted
上記のようにAKS上でリソースを削除することで、Azure上のリソースも削除されます。
おわりに
AzureリソースをKubernetesのリソースのように扱える Azure Service Operator、いかがでしたでしょうか。
アプリケーションとAzureリソースをまとめて管理できるという点は、TerraformやBicepなどの他のIaCツールにはない特徴だと思います。
まだまだ対応しているAzureリソースの数は多くないですが、データベースやネットワーク周りなど基本的な部分は揃っている印象です。
まだベータのステータスですので、今後の発展が楽しみですね。
私達はAzure・AKSを活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。