😽

AKS で Azure App Configuration を使用する

2024/06/12に公開

ごきげんよう!mihohoi です。
先日、Azure App Configuration 拡張機能が AKS でパブリックプレビューとして利用できるようになりました。

https://azure.microsoft.com/ja-jp/updates/appconfig-aksextension/

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 を確認しブラウザーで開きます。
AppConfig01.png

AppConfig の yaml は細かい設定を行うことが出来ます。
https://learn.microsoft.com/en-us/azure/azure-app-configuration/reference-kubernetes-provider?toc=%2Fazure%2Faks%2Ftoc.json&bc=%2Fazure%2Faks%2Fbreadcrumb%2Ftoc.json&tabs=default

その他の設定

たとえば、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 を再作成する必要があります。

AppConfig.png
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)。
正常に復元されました。

new.png

ちょっとだけメッセージを変えて動かしてみました。動いた。
そのあと、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 は、このファイルが見つからない場合にエラーを発生させることを意味しています。つまり、この設定ファイルはアプリケーションの実行に必須としている。

動作を確認します。
local01.png

コンテナー化

Dockerfile を作成します。

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY published/ ./
EXPOSE 8080
ENTRYPOINT ["dotnet", "AppConfig.dll"]

以上が、作成したアプリケーションの内容です。

参考

https://learn.microsoft.com/en-us/azure/aks/azure-app-configuration

GitHubで編集を提案
Microsoft (有志)

Discussion