はじめに
この記事ではAzure Kubernetes Service(以下、AKS)のPodからAzureリソースにアクセスする方法である、AAD Pod Identityについて解説します。
想定読者
- Kubernetesを利用したことがある方
- Azureが好きな方
Azureにおける認証ツール
アプリケーションがAzureリソースへ接続する際に利用される認証ツールとして、サービスプリンシパルとマネージドIDがあります。
サービスプリンシパルでは、Azure Active Directory(以下、AAD)で発行する「アプリケーションID」と「アプリケーションシークレット」を利用して認証し、Azureリソースへの接続を実現するものです。AWSのIAMユーザに該当します。
この方法ではID・シークレットを利用者側で管理する必要があるため、情報流出のリスクがあり、資格情報の管理場所や運用の検討が必要となります。
このような課題に対して、AzureではマネージドIDというツールを提供しています。マネージドIDはAzureリソースに対してのみ割り当てることができるもので、マネージドIDを利用することで、利用者は資格情報を意識(管理)することなくAzureリソースへの認証を実現できます。
この記事ではAKSでマネージドIDを利用するための方法を解説していきます。
AAD Pod Identityとは
AAD Pod IdentityとはAKSのPodでマネージドIDを利用するためのアドオンです。(Helm等を利用してインストールする方法もありますが、この記事では割愛します)
AAD Pod Identityの概念図は次の通りです。(こちらから図を引用)
AAD Pod IdentityアドオンをAKSにインストールすると、上図のPod IdentityがAKSで利用できるようになります。このPod IdentityがPodとAADを中継してアクセストークンを受け渡し、PodからAzureリソースへ接続できるようになります。
AAD Pod Identityを利用してAzureリソースにアクセスする
ここからは公式ドキュメントにならって、AAD Pod Identityを利用してPodからVMのメタデータを取得する手順を実行します。
なお、AAD Pod Identityアドオンは現在プレビュー中です。
Azure Cloud Shell
この記事では、Azure Cloud Shell(Bash)からAzure CLIを利用します。
プレビュー中であるAAD Pod Identityの機能を有効化します。
az feature register --name EnablePodIdentityPreview --namespace Microsoft.ContainerService
コマンドを実行後、State
がRegistered
になっていることが確認できればOKです。
つぎにAKS用の拡張コマンドであるaks-preview
をインストールします。
az extension add --name aks-preview
az extension update --name aks-preview
az extension list
を実行したときにaks-preview
のバージョンが0.5.5以降であることを確認します。
AKSの構築
AKSをリンクを参考に構築します。
-
ネットワークの種類はAzure CNIを選択してください。
AKSへの接続情報取得
以下コマンドを実行し、AKSへの接続情報を取得します。
az aks get-credentials --resource-group <リソースグループ名> --name <AKSクラスタ名>
kubectl config get-contexts
を実行したときに作成したAKSクラスターが選択されていればOKです。
AAD Pod Identityのインストール
AAD Pod Identityをインストールします。
az aks update -g <リソースグループ名> -n <AKSクラスター名> --enable-pod-identity
インストール後、az aks get-credentials --resource-group aks-test --name aks-cluster
で、NMI
のDaemonSetを確認できればインストール完了です。
ここで確認できるNode Management Identity(NMI) は、各ノードで実行されるポッドからのセキュリティトークンの要求を監視・取得し、ポッドに代わってAADからトークンを取得する機能を持ちます。
マネージドIDの作成とロールの割り当て
Podに割り当てるマネージドIDを作成します。
az identity create --resource-group <リソースグループ名> --name <マネージドID名>
作成したマネージドIDに対して、このシナリオで必要となるVirtual Machine Contributor
のロールを割り当てます。対象のリソースグループはAKSのノードが含まれるリソースグループとします。
# AKSノードがあるリソースグループ名取得
NODE_GROUP=$(az aks show -g <リソースグループ名> -n <AKSクラスタ名> --query nodeResourceGroup -o tsv)
# リソースグループのリソースID取得
NODES_RESOURCE_ID=$(az group show -n $NODE_GROUP -o tsv --query "id")
# マネージドIDのクライアントID取得
IDENTITY_CLIENT_ID="$(az identity show -g <リソースグループ名> -n <マネージドID名> --query clientId -otsv)"
# マネージドIDにロール割り当て
az role assignment create --role "Virtual Machine Contributor" --assignee "$IDENTITY_CLIENT_ID" --scope $NODES_RESOURCE_ID
マネージドIDへのロールの割り当てはAzureポータルから確認できます。
対象のリソースグループからマネージドIDを選択し、Azureロールの割り当てを選択したときに下図の通り表示されていればOKです。
AzureIdentityとAzureIdentityBindingの作成
マネージドIDを利用するためのAzureIdentity、およびAzureIdentityBindingを作成します。
AzureIdentityはその名の通りIDを保管するためのリソースで、マネージドIDのクライアントIDとリソースIDが記録されています。
AzureIdentityBindingはAzureIdentityとラベルを関連付けるためのリソースです。ラベルについては後述します。
以下のコマンドにより作成します。
# マネージドIDのリソースID取得
export IDENTITY_RESOURCE_ID="$(az identity show -g <リソースグループ名> -n <マネージドID名> --query id -otsv)"
az aks pod-identity add --resource-group <リソースグループ名> --cluster-name <AKS名> --namespace <AKSの名前空間> --name <Pod Identity名> --identity-resource-id ${IDENTITY_RESOURCE_ID}
コマンド実行後、kubectl get AzureIdentity,AzureIdentityBinding --namespace <名前空間>
でリソースが取得できればOKです。
マネージドIDを利用したアプリケーションのデプロイ
マネージドIDを利用したアプリケーションをデプロイします。
以下のマニフェストを作成してください。aadpodidbiding
ラベルには、前項で作成したPod Identity名を入力します。このaadpodidbiding
に入力されたラベル名とマネージドIDの紐づけをAzureIdentityBinding
のリソースで行っています。
ここで起動するアプリケーションはマネージドIDからトークンを取得し、AKSクラスターのノードに利用されるVMのメタデータを取得します。Virtual Machine Contributor
のロールをマネージドIDに割り当てたのはそのためです。
apiVersion: v1
kind: Pod
metadata:
name: demo
labels:
aadpodidbinding: <Pod Identity名>
spec:
containers:
- name: demo
image: mcr.microsoft.com/oss/azure/aad-pod-identity/demo:v1.6.3
args:
- --subscriptionid=<サブスクリプションID>
- --clientid=<マネージドIDのクライアントID>
- --resourcegroup=<リソースグループ名>
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
nodeSelector:
kubernetes.io/os: linux
作成したマニフェストをPod Identityを作成した名前空間にデプロイします。
kubectl apply -f demo.yaml --namespace <名前空間>
動作確認
コマンドを実行し、アプリケーションのログを確認します。
kubectl logs demo --follow --namespace <名前空間>
ログからトークンが取得されたこと、およびVMのメタデータが取得できたことが確認できます。
successfully acquired a token using the MSI, msiEndpoint(http://169.254.169.254/metadata/identity/oauth2/token)
successfully acquired a token, userAssignedID MSI, msiEndpoint(http://169.254.169.254/metadata/identity/oauth2/token) clientID(fcba39b8-ce43-4c6f-a112-8144efa93012)
successfully made GET on instance metadata, {"compute":{"location":"japaneast".....
おわりに
この記事ではAAD Pod Identityを利用して、PodからマネージドIDを利用する方法を解説しました。
本文中の内容以外にも、Pod IdentityをHelmで構築する方法や、ネットワークとしてKubernetを利用する方法など、様々な方法がサポートされています。是非この記事を足がかりに理解を深めていただけると幸いです。