#はじめに
Podをデプロイする際にコンテナイメージをPullしていますが、パブリックに公開されているイメージをPullする場合には特に認証は必要ありません。
通常業務に使う場合は、パブリックに公開されているイメージだけでなく自分でBuildしたコンテナイメージも使用すると思います。このような自分でBuildしたイメージはパブリックに公開できない場合もあると思いますので、その場合にはプライベートリポジトリからPullすることになります。その際の認証としてServiceAccountを利用できますので、今回はこの動作を確認したいと思います。
#アーキテクチャ
コンテナレジストリとして一番に思いつくのはDockerHubだと思います。このほかにもAWSやGCPなどのクラウドサービスでもレジストリサービスを提供していますが、今回はIBM Cloudのコンテナレジストリを使用したいと思います。
アーキテクチャとしては以下のようになります。
#IBM Cloud Container Registryの作成
##サービスプラン
IBM Cloud Container Registryは以下の範囲で無料で利用できます。有償版にアップグレードするとストレージサイズとプルトラフィックは無制限に利用できるようになりますが、利用量に応じて課金されます。
項目 | 無料枠 |
---|---|
ストレージサイズ | 500MB |
プルトラフィック | 5GB/月 |
##作成
IBM Cloudにログインし、カタログから「Container Registry」を探します。
「作成」をクリックします。
ロケーションを「東京」にして、「作成」をクリックします。
そうすると「名前空間の作成」ダイアログが出てきますので、ユニークな名称を設定して作成します。
#IBM Cloud CLIのインストール
以下に沿ってIBM Cloud CLIをインストールします。ここではKubernetesクラスタのMasterサーバ(CentOS 7)にインストールします。
$ curl -sL https://ibm.biz/idt-installer | bash
[main] --==[ IBM Cloud Developer Tools for Linux/MacOS - Installer, v1.2.3 ]==--
・・・
プラグイン名 バージョン 状況
cloud-functions/wsk/functions/fn 1.0.41
cloud-object-storage 1.1.3
container-registry 0.1.471
container-service/kubernetes-service 1.0.99
・・・
[install_plugins] Finished installing/updating plugins
[env_setup] WARN: Please restart your shell to enable 'ic' alias for ibmcloud!
[install] Install finished.
[main] --==[ Total time: 976 seconds ]==--
インストールできたら、ログインします。--ssoを付与すると、ブラウザにワンタイムパスワードが表示されますので、そのパスワードでログインします。
$ ibmcloud login --sso
API エンドポイント: https://cloud.ibm.com
インストールされたプラグインリストを確認します。
$ ibmcloud plugin list
インストール済みプラグインをリストしています...
プラグイン名 バージョン 状況
container-registry 0.1.471
container-service/kubernetes-service 1.0.99
cloud-functions/wsk/functions/fn 1.0.41
cloud-object-storage 1.1.3
作成したNamespaceが表示されることを確認します。
$ ibmcloud cr namespace-list
レジストリー「jp.icr.io」のアカウント「Kosuke Machida's Account」用の名前空間をリストしています...
名前空間
my-praivate-repo
OK
#レジストリへのイメージのPush
作成したレジストリへイメージをPushします。
##IBM Cloud Container Registryへのログイン
$ ibmcloud cr login
「jp.icr.io」にログインしています...
「jp.icr.io」にログインしました。
##コンテナイメージの作成
DockerHubからnginxのイメージをPullして、commit/tag付けして、IBM CloudにPushします。
###イメージのpull
$ docker pull nginx:latest
latest: Pulling from library/nginx
8559a31e96f4: Pull complete
8d69e59170f7: Pull complete
3f9f1ec1d262: Pull complete
d1f5ff4f210d: Pull complete
1e22bfa8652e: Pull complete
Digest: sha256:21f32f6c08406306d822a0e6e8b7dc81f53f336570e852e25fbe1e3e3d0d0133
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
###commit
nginxを起動して、index.htmlを更新し、commitします。
$ docker run -it nginx /bin/bash
root@62d65397eba0:/# echo "test server" > /usr/share/nginx/html/index.html
root@62d65397eba0:/# exit
$ docker ps -a | grep nginx
62d65397eba0 nginx "/docker-entrypoint.…" About a minute ago Exited (0) About a minute ago brave_mendeleev
59cbd948358f nginx "/docker-entrypoint.…" 17 minutes ago Exited (0) 14 minutes ago frosty_herschel
$ docker commit 62d65397eba0 nginx-custom
sha256:fbd9397264a98e3119ea6a5fb83cc40f120d6227d651438e9f2cfe49ac1102d1
$ docker images | grep nginx
nginx-custom latest fbd9397264a9 15 seconds ago 132MB
nginx latest 2622e6cca7eb 11 days ago 132MB
###tag付け
$ docker tag fbd9397264a9 jp.icr.io/my-praivate-repo/nginx-custom:latest
$ docker images |grep nginx
jp.icr.io/my-praivate-repo/nginx-custom latest fbd9397264a9 5 minutes ago 132MB
nginx-custom latest fbd9397264a9 5 minutes ago 132MB
nginx latest 2622e6cca7eb 11 days ago 132MB
###push
イメージをIBM CloudにPushして確認します。
$ docker push jp.icr.io/my-praivate-repo/nginx-custom:latest
The push refers to repository [jp.icr.io/my-praivate-repo/nginx-custom]
d43db004e4c6: Pushed
f978b9ed3f26: Pushed
9040af41bb66: Pushed
7c7d7f446182: Pushed
d4cf327d8ef5: Pushed
13cb14c2acd3: Pushed
latest: digest: sha256:cf199a373ba30d3d8470f4fc9cd904292dedeb0c53f4a5435576121c2dc4ba33 size: 1569
$ ibmcloud cr image-list
イメージをリストしています...
リポジトリー タグ ダイジェスト 名前空間 作成日 サイズ セキュリティー状況
jp.icr.io/my-praivate-repo/nginx-custom latest cf199a373ba3 my-praivate-repo 7 minutes ago 53 MB 7 件の問題
OK
####コンソールからの確認
コンソールからも確認できます。
何やらセキュリティ状況に「7件の問題」とありますので、確認してみます。
IBM Cloud Container Registryには脆弱性アドバイザー機能があって、自動でコンテナイメージを検査してくれます。便利ですね。
今回は無視して先に進みたいと思います。詳細はこちらに記載されています。
脆弱性アドバイザーを使用したイメージ・セキュリティーの管理
#認証とイメージのPull
Container Registryへのアクセスを許可する認証にはIAM(IBM Cloud Identity and Access Management)を利用します。トークンも利用できるのですが、2020年8月12日以降使用できなくなるようで、非推奨となっています。
##IAMの設定
マニュアルを探してみても設定方法がまとまって書かれていませんでした。行きついた先はOpenShift on IBM Cloudのマニュアルです。
Container Registry単独で使うことはあまり想定していないのかも知れませんね。
これに沿ってIAMを設定します。
IBM Cloud IAM サービスID
IBM Cloud IAM サービスID を作成します。
$ ibmcloud iam service-id-create test-cluster-id --description "Service ID for IBM Cloud Container Registry"
dingtianhongjie@XXXX.jp として 現行アカウント にバインドされるサービス ID test-cluster-id を作成しています...
OK
サービス ID test-cluster-id が正常に作成されました
ID ServiceId-533a112f-c0c0-4150-XXXX-XXXXXXXXXXX
名前 test-cluster-id
説明 Service ID for IBM Cloud Container Registry
CRN crn:v1:bluemix:public:iam-identity::a/3XXXXXXXXXXXXXXXXXXXX::serviceid:ServiceId-533a112f-c0c0-XXXX-XXXX-XXXXXXXXXXXXXX
バージョン 1-4b6d6e29dbXXXXXXXXXXXXXXX
ロック中 false
###カスタム IBM Cloud IAM ポリシー
IBM Cloud Container Registry へのアクセス権を与えるカスタム IBM Cloud IAM ポリシーを作成したサービスIDに設定します。
$ ibmcloud iam service-policy-create test-cluster-id --roles Manager --service-name container-registry
dingtianhongjie@XXXX.jp としてサービス ID test-cluster-id の 現行アカウント にポリシーを作成しています...
失敗
役割 Manager が見つかりませんでした。 有効な役割は 管理者, ライター, リーダー, ビューアー, 管理者, オペレーター, エディター です。
$ ibmcloud iam service-policy-create test-cluster-id --roles 管理者 --service-name container-registry
dingtianhongjie@XXXX.jp としてサービス ID test-cluster-id の 現行アカウント にポリシーを作成しています...
OK
サービス・ポリシーは正常に作成されます
ポリシー ID: 7f0c250f-68b2-XXXX-XXXX-XXXXXXXXXX
バージョン: 1-558268f56XXXXXXXXXXXXXXXXXXXX
役割: 管理者
リソース:
サービス名 container-registry
マニュアルの通りにrolesに「Manager」を指定したら失敗。メッセージの通りに「管理者」としたら通りました。全角文字で指定することがあるんですね。
###APIキー
サービス ID の API キーを作成します。
$ ibmcloud iam service-api-key-create test-cluster-key test-cluster-id --description "Service ID for IBM Cloud Container Registry"
dingtianhongjie@XXXX.jp としてアカウント 3fec0071XXXXXXXXXXXXXXX にサービス ID test-cluster-id の API キー test-cluster-key を作成しています...
OK
サービス ID API キー test-cluster-key が作成されます
API キーを保存してください。 作成後に取得することはできません。
ID ApiKey-5282e4cd-61f2-XXXX-XXXX-XXXXXXXXXXXX
名前 test-cluster-key
説明 Service ID for IBM Cloud Container Registry
作成日時 2020-06-21T12:35+0000
API キー i6KasN38UK--XXXXXXXXXXXXXXXXXX_XXXXXX
ロック中 false
##SecretとServiceAccountの作成
作成したAPIキーを元にSecretとServiceAccountを作成します。
###Secret
以下のコマンドで作成します。
パラメータ | 設定値 |
---|---|
docker-server | Container Resistryのリージョンに応じて設定 |
docker-username | IBM Cloudの場合「iamapikey」固定 |
docker-password | APIキー |
docker-email | メールアドレス(架空のアドレスでも可) |
$ kubectl create secret docker-registry ibmcr --docker-server=jp.icr.io --docker-username=iamapikey --docker-password=i6KasN38UK--XXXXXXXXXXXXXXXXX_XXXXXX --docker-email=dingtianhongjie@XXXXXXX.jp
$ kubectl describe secrets ibmcr
Name: ibmcr
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson: 229 bytes
###ServiceAccount
以下のマニフェストで作成します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: service-account-image-pull
imagePullSecrets:
- name: ibmcr #作成したSecretを指定
$ kubectl apply -f serviceAccount-imagePull.yaml
serviceaccount/service-account-image-pull created
$ kubectl describe serviceaccounts service-account-image-pull
Name: service-account-image-pull
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","imagePullSecrets":[{"name":"ibmcr"}],"kind":"ServiceAccount","metadata":{"annotations":{},"name":"service-account-imag...
Image pull secrets: ibmcr
Mountable secrets: service-account-image-pull-token-mfn8r
Tokens: service-account-image-pull-token-mfn8r
Events: <none>
##イメージのPull(Podのデプロイ)
以下のマニフェストでPodをデプロイします。
なお、ServiceAccountを作成しない場合、PodにimagePullSecretsを指定することでも可能です。
apiVersion: v1
kind: Pod
metadata:
name: nginx-custom
spec:
containers:
- name: nginx
image: jp.icr.io/my-praivate-repo/nginx-custom:latest
command:
- sh
- -c
args:
- tail -f /dev/null
serviceAccountName: service-account-image-pull
$ kubectl apply -f pod02.yaml
pod/nginx-custom created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-custom 1/1 Running 0 4s
念のためコンテナにログインしてindex.htmlが編集したものになっているか確認します。
$ kubectl exec -it nginx-custom cat /usr/share/nginx/html/index.html
test server
また、PodのマニフェストでServiceAccountを指定しない、かつimagePullSecretsを指定しない場合、以下のように認証ができずPullに失敗します。
$ kubectl apply -f pod03.yaml
pod/nginx-custom-temp created
$ kubectl describe pod nginx-custom-temp
Name: nginx-custom-temp
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 12s default-scheduler Successfully assigned default/nginx-custom-temp to k8s-worker02
Normal Pulling 11s kubelet, k8s-worker02 Pulling image "jp.icr.io/my-praivate-repo/nginx-custom:latest"
Warning Failed 11s kubelet, k8s-worker02 Failed to pull image "jp.icr.io/my-praivate-repo/nginx-custom:latest": rpc error: code = Unknown desc = Error response from daemon: Get https://jp.icr.io/v2/my-praivate-repo/nginx-custom/manifests/latest: unauthorized: authentication required
Warning Failed 11s kubelet, k8s-worker02 Error: ErrImagePull
Normal BackOff 9s (x2 over 10s) kubelet, k8s-worker02 Back-off pulling image "jp.icr.io/my-praivate-repo/nginx-custom:latest"
Warning Failed 9s (x2 over 10s) kubelet, k8s-worker02 Error: ImagePullBackOff
#まとめ
今回はServiceAccountというよりも、IBM Cloudの設定に苦戦しました。
まあ、クラウドの設定からSeviceAccountでの動作確認までできましたので、どちらも理解が深まりました。今回はContainer Registry単体で利用しましたので、CICDにも応用していきたいと思います。