Azure Advent Calendar 2021 16日目の記事です。
2023/04/04追記
こちらの記事は、古い内容となりますので、最新記事については以下を確認してください。
https://qiita.com/tbuchi888/items/c7f9024a48c25b0445be
0. はじめに
Azure Kubernetes Service (以降 AKS ) は
- クラスター内の Worker node 数( node pool )を、需要に応じて、設定範囲内で自動で増減可能なオートスケーラー機能に加えて
- クラスターの許容量を超える急なバーストトラフィック等への対応として、OSS の Kubernetes kubelet の実装である、CNCF の Virtual Kubelet を利用して、仮想ノードとして Azure Container Instances (以降 ACI )上に Pod をデプロイ可能です。
今回、ACI 仮想ノード上の複数 Pod より、ReadWriteMany 可能な Azure Files の共有フォルダ( Azure ファイル共有)をマウントする際に、すこしハマリましたので、やり方やハマリポイントなどを記事にしました。
結構なボリュームになってしまったので、結論だけ確認したい場合は、最後のまとめを確認してください。
なお、通常の AKS ノード( Virtual Machine Scale Sets による node pool )上の Pod から、Azure ファイル共有のマウントについては PV / PVC を利用した、静的プロビジョニングによるSMBでのマウントや、CSI( Container Storage Interface )ストレージドライバーを利用した、NFS の動的プロビジョニングなどは、AKSクラスタのバージョンによる考慮事項は多少あるものの、Kubernetes のスキルがあれば、特に問題なく利用できるのではと思います。
その他、本記事の内容は、2021 年 12 月 6 日時点の情報をもとに作成しています。
1. 実行環境について
本記事は、以下 AKS バージョンで試しています。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
aks-agentpool-11590259-vmss000000 Ready agent 34d v1.20.9
aks-agentpool-11590259-vmss000001 Ready agent 34d v1.20.9
aks-agentpool-11590259-vmss000002 Ready agent 34d v1.20.9
virtual-node-aci-linux Ready agent 34d v1.19.10-vk-azure-aci-v1.4.1
2. 事前準備と下調べ
- AKS で仮想ノードを有効化します。
- 仮想ノードを有効化するには、AKS クラスタで
Azure CNI
ネットワーク プラグインを利用する必要があります。 - 本記事では有効化手順の説明をしませんが、詳細は以下を参考にしてください。
- az コマンドでの CLIでも可能ですが、Azure Portalより AKS クラスタ作成時に有効化する方法が楽だと思います。
- 仮想ノードを有効化するには、AKS クラスタで
- 仮想ノード使用にあたって
- 仮想ノード上へ Pod をデプロイするにはいくつか設定が必要(後述)
- AKS での仮想ノード使用時の制限事項がいくつかある(後述)
3. 仮想ノード上へ Pod をデプロイするにはいくつか設定が必要
仮想ノードのサンプルアプリを確認すると、toleration とnodeSelector の定義がされていることが分かります。
- 仮想ノードへの Pod スケジューリングを許可するために、
tolerations
を設定する必要がある- 重要な Pod が意図せずに仮想ノードへスケジュールされないように 仮想ノードにはTaintsが設定されているため、
tolerations
により回避する設定を追加します。
- 重要な Pod が意図せずに仮想ノードへスケジュールされないように 仮想ノードにはTaintsが設定されているため、
- さらに、
nodeSelector
を設定することで、仮想ノード上に限定して Pod を動かすことが可能です。- なお、このサンプルは動作確認テストのために、
nodeSelector
を使用していますが、バースト時のみ、仮想ノードへ Pod をスケジューリングしたい場合は、nodeSelector
を定義しません
- なお、このサンプルは動作確認テストのために、
apiVersion: apps/v1
kind: Deployment
metadata:
name: aci-helloworld
spec:
replicas: 1
selector:
matchLabels:
app: aci-helloworld
template:
metadata:
labels:
app: aci-helloworld
spec:
containers:
- name: aci-helloworld
image: mcr.microsoft.com/azuredocs/aci-helloworld
ports:
- containerPort: 80
nodeSelector:
kubernetes.io/role: agent
beta.kubernetes.io/os: linux
type: virtual-kubelet
tolerations:
- key: virtual-kubelet.io/provider
operator: Exists
4. Azure ファイル共有に関する、仮想ノード使用時の制限事項がある
通常の AKS ノードと比べて、仮想ノードを利用する場合、いくつか制限事項があり、ファイル共有関連で以下の制限があったので、そちらを参考に試してみます。
その他、制限事項の詳細はこちらのドキュメントを参照。
Azure Files 共有のサポート汎用 v1をマウントするボリューム。 Azure Files 共有を含むボリュームをマウントする手順に従います。
4.1 Azure ファイル共有の事前準備
それでは、ファイル共有に関連する仮想ノードの制限事項(日本語も少し微妙なのですが、原文もほぼ同じような内容のため)、Azure Files 共有を含むボリュームに従ってファイル共有をマウントの準備をしていきます。
4.1.1. Azure ファイル共有を作成する
- AKS_PERS_XXX の環境変数の値を自身の環境に置き換えて実行します。
- Azure portal からの作成ももちろん可能ですが、次の Step で、Azure ファイル共有用の Kubernetes の Secret を作成する必要があるため、az コマンドの方が、試しやすいかと思います。
# Change these four parameters as needed for your own environment
AKS_PERS_STORAGE_ACCOUNT_NAME=mystorageaccount$RANDOM
AKS_PERS_RESOURCE_GROUP=myAKSShare
AKS_PERS_LOCATION=eastus
AKS_PERS_SHARE_NAME=aksshare
# Create a resource group
az group create --name $AKS_PERS_RESOURCE_GROUP --location $AKS_PERS_LOCATION
# Create a storage account
az storage account create -n $AKS_PERS_STORAGE_ACCOUNT_NAME -g $AKS_PERS_RESOURCE_GROUP -l $AKS_PERS_LOCATION --sku Standard_LRS
# Export the connection string as an environment variable, this is used when creating the Azure file share
export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string -n $AKS_PERS_STORAGE_ACCOUNT_NAME -g $AKS_PERS_RESOURCE_GROUP -o tsv)
# Create the file share
az storage share create -n $AKS_PERS_SHARE_NAME --connection-string $AZURE_STORAGE_CONNECTION_STRING
# Get storage account key
STORAGE_KEY=$(az storage account keys list --resource-group $AKS_PERS_RESOURCE_GROUP --account-name $AKS_PERS_STORAGE_ACCOUNT_NAME --query "[0].value" -o tsv)
# Echo storage account name and key
echo Storage account name: $AKS_PERS_STORAGE_ACCOUNT_NAME
echo Storage account key: $STORAGE_KEY
4.1.2. Kubernetes シークレットを作成する
* Azure ファイル共有用へアクセスするために、Kubernetes の Secret を作成します。
* 前の Step の実行結果である `AKS_PERS_STORAGE_ACCOUNT_NAME` と `STORAGE_KEY` 環境変数を利用していますが、 既存の Azure ストレージアカウントや、Portal か ら作成した場合には、ストレージアカウント名とアクセスキーを設定します。
kubectl create secret generic azure-secret --from-literal=azurestorageaccountname=$AKS_PERS_STORAGE_ACCOUNT_NAME --from-literal=azurestorageaccountkey=$STORAGE_KEY
以上で、ファイル共有を AKS で利用する準備が整いました。
4.2 ファイル共有を永続ボリューム( Persitent volume )としてマウントする
結論から言うと、こちらの方法 ”ファイル共有を永続ボリュームとしてマウント” がハマりポイントでした。
通常の AKS ノード上ではうまくいくのですが、仮想ノード上ではうまくいきません。次のパートを試していただければと思います。
ファイル共有を永続ボリューム( Persitent volume )としてマウントするために
前の Step で作成した、ファイル共有用の Secret を使って PV ( Persitent volume )、PVC ( Persistent Volume Claim )を静的に作成します。
apiVersion: v1
kind: PersistentVolume
metadata:
name: azurefile
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
azureFile:
secretName: azure-secret
secretNamespace: default
shareName: aksshare
readOnly: false
mountOptions:
- dir_mode=0755
- file_mode=0755
- uid=1000
- gid=1000
- mfsymlinks
- nobrl
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: azurefile
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 5Gi
kubectl コマンドで AKS へ apply します。
kubectl apply -f pv-pvc.yml
作成後に、PV と PVC が以下のような状態になっていれば成功です。
$ kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/azurefile 5Gi RWX Retain Bound default/azurefile 5d1h
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/azurefile Bound azurefile 5Gi RWX 5d1h
次に、以下 Deployment を使って Pod を仮想ノードへデプロイします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-azurefiles-pvc-acinode
labels:
node: aci
app: nginx-azurefiles-pvc-acinode
spec:
minReadySeconds: 30
strategy:
type: RollingUpdate
replicas: 4
selector:
matchLabels:
node: aci
app: nginx-azurefiles-pvc-acinode
template:
metadata:
name: nginx-azurefiles-pvc-acinode
labels:
app: nginx-azurefiles-pvc-acinode
node: aci
spec:
containers:
- image: docker.io/nginx:1.20
name: nginx-azurefiles-pvc-acinode
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: azurefilespvc
volumes:
- name: azurefilespvc
persistentVolumeClaim:
claimName: azurefile
nodeSelector:
kubernetes.io/role: agent
beta.kubernetes.io/os: linux
type: virtual-kubelet
tolerations:
- key: virtual-kubelet.io/provider
operator: Exists
- key: azure.com/aci
effect: NoSchedule
kubectl コマンドで AKS へ apply します。
kubectl apply -f dp-azurefiles-pvc-vol-acinode.yml
作成後に、状態を確認すると、仮想ノードへ Pod はスケジューリングされていますが、STATUS がProviderFailed
となり Pod が起動していません。
また、describe
コマンドで詳細を確認すると、
Message: Pod nginx-azurefiles-aci-85c4d6b9fd-gr5tn requires volume azurefilespvc which is of an unsupported type
のメッセージが出ていました。
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-azurefiles-aci-85c4d6b9fd-gr5tn 0/1 ProviderFailed 0 4h8m <none> virtual-node-aci-linux <none> <none>
nginx-azurefiles-aci-85c4d6b9fd-hpt9k 0/1 ProviderFailed 0 4h8m <none> virtual-node-aci-linux <none> <none>
nginx-azurefiles-aci-85c4d6b9fd-s6p8p 0/1 ProviderFailed 0 4h8m <none> virtual-node-aci-linux <none> <none>
nginx-azurefiles-aci-85c4d6b9fd-v6qvv 0/1 ProviderFailed 0 4h8m <none> virtual-node-aci-linux <none> <none>
$ kubectl describe po nginx-azurefiles-aci-85c4d6b9fd-gr5tn
Name: nginx-azurefiles-aci-85c4d6b9fd-gr5tn
Namespace: default
Priority: 0
Node: virtual-node-aci-linux/
Labels: app=nginx-azurefiles-aci
node=aci
pod-template-hash=85c4d6b9fd
Annotations: <none>
Status: Pending
Reason: ProviderFailed
Message: Pod nginx-azurefiles-aci-85c4d6b9fd-gr5tn requires volume azurefilespvc which is of an unsupported type
IP:
・・・ 省略 ・・・
Events: <none>
SecretName: default-token-9fbh4
$
問題、切り分けのため、上記 Deployment から、仮想ノード用の設定である、tolerations
とnodeSelector
を外して、通常の AKS ノードへのデプロイを試したところ、
問題なく起動し、ファイル共有も動作することが確認できたため、ドキュメントフィードバック機能を利用して内容を確認したところ、、、以下が分かりました。
- AKS 仮想ノードは現在(本記事執筆時点)、永続ボリューム(Persistent Volume)をサポートしていない
- 仮想ノード上の Pod よりファイル共有を利用したい場合は、インラインボリュームとしてマウントする
Persistent Volume を利用できないのは、ハマりポイントでした。。。
4.3 Azure ファイル共有をインラインボリュームとしてマウントする
結論から言うと、仮想ノード上では、こちらの方法が正解でした。
AKS 仮想ノードは現在(本記事執筆時点)、永続ボリューム(Persistent Volume)をサポートしていないため、ファイル共有をインラインボリュームとしてマウントしていきます。
さきほどの Deployment より、PV/PVC を利用する形から、azureFile で Pod から直接インラインマウントする形へ変更します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-azurefiles-inline-vol-aci
labels:
node: aci
app: nginx-azurefiles-inline-vol-aci
spec:
strategy:
type: RollingUpdate
replicas: 4
selector:
matchLabels:
node: aci
app: nginx-azurefiles-inline-vol-aci
template:
metadata:
name: nginx-azurefiles-inline-vol-aci
labels:
app: nginx-azurefiles-inline-vol-aci
node: aci
spec:
containers:
- image: docker.io/nginx:1.20
name: nginx-azurefiles-inline-vol-aci
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: azurefile
# Mount directly from Pod using Secret via azureFile instead of pvc
volumes:
- name: azurefile
azureFile:
secretName: azure-secret
shareName: aksshare
readOnly: false
nodeSelector:
kubernetes.io/role: agent
beta.kubernetes.io/os: linux
type: virtual-kubelet
tolerations:
- key: virtual-kubelet.io/provider
operator: Exists
- key: azure.com/aci
effect: NoSchedule
kubectl コマンドで AKS へ apply します。
kubectl apply -f dp-azurefiles-inline-vol-acinode.yml
Pod の状態を確認すると、STATUS が Running
となり、同一の Azure ファイル共有をマウントした複数の Pod を仮想ノード上で動作できることを確認できました。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-azurefiles-inline-vol-aci-589575b559-4jnd5 1/1 Running 0 4m1s 10.241.0.4 virtual-node-aci-linux <none> <none>
nginx-azurefiles-inline-vol-aci-589575b559-8nmvm 1/1 Running 0 3m24s 10.241.0.7 virtual-node-aci-linux <none> <none>
nginx-azurefiles-inline-vol-aci-589575b559-9kkd6 1/1 Running 0 3m24s 10.241.0.6 virtual-node-aci-linux <none> <none>
nginx-azurefiles-inline-vol-aci-589575b559-drdtr 1/1 Running 0 4m1s 10.241.0.5 virtual-node-aci-linux <none> <none>
これで、ACI 仮想ノード上の複数 Podより、 ReadWriteMany 可能な Azure Files の共有フォルダ( Azure ファイル共有)をマウントすることができました。
あとは、ストレージアカウント上の共有フォルダへ何かしら Web コンテンツ( js や html、画像等)を格納し、以下のような Kubernetes Service (または Ingress )を作成することで、外部よりアクセス可能になります。
apiVersion: v1
kind: Service
metadata:
name: nginx-azurefiles
labels:
node: aci
app: nginx-azurefiles
spec:
ports:
- name: nginx-azurefiles
port: 80
targetPort: 80
selector:
node: aci
app: nginx-azurefiles-inline-vol-aci
type: LoadBalancer
5. まとめ
Azure ファイル共有を利用する場合、仮想ノード使用時の制限として
- AKS 仮想ノードは現在(本記事執筆時点)、永続ボリューム(Persistent Volume)をサポートしていません。
- AKS 仮想ノード上に作成された Pod で Azure ファイル共有を使用する必要がある場合は、ファイル共有をインラインボリュームとしてマウントする必要があります。
Pod を仮想ノード上で動かすために
- 仮想ノードには taints が設定されているため、toleration をPodへ設定する必要があります。
- 上記
tolerations
に加えて、Pod へ nodeSelector を設定することで、仮想ノード上に限定して Pod を動かすことが可能です。 - 言い換えると、バースト時のみ、仮想ノードへ Pod をスケジューリングしたい場合は
nodeSelector
を定義しません。
・・・ デプロイメントからの抜粋 ・・・
spec:
containers:
- image: docker.io/nginx:1.20
name: nginx-azurefiles-inline-vol-aci
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: azurefile
# pvc ではなく、azureFile により、Secret を使って Pod から直接マウント
volumes:
- name: azurefile
azureFile:
secretName: azure-secret
shareName: aksshare
readOnly: false
# 仮想ノード上のみに Pod デプロイを限定する場合に nodeSelector 設定(バースト時のみ仮想ノードへ Pod をスケジュールしたい場合は定義しない)
nodeSelector:
kubernetes.io/role: agent
beta.kubernetes.io/os: linux
type: virtual-kubelet
# 仮想ノード上へ Pod をスケジュール可能なようにさせるために tolerations を設定
tolerations:
- key: virtual-kubelet.io/provider
operator: Exists
- key: azure.com/aci
effect: NoSchedule
なお、本内容については、ドキュメントへフィードバック中です。
6. 参考
記事中でリンクしている物とほぼ同じですが
- https://docs.microsoft.com/ja-jp/azure/aks/virtual-nodes
- https://docs.microsoft.com/ja-jp/azure/aks/azure-files-volume
- https://docs.microsoft.com/ja-jp/azure/aks/virtual-nodes-portal#deploy-a-sample-app
- https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
- https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
- https://kubernetes.io/docs/concepts/storage/volumes/#azurefile
- https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_file/README.md
7. さいごに
最後まで、閲覧ありがとうございます。
今後 ACI 仮想ノード上の複数 Pod より、ReadWriteMany 可能な Azure Files の共有フォルダをマウントする際に、こちらのハマりポイントなど、お役に立てれば幸いです。