CTS-KB

GKEからGitLab Container Registryのイメージをpullする:手動運用編

⏱ 約 4 分で読めます
#Kubernetes#GKE#GitLab#Container Registry#imagePullSecret

この構成では、DockerイメージをGitLab Container Registryへ置き、GKEがそこからpullします。作業はすべて手動です。GitLab CI/CDパイプラインは作りません。

過去に使ったGitLabトークンは失効済みという前提で、必要時に最小権限・有効期限付きの新しい資格情報を発行します。実在するトークン、ユーザー名、プロジェクトパスは記事やマニフェストへ書きません。

GKEがGitLab Container Registryからイメージを取得する流れ

認証情報を用途で分ける

用途推奨資格情報必要scope
開発者が手動pushProject access tokenなどread_registrywrite_registry
GKEがpullDeploy Tokenread_registry のみ

クラスタへ個人用トークンを置かないことが重要です。pullしかしないGKEに write_registry やAPI全体の権限は不要です。

1. 手元でイメージをbuildする

docker build -t example-app:local .
docker run --rm -p 8080:8080 example-app:local

ローカル動作を確認したら、GitLabの完全なイメージ名を付けます。

docker tag example-app:local \
  registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG

GROUP/PROJECT/IMAGE:TAG は説明用プレースホルダーです。実運用では変更不能なリリース番号やコミット識別子をタグに使い、latest だけに依存しません。

2. 手動push用トークンでログインする

GitLabでProject access tokenなどを発行し、対象プロジェクトとContainer Registryだけに必要なscope、有効期限を設定します。2要素認証を有効にしている場合も、GitLabパスワードではなくトークンを使います。

read -s GITLAB_PUSH_TOKEN
printf '%s' "${GITLAB_PUSH_TOKEN}" | \
  docker login registry.gitlab.com \
    --username YOUR_GITLAB_USERNAME \
    --password-stdin

docker push registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
docker logout registry.gitlab.com
unset GITLAB_PUSH_TOKEN

コマンド履歴へトークンそのものを書かないため --password-stdin を使います。共有端末ではDockerの認証情報保存方式も確認します。一時トークンならpushと検証後に失効させます。

3. pull専用Deploy Tokenを作る

GitLabプロジェクトまたはグループのDeploy Tokenを作成します。

  • scopeは read_registry のみ
  • 有効期限を設定
  • 用途が分かる名前にする
  • 発行時に表示された値をSecret Managerへ安全に保管
  • 画面やチケットへ貼らない

ユーザー名とトークンは発行後の安全な場所へ一度だけ保管します。本記事ではそれぞれ YOUR_DEPLOY_TOKEN_USERNAMEYOUR_DEPLOY_TOKEN と表します。

4. 手動でimagePullSecretを作る

最小の動作確認では、対象NamespaceにDocker Registry用Secretを作ります。

read -s GITLAB_DEPLOY_TOKEN

kubectl create secret docker-registry gitlab-registry \
  --docker-server=registry.gitlab.com \
  --docker-username=YOUR_DEPLOY_TOKEN_USERNAME \
  --docker-password="${GITLAB_DEPLOY_TOKEN}" \
  --namespace=YOUR_NAMESPACE

unset GITLAB_DEPLOY_TOKEN

引数として展開された値が同一マシンのプロセス情報から見える可能性があるため、共有端末では実行しません。継続運用では第11回のESOなどを使い、Secret Managerから kubernetes.io/dockerconfigjson 型のSecretを同期する方式を検討します。

Secretの値を表示せず、型と存在だけを確認します。

kubectl get secret gitlab-registry \
  -n YOUR_NAMESPACE \
  -o jsonpath='{.type}{"\n"}'

5. Deploymentから参照する

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-app
  namespace: YOUR_NAMESPACE
spec:
  replicas: 2
  selector:
    matchLabels:
      app: example-app
  template:
    metadata:
      labels:
        app: example-app
    spec:
      imagePullSecrets:
        - name: gitlab-registry
      containers:
        - name: app
          image: registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
          ports:
            - containerPort: 8080

imagePullSecrets はPodと同じNamespaceに存在する必要があります。Namespaceをまたいで直接共有できません。

kubectl apply -f deployment.yaml
kubectl rollout status deployment/example-app -n YOUR_NAMESPACE
kubectl get pods -n YOUR_NAMESPACE

ImagePullBackOffの切り分け

kubectl describe pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl get events -n YOUR_NAMESPACE --sort-by=.metadata.creationTimestamp

主な原因は次のとおりです。

  • イメージ名、グループ、プロジェクト、タグの誤り
  • Deploy Tokenの失効または期限切れ
  • read_registry scope不足
  • imagePullSecretのNamespace違い
  • Deploymentの imagePullSecrets 名の誤り
  • GitLab側でイメージやタグが削除済み

401/403なら認証・権限、manifest unknownならパスやタグを優先して確認します。トークンをログへ表示して検証しないでください。

ローテーション

  1. 新しいDeploy Tokenを発行する
  2. Secret ManagerまたはimagePullSecretを新値へ更新する
  3. 新規Podがpullできることを固定タグで確認する
  4. 古いDeploy Tokenを失効する
  5. 監査記録へトークン値を含めず、実施日時と識別名だけを残す

既にNodeへイメージがキャッシュされていると、古い認証のままでもPodが起動したように見える場合があります。新しい未取得タグでpullを確認してから旧トークンを失効します。

参考資料