AKS で Azure App Configuration を使用する
ごきげんよう!mihohoi です。
先日、Azure App Configuration 拡張機能が AKS でパブリックプレビューとして利用できるようになりました。
Azure App Configuration は、クラウドアプリケーションの設定を一元管理するサービスです。
Kubernetes の場合、このような設定ファイルは ConfigMap で設定することが一般的です。
AKS の場合も、Secret の場合は KeyVault に保管しますが、アプリケーションの設定ファイルについては ConfigMap で保存することが多いのではないでしょうか。
Azure App Configuration を使用すると、設定ファイルを Azure で一元管理できるほか、設定に対して RBAC を設定し変更できる開発者を制限したり、変更管理を AKS 外へ持たせることができます。
それでは、実際どのような動作となるか確認していきます。
準備
事前準備から始めます。Azure にログインしていることが前提です。
拡張機能
Azure CLI 拡張機能をインストールとアップデートを行います。
% az extension add --name k8s-extension
Default enabled including preview versions for extension installation now. Disabled in future release. Use '--allow-preview true' to enable it specifically if needed. Use '--allow-preview false' to install stable version only.
% az extension update --name k8s-extension
Default enabled including preview versions for extension installation now. Disabled in future release. Use '--allow-preview true' to enable it specifically if needed. Use '--allow-preview false' to install stable version only.
Latest version of 'k8s-extension' is already installed.
Use --debug for more information
KubernetesConfiguration リソースプロバイダーを登録
KubernetesConfiguration
リソースプロバイダーを登録します。すでに登録している場合は不要です。
% az provider list --query "[?namespace=='Microsoft.KubernetesConfiguration']" -o table
Namespace RegistrationState RegistrationPolicy
--------------------------------- ------------------- --------------------
Microsoft.KubernetesConfiguration Registered RegistrationRequired
AKS の作成
まずは何はともあれ AKS を作成します。変数については適宜置き換えてください。
% myResourceGroup=<リソースグループ名>
% location=eastus2
% myAKSCluster=<AKS クラスター名>
% az group create --name $myResourceGroup --location $location
% az aks create -g $myResourceGroup -n $myAKSCluster --enable-managed-identity --node-count 3 --enable-addons monitoring --enable-msi-auth-for-monitoring --generate-ssh-keys
作成後、AKS に接続します。
% az aks get-credentials --resource-group $myResourceGroup --name $myAKSCluster
接続できたことを確認します。
% kubectl get pods
No resources found in default namespace.
AKS クラスターに拡張機能をインストールする
作成した AKS クラスターに Microsoft.AppConfiguration
拡張機能をインストールします。
% az k8s-extension create --cluster-type managedClusters --cluster-name $myAKSCluster --resource-group $myResourceGroup --name appconfigurationkubernetesprovider --extension-type Microsoft.AppConfiguration --release-train preview --auto-upgrade-minor-version false
アプリのデプロイ
密かに作成していた .NET アプリをデプロイします。.NET アプリケーションについては、この記事の最後に内容を掲載しています。
また、ACR (Azure Container Registry) は既存のものを使用します。まだ作成していない場合は、作成してください。
ACR を作成した AKS にアタッチします。これで ACR に格納しているイメージを使用できます。
% myACR = <ACR名>
% az aks update --name $myAKSCluster --resource-group $myResourceGroup --attach-acr $myACR
Deployment は以下のように作成しました。デプロイするイメージに合わせて作成します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: appconfig-deployment
labels:
app: appconfig
spec:
replicas: 2
selector:
matchLabels:
app: appconfig
template:
metadata:
labels:
app: appconfig
spec:
containers:
- name: appconfig
image: <ACR 名>.azurecr.io/appconfig:v2
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: appconfig-service
spec:
type: LoadBalancer
selector:
app: appconfig
ports:
- protocol: TCP
port: 80
targetPort: 8080
これを一度デプロイしておきます。
% kubectl create ns appconfig-demo
% kubectl apply -f kubernetes/ -n appconfig-demo
App Configuration ストアを作成する
ここからが本題です。App Configutation ストアを作成します。名前は固定で実行していますが、適宜置き換えてください。
作成
App Configuration ストアを作成します。
% az appconfig create --location eastus2 --name krmt-app-conf --resource-group $myResourceGroup
キーの値を作成
設定ファイルで使用するキーを作成します。FontColor と Message です。この値については、好きな値に変えてもいいです。例えば Red でも Blue でも。
% az appconfig kv set --name krmt-app-conf --key Settings:FontColor --value Green
% az appconfig kv set --name krmt-app-conf --key Settings:Message --value "App Configuration Settings (>ω<ノ)"
これで App Configutation は作成できました。
AKS の設定
ワークロード ID の設定
ワークロード ID が必要になります。AKS で有効化していきます。
% az aks update --resource-group $myResourceGroup --name $myAKSCluster --enable-oidc-issuer --enable-workload-identity
ユーザー割り当てマネージド ID を作成し、作成後にそのクライアント ID を書き留めておきます。
% az identity create -g $myResourceGroup -n krmt-user-identity
Azure CLI を使用して、マネージド ID、OIDC 発行者、およびサブジェクト間のフェデレーション ID 資格情報を作成します。
% FEDERATED_IDENTITY_CREDENTIAL_NAME=federated-credential
% USER_ASSIGNED_IDENTITY_NAME=krmt-user-identity
% export AKS_OIDC_ISSUER="$(az aks show --name $myAKSCluster --resource-group $myResourceGroup --query "oidcIssuerProfile.issuerUrl" -o tsv)"
% az identity federated-credential create --name "${FEDERATED_IDENTITY_CREDENTIAL_NAME}" --identity-name "${USER_ASSIGNED_IDENTITY_NAME}" --resource-group $myResourceGroup --issuer "${AKS_OIDC_ISSUER}" --subject system:serviceaccount:azappconfig-system:az-appconfig-k8s-provider --audience api://AzureADTokenExchange
Azure App Configuration で、ユーザー割り当てマネージド ID にApp Configuration データ リーダーロールを付与します。
# Azure App Configuration のリソース ID を取得
% APP_CONFIG_ID=$(az appconfig show --name krmt-app-conf --resource-group krmt-AKS-rg --query "id" --output tsv)
# ユーザー割り当てマネージドIDのリソースIDを取得
% USER_ASSIGNED_ID=$(az identity show --name krmt-user-identity --resource-group krmt-AKS-rg --query "principalId" --output tsv)
# ロール割り当ての作成
% az role assignment create --assignee-object-id $USER_ASSIGNED_ID --assignee-principal-type ServicePrincipal --role "App Configuration Data Reader" --scope $APP_CONFIG_ID
アプリ構成 Kubernetes プロバイダーを使用する
次に Helm を使って Azure App Configuration Kubernetes プロバイダーを AKS クラスターにインストールします。
% helm install azureappconfiguration.kubernetesprovider \
oci://mcr.microsoft.com/azure-app-configuration/helmchart/kubernetes-provider \
--namespace azappconfig-system \
--create-namespace
ユーザー割り当てマネージド ID のクライアント ID の値を取得します。
% az identity show --name krmt-user-identity --resource-group krmt-AKS-rg --query "clientId" --output tsv
spec.auth.workloadIdentity.managedIdentityClientId
に上記で取得した値と、App Configuration のエンドポイントを入力し、AKS クラスターにデプロイします。
apiVersion: azconfig.io/v1
kind: AzureAppConfigurationProvider
metadata:
name: appconfigurationprovider-sample
spec:
endpoint: <your-app-configuration-store-endpoint>
target:
configMapName: configmap-created-by-appconfig-provider
configMapData:
type: json
key: mysettings.json
auth:
workloadIdentity:
managedIdentityClientId: <your-managed-identity-client-id>
デプロイ
% kubectl apply -f appconfig.yaml -n appconfig-demo
% kubectl apply -f deployment.yaml -n appconfig-demo
最初にデプロイした自作のアプリを ConfigMap を利用するように修正して、再度デプロイします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: appconfig-deployment
labels:
app: appconfig
spec:
replicas: 2
selector:
matchLabels:
app: appconfig
template:
metadata:
labels:
app: appconfig
spec:
containers:
- name: appconfig
image: <ARC 名>.azurecr.io/appconfig:v2
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: configmap-created-by-appconfig-provider
---
apiVersion: v1
kind: Service
metadata:
name: appconfig-service
spec:
type: LoadBalancer
selector:
app: appconfig
ports:
- protocol: TCP
port: 80
targetPort: 8080
再度デプロイ
% kubectl apply -f kubernetes/ -n appconfig-demo
azureappconfigurationprovider.azconfig.io/appconfigurationprovider-sample created
deployment.apps/appconfig-deployment configured
service/appconfig-service unchanged
App Configuration の設定をデプロイした後に自動的に作成される Configmap はどうなっているのでしょうか?
% kubectl get configmap -n appconfig-demo
NAME DATA AGE
configmap-created-by-appconfig-provider 1 2m36s
kube-root-ca.crt 1 47m
% kubectl describe configmap configmap-created-by-appconfig-provider -n appcon
fig-demo
Name: configmap-created-by-appconfig-provider
Namespace: appconfig-demo
Labels: <none>
Annotations: azconfig.io/LastReconcileTime: 2024-06-11 05:46:59.447766062 +0000 UTC
Data
====
mysettings.json:
----
{"Settings:FontColor":"Blue","Settings:Message":"App Configuration Settings (\u003eω\u003cノ)"}
BinaryData
====
Events: <none>
設定が反映されていそうですね!ここで表示されていない、または ConfigMap が作成されていない場合は、うまくいっていない可能性があります。
動作確認
実際に、Service で付与された IP を確認しブラウザーで開きます。
AppConfig の yaml は細かい設定を行うことが出来ます。
その他の設定
たとえば、30 秒ごとにキーが更新されるようにしたい場合があるとします。
その場合は、spec.configuration.refresh
を以下のように変更(追加)します。
configuration:
refresh:
enabled: true
interval: "30s"
monitoring:
keyValues:
- key: mysettings.json
Azure App Configuration の値を変更します。その後、変更を確認します。
% kubectl describe configmap configmap-created-by-appconfig-provider -n appconfig-demo
Name: configmap-created-by-appconfig-provider
Namespace: appconfig-demo
Labels: <none>
Annotations: azconfig.io/LastReconcileTime: 2024-06-11 06:00:26.327182539 +0000 UTC
Data
====
mysettings.json:
----
{"Settings:FontColor":"pink","Settings:Message":"App Configuration Settings (\u003eω\u003cノ)"}
BinaryData
====
Events: <none>
FontColor
が pink に変わってますね!続いて Pod を exec を使って確認します。
root@appconfig-deployment-6d97f7dbdf-29zw5:/app# cat /app/config/mysettings.json
{"Settings:FontColor":"pink","Settings:Message":"App Configuration Settings (\u003eω\u003cノ)"}
値は Pod まで反映されていますが、アプリケーション側としては特に自動更新の設定をしていないため、Pod を再作成する必要があります。
Pod が再作成されたので、アプリケーションの設定も再度読み込まれました。
※ConfigMap とシークレットは更新されたデータでのみ再生成されます
まとめ
下準備が長い印象ですが、運用上どうしてもアプリケーションの設定を Azure 上で一元管理をしたい場合に最適な機能だと思います。大変ですし。
現状、日本リージョンでは展開されていない&プレビューのため、早く GA されないかなという気持ちです。
余談:dotnet アプリを作成する
本文で使用した .NET アプリを以下に記述します。
% dotnet new webapp --output AppConfig --framework net8.0
テンプレート "ASP.NET Core Web アプリ" が正常に作成されました。
このテンプレートには、Microsoft 以外のパーティのテクノロジーが含まれています。詳しくは、https://aka.ms/aspnetcore/8.0-third-party-notices をご覧ください。
作成後の操作を処理しています...
/home/miho/develop/AppConfig/AppConfig.csproj を復元しています:
復元対象のプロジェクトを決定しています...
/home/miho/develop/AppConfig/AppConfig.csproj を復元しました (49 ms)。
正常に復元されました。
ちょっとだけメッセージを変えて動かしてみました。動いた。
そのあと、Index.cshtml
を変更
@page
@model IndexModel
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
ViewData["Title"] = "Home page";
}
<style>
h1 {
color: @Configuration["Settings:FontColor"]
}
</style>
<div class="text-center">
<h1 class="display-4">@Configuration["Settings:Message"]</h1>
<p>Hello Mihohoi!(`・ω・´)</p>
</div>
設定ファイルの作成
プロジェクト トップに、config フォルダを作成して、その中に mysettings.json
という JSON ファイルを作成します。
その中に以下を追加して保存します。
{
"Settings": {
"FontColor": "Black",
"Message": "Local Settings (>ω<ノ)ノ"
}
}
Program.cs
の4行目あたりに以下を追加。
builder.Configuration.AddJsonFile("config/mysettings.json", reloadOnChange: true, optional: false);
設定の意味としては:
- 自分で作成した設定ファイルを読み込む。
-
reloadOnChange: true
は、このファイルが変更された場合に自動的に再読み込みするように指定。 -
optional: false
は、このファイルが見つからない場合にエラーを発生させることを意味しています。つまり、この設定ファイルはアプリケーションの実行に必須としている。
動作を確認します。
コンテナー化
Dockerfile
を作成します。
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY published/ ./
EXPOSE 8080
ENTRYPOINT ["dotnet", "AppConfig.dll"]
以上が、作成したアプリケーションの内容です。
参考
Discussion