メインコンテンツまでスキップ

kubectl で imagePullSecret を作成する

プライベート registry からイメージを pull するには、Kubernetes クラスターに kubernetes.io/dockerconfigjson タイプの Secret が必要です。この Secret は imagePullSecret と呼ばれます。これがないと、Pod は ImagePullBackOff のままで、アプリケーションは起動しません。これは、プライベートイメージを使うアプリを deploy する developer、複数の namespace 用に Secret を準備する platform engineer、認証情報をローテーションするたびに Secret を再作成する CI/CD pipeline のいずれにも当てはまります。このチュートリアルを完了すると、namespace 内に Secret が作成され、workload が Container Registry からプライベートイメージを正常に pull できるようになります。

前提条件​

  • kubectl がクラスターに接続されていること。kubectl get nodes で確認します。
  • 対象 namespace に Secret を作成する権限があること。kubectl auth can-i create secret -n <namespace> で確認します。
  • Container Registry のログイン情報を持っていること。FPT Portal の Container Registry > Get Token から取得します。

個人アカウントではなく、pull 権限のみを持つ Robot Account を使用してください。Robot Account の作成 を参照してください。

Secret を作成する​

kubectl create secret docker-registry regcred \
--docker-server=registry.fptcloud.com \
--docker-username='robot$my-project+ci' \
--docker-password='Xy9!kP2$mQ' \
--namespace=my-app

成功すると、次のように返されます。

secret/regcred created
警告

以下の 3 点を誤ると、Secret は正常に作成されたように見えても認証に失敗します。

  • password は必ず一重引用符('...')で囲んでください。$、!、& などの文字を囲まないと、シェルによって値が変わってしまい、コマンドは成功と表示されても Secret には誤った値が保存されます。
  • --docker-server は、イメージ名の先頭にあるホスト部分とだけ一致させてください。https:// プレフィックスやプロジェクト名は含めません。
  • --namespace は workload が実行される namespace と一致させてください。Secret は namespace をまたいで使用できません。
ヒント

username と password はコマンドに直接書かず、環境変数経由で渡してください。また、.dockerconfigjson を含む YAML ファイルを Git にコミットしないでください。

kubectl create secret docker-registry が受け付けるすべてのフラグと、Secret の命名規則については、imagePullSecret フィールドリファレンス を参照してください。

Secret を workload にアタッチする​

Pod テンプレートに imagePullSecrets を追加します。

spec:
template:
spec:
imagePullSecrets:
- name: regcred
containers:
- name: api
image: registry.fptcloud.com/my-project/api:v1
kubectl apply -f deployment.yaml

同じ namespace 内の複数の workload が同じ registry を使う場合は、各マニフェストを編集する代わりに、Secret を ServiceAccount にアタッチします。

kubectl patch serviceaccount default -n my-app \
-p '{"imagePullSecrets":[{"name":"regcred"}]}'
注記

ServiceAccount への patch は、patch 後に作成された Pod にのみ適用されます。既に実行中の Pod に反映するには、kubectl rollout restart が必要です。

Secret が機能しているか確認する​

kubectl get pods -n my-app
ステータス意味対応
ContainerCreatingまだ pull 中です。しばらく待って再確認してください。
Runningpull に成功しました。これ以上の対応は不要です。
ErrImagePull最初の pull が失敗しました。トラブルシューティング を参照してください。
ImagePullBackOffKubernetes が再試行しても失敗しました。トラブルシューティング を参照してください。

具体的な原因を確認するには、Pod の Events を確認します。

kubectl describe pod <pod-name> -n my-app | tail -20

末尾の Events セクションで、認証エラーとイメージが見つからないエラーを区別できます。

Secret に保存された認証情報を確認するには、次を実行します。

kubectl get secret regcred -n my-app \
-o jsonpath='{.data.\.dockerconfigjson}' | base64 -d

正しい結果には、registry のアドレスを含む auths ブロックと空でない auth フィールドが含まれ、Pod は Running になります。

Docker の設定ファイルから Secret を作成する​

password にエスケープが難しい文字が含まれる場合、または既に docker login 済みの場合は、この方法を使います。

docker login registry.fptcloud.com

kubectl create secret docker-registry regcred \
--from-file=$HOME/.docker/config.json \
--namespace=my-app

この方法を使う前に、ファイルの内容を確認してください。

cat ~/.docker/config.json

ファイルに "auth" フィールドを持つ "auths" ブロックではなく "credsStore" が含まれている場合、Docker は認証情報を OS のキーチェーンに保存しています。このファイルから作成した Secret は空になるため、前の節の kubectl create secret docker-registry コマンドを使ってください。

Secret を再作成する、または複数の namespace で使う​

既に存在する Secret に対して kubectl create secret を再実行すると AlreadyExists エラーになります。スクリプトや CI/CD では、kubectl apply にパイプして、何度でも安全に実行できるようにします。

kubectl create secret docker-registry regcred \
--docker-server=registry.fptcloud.com \
--docker-username="$REG_USER" \
--docker-password="$REG_PASS" \
--namespace=my-app \
--dry-run=client -o yaml | kubectl apply -f -

Secret は namespace をまたいで使用できないため、必要な namespace ごとに同じコマンドを繰り返します。

for ns in app-dev app-staging app-prod; do
kubectl create secret docker-registry regcred \
--docker-server=registry.fptcloud.com \
--docker-username="$REG_USER" \
--docker-password="$REG_PASS" \
--namespace="$ns" \
--dry-run=client -o yaml | kubectl apply -f -
done

認証情報をローテーションした後に Secret を更新する​

実行中の Pod は、ローテーションされた認証情報を自動では読み込みません。新しい認証情報で Secret を再作成または更新したら、workload を再起動して反映させます。

kubectl rollout restart deployment/api -n my-app

次のステップ​