Zero to JupyterHub with Kubernetes(Z2JH)でユーザデータをS3にバックアップ

背景

EKSでZero to JupyterHub with Kubernetes(Z2JH)で構築したJupyterHubを運用しています。
障害時の回復力を高めるため、AWS外のストレージ(Cloud Storage等)にバックアップの複製を作成することになり、Storage Transfer ServiceRcloneの利用が可能なS3にユーザデータ(ノートブック等)のバックアップを取得する方式を構築しました。

実行環境

  • EKS 1.25
  • Z2JH 3.2.0

IAM ServiceAccountの作成

ノートブックサーバにS3バケットへの書き込み権限を与えるサービスアカウント singleuser を作成します。

$ BUCKET_NAME=<bucket-name>
$ POLICY_FILE=$(mktemp -t s3.iam.policy.json)
$ cat<<EOF> ${POLICY_FILE}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::${BUCKET_NAME}/*"
      ]
    }
  ]
}
EOF

$ POLICY_ARN=$(
    aws iam create-policy \
      --policy-name AmazonS3BucketWriteOnlyAccess \
      --policy-document file://${POLICY_FILE} \
      --query 'Policy.Arn' \
      --output text
  )

$ CLUSTER_NAME=<cluster-name>
$ NAMESPACE=<namespace>
$ eksctl create iamserviceaccount \
    --cluster=${CLUSTER_NAME} \
    --namespace=${NAMESPACE} \
    --name=singleuser \
    --attach-policy-arn=${POLICY_ARN} \
    --approve

Z2JHの設定

チャートの values.yaml にバックアップ処理を追加します。

singleuser.serviceAccountNameでServiceAccount singleuser を指定し、 バケットへの書き込み権限を付与します。

singleuser:
  serviceAccountName: singleuser

singleuser.lifecycleHooks.preStopでサーバの停止時にS3にユーザデータをコピーする処理を追加します。

singleuser:
  lifecycleHooks:
    preStop:
      exec:
        command:
          - sh
          - -c
          - >
            tar -C /home/jovyan -czf .${JUPYTERHUB_USER}.tar.gz .;
            aws s3 cp .${JUPYTERHUB_USER}.tar.gz s3://<bucket-name>/jhub/singleuser/${JUPYTERHUB_USER}.tar.gz; # <bucket-name>にバケット名を指定
            rm .${JUPYTERHUB_USER}.tar.gz;

preStop の処理が中断されないようにhub.extraConfigc.KubeSpawner.delete_grace_periodを設定し、Pod削除までの時間を延長します。

hub:
  extraConfig:
    kubeSpawnerConfig:
      c.KubeSpawner.delete_grace_period = 30

バックアップの確認

これでノートブックサーバの停止を契機に、バケットにバックアップファイルが作成されるようになりました。