🦥

【AKS】git-sync を使って Azure Files にgitリポジトリをコピーする

2023/12/12に公開

はじめに

こんにちは。
k8s全然わからない民です。やればやるほどわからん。

今回やったのは、
永続ボリュームに git repository のフォルダ・ファイルを永続ボリュームに同期させて、各アプリケーションポッドで使えるようにしよう
という内容です。

AKSで gitrepo ボリュームを作りたかったんですが、現在非推奨[1]です。
調べたところ、 git-sync を代用として使うみたいです。

https://github.com/kubernetes/git-sync

READMEにも書いてますが、本来はサイドカーコンテナとして使う代物のようですので、このやり方は本来の使い方ではないと思われます。
が、gitと同期させたいファイルやらが多いのとサイズも大きめなので、pod側は永続ボリュームをマウントして使う利用方法にしました。
全体的に運用に耐えられるかどうかも含めて、このやり方があってるかはわかりませんが、検証ベースでやりたいことはとりあえずできた、というレベルです。

イメージ

こんな感じのことをします。
概念なので、間違ってる可能性は大いにあります。あくまでイメージです。
イメージ図

前準備

必要なもの

Azure Cloud Shell
AKS
Storage Account / Azure Files
git repository

AKSにおけるストレージオプション

PersistentVolume やら PersistentVolumeClaim の話は公式のドキュメントを一通り読んだ方がいいです。やってる最中は全然わからなかったんですが😂

https://learn.microsoft.com/ja-jp/azure/aks/concepts-storage#persistent-volume-claims

Azure Files CSI ドライバー

Azure Files との共有ファイルストレージは公式にある設定でだいたいできます。
https://learn.microsoft.com/ja-jp/azure/aks/azure-files-csi

今回やるのは静的プロビジョニングになります。
https://learn.microsoft.com/ja-jp/azure/aks/azure-csi-files-storage-provision

Azure Files の作り方もファイル共有も上記のサイトに書いてますので、ここでは詳細は割愛します。

マニュフェストファイル

ここからが本題。

git-sync pod

git-sync.yaml
apiVersion: v1
kind: Pod
metadata:
  name: git-sync
  namespace: git-sync-app
  labels:
    app: git-sync
spec:
  containers:
  - name: git-sync
    image: registry.k8s.io/git-sync/git-sync:v4.1.0
    securityContext:
      runAsUser: 0
      runAsGroup: 0
    volumeMounts:
    - name: azurefile
      mountPath: /mnt/azurefiles # マウントするパスはなんでもよい
    args:
    - --repo=<git repository のURL>
    - --depth=1
    - --period=30s
    - --ref=main
    - --link=current
    - --root=/mnt/azurefiles # 上の mounthPath と合わせる
  volumes:
    - name: azurefile
      persistentVolumeClaim:
        claimName: azurefile-pvc # AzureFilesのCSIドライバーを使ってプロビジョニングされたファイル共有を参照するPVCの名前

Azure Files を使用する場合、一番ハマったのが、securityContext でユーザをrootユーザ(0)にしないと、permission で怒られます。

このsecurityContextがポイント。
ボリュームをマウントするのはrootユーザ(0)
git-syncでcloneとかするときにchmodしたりするらしんだけど、その時のユーザと一致してなくてpermissionで怒られたらしい。
明示的にsecurityContextでユーザを指定してあげるとよいとか。
https://zenn.dev/link/comments/a6c551071ed973

永続ボリューム周り

  • PersistentVolume
azurefiles-pv.yaml
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
    volumeAttributes:
      resourceGroup: ストレージアカウントを作ったリソースグループ名
      shareName: ファイル共有名
    nodeStageSecretRef:
      name: azure-secret
      namespace: git-sync-app
  mountOptions:
    - dir_mode=0777
    - file_mode=0777
    - uid=0
    - gid=0
    - noperm
  • PersistentVolumeClaim
azurefiles-mount-options-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: azurefile-pvc
  namespace: git-sync-app
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: azurefile-csi
  volumeName: azurefile
  resources:
    requests:
      storage: 5Gi # 確保するメモリは適宜
azurefiles-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: azure-secret
  namespace: git-sync-app
type: Opaque
data:
  azurestorageaccountname: <base64 エンコードしたStorageアカウント名>
  azurestorageaccountkey: <base64 エンコードしたStorageアカウントキー>

git-sync するとこんな感じのフォルダ構成が作成されます。

application Pod

  • メインアプリケーション
    一応、git-sync pod が起動してから、メインのアプリケーションも起動するようにinitContainers でチェックしてます。
    ※もっとエラーハンドリングする必要はありますが。
git-sync-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
  namespace: git-sync-app
  labels:
    app: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      # config がAzure Files に置かれるのを待つ
      serviceAccountName: git-sync-service-account
      initContainers:
      - name: wait-for-git-sync
        image: bitnami/kubectl:1.27
        command: ["/bin/sh"]
        args: ["-c", "until [ \"$(kubectl get pods -l app='git-sync' -n 'git-sync-app' -o jsonpath='{.items[0].status.phase}')\" = 'Running' ]; do sleep 1; done"]
      containers:
        - name: app
          image: <イメージ>
          imagePullPolicy: Always
          resources:
            requests:
              cpu: 100m
              memory: 256Mi
          ports:
            - containerPort: 80
          volumeMounts:
            - name: azurefile
              mountPath: /mnt/azurefiles
      volumes:
        - name: azurefile
          persistentVolumeClaim:
            claimName: azurefile-pvc # AzureFilesのCSIドライバーを使ってプロビジョニングされたファイル共有を参照するPVCの名前
  • service Account
    他の Pod の情報を得るためには、serviceAccount を作成する必要があります。
git-sync-service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: git-sync-service-account
  namespace: git-sync-app
  • service Account に権限を付与する
git-sync-cluster-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: git-sync-cluster-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- kind: ServiceAccount
  name: git-sync-service-account
  namespace: git-sync-app

ClusterRole:view 権限をつけることにより、kubectl で pod の情報が取得できるようになります。もうちょっと細かく権限をつけたい場合は自作もできるそうですが、まあ pod 起動しかたどうかを見たいだけなので、view権限で。

あとがき

このPodができるようになったら、メインアプリケーション側の Pod でも同じPVCを使用するようにすると永続ボリュームが k8s 内で共有することができます(たぶん)
git-sync はオプションで webhook とかもあるので、更新されたら通知するとかいろいろできます。
それでは引き続き k8s 沼💀に落ちていきましょう。

参考

https://github.com/eclipse/che/issues/18350
https://qiita.com/toshihirock/items/9f039d20beed9752440f

脚注
  1. https://kubernetes.io/ja/docs/concepts/storage/volumes/#gitrepo ↩︎

Discussion