1. そもそもこの記事を書く上でのきっかけ
IBM Cloud monitoring(Sysdig)やIBM Cloud Log Analysis(LogDNA/MEZMO)をUI上からROKSに導入するとibm-observe
というnamespaceにDaemon Setが作成される。利用されるイメージは、以下の通り、icr.io
という外部レジストリーを利用している。
[root@new-syasuda-tok1-vpc1 ~]# oc version
Client Version: 4.11.0-202210250857.p0.g142cb44.assembly.stream-142cb44
Kustomize Version: v4.5.4
Server Version: 4.11.12
Kubernetes Version: v1.24.6+5157800
[root@new-syasuda-tok1-vpc1 ~]# oc get ds -n ibm-observe
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
logdna-agent 2 2 2 2 2 <none> 50d
sysdig-agent 2 2 2 2 2 <none> 50d
[root@new-syasuda-tok1-vpc1 ~]# oc get pods -n ibm-observe
NAME READY STATUS RESTARTS AGE
logdna-agent-2p6p4 1/1 Running 0 30h
logdna-agent-75pxm 1/1 Running 0 30h
sysdig-agent-b9tlg 1/1 Running 0 30h
sysdig-agent-tx6q7 1/1 Running 0 30h
[root@new-syasuda-tok1-vpc1 ~]# oc get pods logdna-agent-2p6p4 -n ibm-observe -o yaml|grep -i image
image: icr.io/ext/logdna-agent:stable
imagePullPolicy: Always
imagePullSecrets:
image: icr.io/ext/logdna-agent:stable
imageID: icr.io/ext/logdna-agent@sha256:a52f2e44ad7db9f88cb3da9565772734449ec97c8c6182b4369d42928c3eaa23
[root@new-syasuda-tok1-vpc1 ~]# oc get pods sysdig-agent-b9tlg -n ibm-observe -o yaml|grep -i image
image: icr.io/ext/sysdig/agent
imagePullPolicy: Always
imagePullSecrets:
image: icr.io/ext/sysdig/agent:latest
imageID: icr.io/ext/sysdig/agent@sha256:45b10702667b33b0663dd23164fc9f928945083060c14c3dd1e4b538b9348942
一方、icr.ioはpublic registryではない。以下のように認証なしにはアクセスできない。よって、どこかに認証情報が構成されている必要がある。
[root@new-syasuda-tok1-vpc1 ~]# skopeo inspect docker://icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0
FATA[0001] Error parsing image name "docker://icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0": unable to retrieve auth token: invalid username/password: unauthorized: The login credentials are not valid, or your IBM Cloud account is not active.
[root@new-syasuda-tok1-vpc1 ~]# skopeo inspect docker://private.icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0
FATA[0001] Error parsing image name "docker://private.icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0": unable to retrieve auth token: invalid username/password: unauthorized: The login credentials are not valid, or your IBM Cloud account is not active.
しかし、以下のようにこのDaemon Setに紐づいているService Accountのpull secretsにはicr.ioに関する認証情報は含まれていない。一般的には、default namespaceに存在するall-icr-ioというsecretを該当のnamespaceにコピーして使うようにガイドされているが、他にそういうsecretがコピーされている様子もない。では、どこでicr.ioへの認証は行われているのだろうか? それとも、ibm-observe
というnamespaceだけ何か特別な設定がされているのだろうか?という疑問が生じたのがこの記事を書くきっかけである。
[root@new-syasuda-tok1-vpc1 ~]# oc get ds logdna-agent -n ibm-observe -o jsonpath='{.spec.template.spec.serviceAccount}{"\n"}'
logdna-agent
[root@new-syasuda-tok1-vpc1 ~]# oc describe sa logdna-agent -n ibm-observe
Name: logdna-agent
Namespace: ibm-observe
Labels: <none>
Annotations: <none>
Image pull secrets: logdna-agent-dockercfg-lmqwp
Mountable secrets: logdna-agent-dockercfg-lmqwp
Tokens: logdna-agent-token-b2qgh
Events: <none>
[root@new-syasuda-tok1-vpc1 ~]# oc get secrets logdna-agent-dockercfg-lmqwp -n ibm-observe -o jsonpath='{.data.\.dockercfg}' | base64 -d | jq
{
"172.21.75.245:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
},
"image-registry.openshift-image-registry.svc.cluster.local:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
},
"image-registry.openshift-image-registry.svc:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
}
}
[root@new-syasuda-tok1-vpc1 ~]# oc get ds sysdig-agent -n ibm-observe -o jsonpath='{.spec.template.spec.serviceAccount}{"\n"}'
sysdig-agent
[root@new-syasuda-tok1-vpc1 ~]# oc describe sa sysdig-agent -n ibm-observe
Name: sysdig-agent
Namespace: ibm-observe
Labels: <none>
Annotations: <none>
Image pull secrets: sysdig-agent-dockercfg-5f55h
Mountable secrets: sysdig-agent-dockercfg-5f55h
Tokens: sysdig-agent-token-4474r
Events: <none>
[root@new-syasuda-tok1-vpc1 ~]# oc get secrets sysdig-agent-dockercfg-5f55h -n ibm-observe -o jsonpath='{.data.\.dockercfg}' | base64 -d | jq
{
"172.21.75.245:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
},
"image-registry.openshift-image-registry.svc.cluster.local:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
},
"image-registry.openshift-image-registry.svc:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
}
}
openshift-configなどのnamespaceにも当然含まれていない。
[root@new-syasuda-tok1-vpc1 ~]# oc get secrets -n openshift-config
NAME TYPE DATA AGE
builder-dockercfg-td579 kubernetes.io/dockercfg 1 510d
builder-token-wrmmf kubernetes.io/service-account-token 4 510d
builder-token-xzrc2 kubernetes.io/service-account-token 4 510d
default-dockercfg-45r68 kubernetes.io/dockercfg 1 510d
default-token-7kv57 kubernetes.io/service-account-token 4 510d
default-token-dhczn kubernetes.io/service-account-token 4 510d
deployer-dockercfg-t4zq2 kubernetes.io/dockercfg 1 510d
deployer-token-fz5jv kubernetes.io/service-account-token 4 510d
deployer-token-xjglw kubernetes.io/service-account-token 4 510d
htpasswd-secret Opaque 1 497d
pull-secret kubernetes.io/dockerconfigjson 1 510d
[root@new-syasuda-tok1-vpc1 ~]# oc get secrets pull-secret -n openshift-config -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq
{
"auths": {
"cloud.openshift.com": {
"auth": "<data>",
"email": "ibmocp@us.ibm.com"
},
"quay.io": {
"auth": "<data>",
"email": "ibmocp@us.ibm.com"
},
"registry.connect.redhat.com": {
"auth": "<data>",
"email": "ibmocp@us.ibm.com"
},
"registry.redhat.io": {
"auth": "<data>",
"email": "ibmocp@us.ibm.com"
}
}
}
2. 任意のnamespaceからもicr.io上のイメージを取得できてしまう。
試しに、新規にprojectを作成し、そこにicr.io上のイメージを指定してPodを動かそうとしてみたが、驚くべきことに、無事イメージを取得できてしまった。当然該当するデフォルトのsecretにはicr.ioに対する認証情報は含まれていない。よって、これはIBM Cloud monitoring(Sysdig)やIBM Cloud Log Analysis(LogDNA/MEZMO)だけで何か特別に行われている構成ではなく、プラットフォーム全体で有効な設定であることが想像される。
[root@new-syasuda-tok1-vpc1 ~]# oc new-project testproject1
[root@new-syasuda-tok1-vpc1 ~]# oc run samplepod1 --image=icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0
[root@new-syasuda-tok1-vpc1 ~]# oc get pods
NAME READY STATUS RESTARTS AGE
samplepod1 1/1 Running 0 30s
[root@new-syasuda-tok1-vpc1 ~]# oc describe pod samplepod1
(途中略)
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 33s default-scheduler Successfully assigned syasuda1/samplepod1 to 10.0.0.25 by kube-scheduler-794dfbddfd-7sgsv
Normal AddedInterface 31s multus Add eth0 [172.17.34.53/32] from k8s-pod-network
Normal Pulled 31s kubelet Container image "icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0" already present on machine
Normal Created 31s kubelet Created container samplepod1
Normal Started 31s kubelet Started container samplepod1
[root@new-syasuda-tok1-vpc1 ~]# oc get pods samplepod1 -o jsonpath='{.spec.imagePullSecrets[*].name}{"\n"}'
default-dockercfg-lkb8m
[root@new-syasuda-tok1-vpc1 ~]# oc get secrets
NAME TYPE DATA AGE
builder-dockercfg-wwwpt kubernetes.io/dockercfg 1 15m
builder-token-x4p8g kubernetes.io/service-account-token 4 15m
default-dockercfg-lkb8m kubernetes.io/dockercfg 1 15m
default-token-mrv6r kubernetes.io/service-account-token 4 15m
deployer-dockercfg-nd2kh kubernetes.io/dockercfg 1 15m
deployer-token-9vjcg kubernetes.io/service-account-token 4 15m
[root@new-syasuda-tok1-vpc1 ~]# oc get secrets default-dockercfg-lkb8m -o jsonpath='{.data.\.dockercfg}' | base64 -d | jq
{
"172.21.75.245:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
},
"image-registry.openshift-image-registry.svc.cluster.local:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
},
"image-registry.openshift-image-registry.svc:5000": {
"username": "serviceaccount",
"password": "<data>",
"email": "serviceaccount@example.org",
"auth": "<data>"
}
}
ちなみに、icr.ioではなく、private.icr.ioを利用した場合は以下のように失敗するため、これはicr.ioだけ許容される操作なのであろうと想像される。
[root@new-syasuda-tok1-vpc1 ~]# oc run samplepod2 --image=private.icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0
[root@new-syasuda-tok1-vpc1 ~]# oc describe pod samplepod2
(途中略)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 36s default-scheduler Successfully assigned testproject1/samplepod2 to 10.0.0.25 by kube-scheduler-794dfbddfd-7sgsv
Normal AddedInterface 36s multus Add eth0 [172.17.34.31/32] from k8s-pod-network
Normal BackOff 6s (x2 over 34s) kubelet Back-off pulling image "private.icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0"
Warning Failed 6s (x2 over 34s) kubelet Error: ImagePullBackOff
Normal Pulling <invalid> (x3 over 35s) kubelet Pulling image "private.icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0"
Warning Failed <invalid> (x3 over 34s) kubelet Failed to pull image "private.icr.io/ext/istio/examples-bookinfo-reviews-v3:1.15.0": rpc error: code = Unknown desc = unable to retrieve auth token: invalid username/password: unauthorized: The login credentials are not valid, or your IBM Cloud account is not active.
Warning Failed <invalid> (x3 over 34s) kubelet Error: ErrImagePull
3. アクセスできる理由はノード構成にある
結局、この辺りはkubeletのノード側の構成にあるのではないだろうかと想像して、ノードの中を探ってみたらビンゴだった。
[root@new-syasuda-tok1-vpc1 ~]# oc debug -t node/10.0.0.25 -- chroot /host
sh-4.4# ls -ld /var/lib/kubelet
lrwxrwxrwx. 1 root root 17 Oct 4 17:35 /var/lib/kubelet -> /var/data/kubelet
sh-4.4# ps -ef|grep kubelet.conf |grep -v grep
root 7978 1 9 Oct04 ? 5-08:36:25 kubelet --config=/etc/kubernetes/kubelet.conf --root-dir=/var/data/kubelet --v=2 --kubeconfig=/etc/kubernetes/kubelet-kubeconfig --hostname-override=10.0.0.25 --cloud-provider=external --container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock --runtime-cgroups=/podruntime.slice
sh-4.4# ls -l /var/data/kubelet
total 32
-rw-------. 1 root root 3533 Oct 4 17:36 config.json
-rw-------. 1 root root 62 Oct 4 17:36 cpu_manager_state
drwxr-xr-x. 2 root root 4096 Oct 4 17:36 device-plugins
-rw-------. 1 root root 61 Oct 4 17:36 memory_manager_state
drwxr-x---. 2 root root 4096 Oct 4 17:36 plugins
drwxr-x---. 2 root root 4096 Oct 4 17:36 plugins_registry
drwxr-x---. 2 root root 4096 Oct 4 17:36 pod-resources
drwxr-x---. 60 root root 4096 Nov 24 23:45 pods
sh-4.4# cat /var/data/kubelet/config.json | jq
{
"auths": {
"cloud.openshift.com": {
"auth": "<data>"
},
"quay.io": {
"auth": "<data>"
},
"registry.connect.redhat.com": {
"auth": "<data>"
},
"registry.redhat.io": {
"auth": "<data>"
},
"icr.io": {
"auth": "<data>"
},
"registry.bluemix.net": {
"auth": "<data>"
},
"registry.au-syd.bluemix.net": {
"auth": "<data>"
},
"registry.eu-gb.bluemix.net": {
"auth": "<data>"
},
"registry.eu-de.bluemix.net": {
"auth": "<data>"
},
"registry.ng.bluemix.net": {
"auth": "<data>"
}
}
}
sh-4.4# cat /var/data/kubelet/config.json | jq -r '.auths."icr.io".auth' | base64 -d
iamapikey:<API Key情報>
icr.ioにアクセスできるからといっても、当然構成されているAPIKeyの権限でアクセスできるイメージにしかアクセスできないはずである。おそらくicr.io/extなどのイメージしかアクセスできないのだろう。念のため、この情報を使ってicr.io(IBM Cloud Container Registry)にアクセスできることも確認してみた。
[root@new-syasuda-tok1-vpc1 ~]# ibmcloud login --apikey $(oc debug -t node/10.0.0.25 -- chroot host cat /var/data/kubelet/config.json | jq -r '.auths."icr.io".auth' | base64 -d| cut -f 2 -d ":")
[root@new-syasuda-tok1-vpc1 ~]# ibmcloud cr info
Plugin version 1.0.2
Container Registry icr.io
Container Registry API endpoint https://icr.io/api
IBM Cloud API endpoint https://cloud.ibm.com
IBM Cloud account details Argonauts Production 531277 (e223e119c9be31669e5688bb376411f7)
[root@new-syasuda-tok1-vpc1 ~]# ibmcloud cr images --restrict ext/sysdig/agent | grep -e Tag -e latest
Repository Tag Digest Namespace Created Size Security status
icr.io/ext/sysdig/agent latest 45b10702667b ext 2 weeks ago 696 MB -
[root@new-syasuda-tok1-vpc1 ~]# ibmcloud cr images --restrict ext/logdna-agent | grep -e Tag -e stable
Repository Tag Digest Namespace Created Size Security status
icr.io/ext/logdna-agent stable 48deacca9636 ext 1 day ago 125 MB -
icr.io/ext/logdna-agent v2-stable 48deacca9636 ext 1 day ago 125 MB -
[root@new-syasuda-tok1-vpc1 ~]# ibmcloud cr images --restrict ext/istio/examples-bookinfo-reviews-v3 | grep -e Tag -e 1.15.0
Repository Tag Digest Namespace Created Size Security status
icr.io/ext/istio/examples-bookinfo-reviews-v3 1.15.0 e454cab754cf ext 3 years ago 329 MB -