3
1

More than 1 year has passed since last update.

AKS 仮想ノード( ACI ) 上の Pod から Azure ファイル共有をマウントする

Last updated at Posted at 2021-12-15

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 クラスタ作成時に有効化する方法が楽だと思います。
  • 仮想ノード使用にあたって
    • 仮想ノード上へ Pod をデプロイするにはいくつか設定が必要(後述)
    • AKS での仮想ノード使用時の制限事項がいくつかある(後述)

3. 仮想ノード上へ Pod をデプロイするにはいくつか設定が必要

仮想ノードのサンプルアプリを確認すると、tolerationnodeSelector の定義がされていることが分かります。

  • 仮想ノードへの Pod スケジューリングを許可するために、tolerationsを設定する必要がある
    • 重要な Pod が意図せずに仮想ノードへスケジュールされないように 仮想ノードにはTaintsが設定されているため、tolerationsにより回避する設定を追加します。
  • さらに、nodeSelectorを設定することで、仮想ノード上に限定して Pod を動かすことが可能です。
    • なお、このサンプルは動作確認テストのために、nodeSelectorを使用していますが、バースト時のみ、仮想ノードへ Pod をスケジューリングしたい場合は、nodeSelectorを定義しません
aci-sample-deploy.yml
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 )を静的に作成します。

pv-pvc.yml
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 を仮想ノードへデプロイします。

dp-azurefiles-pvc-vol-acinode.yml
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 から、仮想ノード用の設定である、tolerationsnodeSelectorを外して、通常の AKS ノードへのデプロイを試したところ、
問題なく起動し、ファイル共有も動作することが確認できたため、ドキュメントフィードバック機能を利用して内容を確認したところ、、、以下が分かりました。

  • AKS 仮想ノードは現在(本記事執筆時点)、永続ボリューム(Persistent Volume)をサポートしていない
  • 仮想ノード上の Pod よりファイル共有を利用したい場合は、インラインボリュームとしてマウントする

Persistent Volume を利用できないのは、ハマりポイントでした。。。

4.3 Azure ファイル共有をインラインボリュームとしてマウントする

結論から言うと、仮想ノード上では、こちらの方法が正解でした。

AKS 仮想ノードは現在(本記事執筆時点)、永続ボリューム(Persistent Volume)をサポートしていないため、ファイル共有をインラインボリュームとしてマウントしていきます。
さきほどの Deployment より、PV/PVC を利用する形から、azureFile で Pod から直接インラインマウントする形へ変更します。

dp-azurefiles-inline-vol-acinode.yml
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 )を作成することで、外部よりアクセス可能になります。

svc.yml
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 ファイル共有を利用する場合、仮想ノード使用時の制限として

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. 参考

記事中でリンクしている物とほぼ同じですが

7. さいごに

最後まで、閲覧ありがとうございます。
今後 ACI 仮想ノード上の複数 Pod より、ReadWriteMany 可能な Azure Files の共有フォルダをマウントする際に、こちらのハマりポイントなど、お役に立てれば幸いです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1