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 ファイル共有)をマウントする際のハマリポイントなどを記事にしました。
結論からいいますと、ACI 仮想ノード上でCSI ストレージドライバーを利用する場合でも、以前のazurefileのストレージクラスと同じように PV ( Persitent volume )、PVC ( Persistent Volume Claim ) の利用はできませんので、静的にボリュームを作成し、Secretとして、インラインボリュームとしてマウントしてあげる必要があります。
なお、通常の AKS ノード( Virtual Machine Scale Sets による node pool )上の Pod から、Azure ファイル共有のマウントについては PV ( Persitent volume )、PVC ( Persistent Volume Claim ) を利用した、静的プロビジョニングや動的プロビジョニングなどは、AKSクラスタのバージョンによる考慮事項は多少あるものの、Kubernetes のスキルがあれば、特に問題なく利用できるのではと思います。
- 本記事は、以下過去に執筆した記事を、CSI ストレージドライバーを利用する形で再度検証を行い ReWrite したものとなります。
- ドキュメント修正のPR#106637が、先日無事マージされ、日本語版公式ドキュメントにも反映されましたので、このタイミングであらためて記事を書きます。
- なお、実行結果などは執筆時点(2023/04/04)の内容です
1. 実行環境について
本記事は、以下 AKS バージョンで試しています。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
aks-agentpool-19611256-vmss000002 Ready agent 25h v1.24.9
virtual-node-aci-linux Ready agent 25d v1.19.10-vk-azure-aci-1.4.8
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 が起動するようにしていますが
バースト時のみ、仮想ノードへ 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 共有のサポート汎用 V2 と汎用 V1 をマウントするボリューム。 ただし、仮想ノードでは現在、永続ボリュームと永続ボリューム要求がサポートされていません。 Azure Files 共有を含むボリュームをインライン ボリュームとしてマウントする手順に従います。
こちらが、今回のポイントとなる制限事項です
仮想ノードではファイル共有の PV ( Persitent volume )、PVC ( Persistent Volume Claim )としてのマウントをサポートしていません
インライン ボリュームとしてマウントする必要があります!
4.1 Azure ファイル共有の事前準備
それでは、Azure ファイル共有を作成するに従ってファイル共有のマウント準備をしていきます。
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 の Secret を作成する
- 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 仮想ノードはファイル共有の PV ( Persitent volume )、PVC ( Persistent Volume Claim )マウントをサポートしていない
結論から言うと、こちらの方法がハマりポイントです
なんども言いますが、公式ドキュメントの制約事項にも、加筆した通り
- 以下の PV ( Persitent volume )、PVC ( Persistent Volume Claim )利用は、通常の AKS ノード上ではうまくいくのですが、仮想ノード上では利用できませんのでご注意ください
- 以下は仮想ノード上でのマウントエラーのナレッジのために記載してているものとなります
ファイル共有を永続ボリューム( Persitent volume )としてマウントするために
前の Step で作成した、ファイル共有用の Secret を使って PV ( Persitent volume )、PVC ( Persistent Volume Claim )を静的に作成します。
resourceGroup
やshareName
、nodeStageSecretRef
などは、前述の 4.1. の内容に置き換えてください。
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/provisioned-by: file.csi.azure.com
name: azurefile
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: azurefile-csi
csi:
driver: file.csi.azure.com
readOnly: false
volumeHandle: unique-volumeid # make sure this volumeid is unique for every identical share in the cluster
volumeAttributes:
resourceGroup: myAKSShare # optional, only set this when storage account is not in the same resource group as node
shareName: aksshare
nodeStageSecretRef:
name: azure-secret
namespace: default
mountOptions:
- dir_mode=0777
- file_mode=0777
- uid=0
- gid=0
- mfsymlinks
- cache=strict
- nosharesock
- nobrl
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: azurefile
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile-csi
volumeName: azurefile
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 azurefile-csi 13s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/azurefile Bound azurefile 5Gi RWX azurefile-csi 12s
次に、以下 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.yaml
作成後に、状態を確認すると、仮想ノードへ Pod はスケジューリングされていますが、STATUS がProviderFailed
となり Pod が起動していません。
また、describe
コマンドで詳細を確認すると、
Message: pod nginx-azurefiles-pvc-acinode-7d55d7679b-ftb5n 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-pvc-acinode-7d55d7679b-ftb5n 0/1 ProviderFailed 0 31s <none> virtual-node-aci-linux <none> <none>
nginx-azurefiles-pvc-acinode-7d55d7679b-kpwq4 0/1 ProviderFailed 0 31s <none> virtual-node-aci-linux <none> <none>
nginx-azurefiles-pvc-acinode-7d55d7679b-pbwbg 0/1 ProviderFailed 0 31s <none> virtual-node-aci-linux <none> <none>
nginx-azurefiles-pvc-acinode-7d55d7679b-ztm9g 0/1 ProviderFailed 0 31s <none> virtual-node-aci-linux <none> <none>
$ kubectl describe po nginx-azurefiles-pvc-acinode-7d55d7679b-ftb5n
Name: nginx-azurefiles-pvc-acinode-7d55d7679b-ftb5n
Namespace: default
Priority: 0
Service Account: default
Node: virtual-node-aci-linux/
Labels: app=nginx-azurefiles-pvc-acinode
node=aci
pod-template-hash=7d55d7679b
Annotations: <none>
Status: Pending
Reason: ProviderFailed
Message: pod nginx-azurefiles-pvc-acinode-7d55d7679b-ftb5n requires volume azurefilespvc which is of an unsupported type
IP:
・・・ 省略 ・・・
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 98s default-scheduler Successfully assigned default/nginx-azurefiles-pvc-acinode-7d55d7679b-ftb5n to virtual-node-aci-linux
Warning ProviderCreateFailed 11s (x14 over 98s) virtual-node-aci-linux/pod-controller pod nginx-azurefiles-pvc-acinode-7d55d7679b-ftb5n requires volume azurefilespvc which is of an unsupported type
$
上記 Deployment から、仮想ノード用の設定である、tolerations
とnodeSelector
を外して、通常の AKS ノードへのデプロイを試したところ、問題なく起動し、ファイル共有も動作することが確認できます。
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-azurefiles-pvc-acinode-7cdf6c6c9f-6smcx 1/1 Running 0 76s 10.224.0.59 aks-agentpool-19611256-vmss000002 <none> <none>
nginx-azurefiles-pvc-acinode-7cdf6c6c9f-9dj4j 1/1 Running 0 41s 10.224.0.11 aks-agentpool-19611256-vmss000002 <none> <none>
nginx-azurefiles-pvc-acinode-7cdf6c6c9f-bhs6h 1/1 Running 0 41s 10.224.0.56 aks-agentpool-19611256-vmss000002 <none> <none>
nginx-azurefiles-pvc-acinode-7cdf6c6c9f-zjvnn 1/1 Running 0 76s 10.224.0.39 aks-agentpool-19611256-vmss000002 <none> <none>
冒頭からの、繰り返しとなりますが、仮想ノードの制限事項にある通り
- AKS 仮想ノードは現在(本記事執筆時点)、PV ( Persitent volume )、PVC ( Persistent Volume Claim )をサポートしていません
- 仮想ノード上の Pod よりファイル共有を利用したい場合は、インラインボリュームとしてマウントします
- この制限事項は、CSIドライバーでも同様となります
PV ( Persitent volume )、PVC ( Persistent Volume Claim )を利用できないのは、ハマりポイントだと思いますのでご注意ください!
4.3 Azure ファイル共有をインラインボリュームとしてマウントする
それでは、正規の方法で試してみます。
AKS 仮想ノードは現在(本記事執筆時点)、PV ( Persitent volume )、PVC ( Persistent Volume Claim )をサポートしていないため、ファイル共有をインラインボリュームとしてマウントしていきます。
さきほどの Deployment より、PV/PVC を利用する形から、ファイル共有をインライン ボリュームとしてマウントする 方法で 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
csi:
driver: file.csi.azure.com
readOnly: false
volumeAttributes:
secretName: azure-secret # required
shareName: aksshare # required
mountOptions: "dir_mode=0777,file_mode=0777,cache=strict,actimeo=30,nosharesock" # optional
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-csi-azurefiles-inline-vol-acinode.yaml
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-f5d9bd68-fsmk6 1/1 Running 0 101s 10.239.0.7 virtual-node-aci-linux <none> <none>
nginx-azurefiles-inline-vol-aci-f5d9bd68-h6w2g 1/1 Running 0 101s 10.239.0.5 virtual-node-aci-linux <none> <none>
nginx-azurefiles-inline-vol-aci-f5d9bd68-n752t 1/1 Running 0 101s 10.239.0.4 virtual-node-aci-linux <none> <none>
nginx-azurefiles-inline-vol-aci-f5d9bd68-wc5nm 1/1 Running 0 101s 10.239.0.6 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 仮想ノードは現在(本記事執筆時点)、PV ( Persitent volume )、PVC ( Persistent Volume Claim )をサポートしていません。
- AKS 仮想ノード上に作成された Pod で Azure ファイル共有を使用する必要がある場合は、ファイル共有をインライン ボリュームとしてマウントする必要があります。
・・・ デプロイメントからの抜粋 ・・・
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 ではなく、Secret を使って Pod から azureFile を直接インラインマウント
volumes:
- name: azurefile
csi:
driver: file.csi.azure.com
readOnly: false
volumeAttributes:
secretName: azure-secret # required
shareName: aksshare # required
mountOptions: "dir_mode=0777,file_mode=0777,cache=strict,actimeo=30,nosharesock" # optional
# 仮想ノード上のみに Pod デプロイを限定する場合に nodeSelector 設定(バースト時のみ仮想ノードへ Pod をスケジュールしたい場合は定義しない)
また、Pod を仮想ノード上で動かすために
- 仮想ノードには taints が設定されているため、toleration をPodへ設定する必要があります。
- 上記
tolerations
に加えて、Pod へ nodeSelector を設定することで、仮想ノード上に限定して Pod を動かすことが可能です。 - 言い換えると、バースト時のみ、仮想ノードへ Pod をスケジューリングしたい場合は
nodeSelector
を定義しません。
・・・ デプロイメントからの抜粋 ・・・
spec:
# 仮想ノード上のみに Pod デプロイを限定する場合に nodeSelector 設定(バースト時のみ仮想ノードへ Pod をスケジュールしたい場合はあえては nodeSelector を定義しない)
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://learn.microsoft.com/ja-jp/azure/aks/azure-csi-files-storage-provision
- 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://kubernetes.io/docs/concepts/storage/volumes/#azurefile-csi-migration
- https://kubernetes.io/docs/concepts/storage/volumes/#azurefile-csi-migration-complete
- https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_file/README.md
7. さいごに
最後まで、閲覧ありがとうございます。
今後 ACI 仮想ノード上の複数 Pod より、ReadWriteMany 可能な Azure Files の共有フォルダをマウントする際に、こちらのハマりポイントなど、お役に立てれば幸いです。