この構成では、DockerイメージをGitLab Container Registryへ置き、GKEがそこからpullします。作業はすべて手動です。GitLab CI/CDパイプラインは作りません。
過去に使ったGitLabトークンは失効済みという前提で、必要時に最小権限・有効期限付きの新しい資格情報を発行します。実在するトークン、ユーザー名、プロジェクトパスは記事やマニフェストへ書きません。

認証情報を用途で分ける
| 用途 | 推奨資格情報 | 必要scope |
|---|---|---|
| 開発者が手動push | Project access tokenなど | read_registry、write_registry |
| GKEがpull | Deploy Token | read_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_USERNAME、YOUR_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_registryscope不足- imagePullSecretのNamespace違い
- Deploymentの
imagePullSecrets名の誤り - GitLab側でイメージやタグが削除済み
401/403なら認証・権限、manifest unknownならパスやタグを優先して確認します。トークンをログへ表示して検証しないでください。
ローテーション
- 新しいDeploy Tokenを発行する
- Secret ManagerまたはimagePullSecretを新値へ更新する
- 新規Podがpullできることを固定タグで確認する
- 古いDeploy Tokenを失効する
- 監査記録へトークン値を含めず、実施日時と識別名だけを残す
既にNodeへイメージがキャッシュされていると、古い認証のままでもPodが起動したように見える場合があります。新しい未取得タグでpullを確認してから旧トークンを失効します。