GKE における k8s.gcr.io 廃止の影響について

2023/04/14に公開

こんにちは。クラウドエースの阿部です。
この記事では、Google Kubernetes Engine (GKE)における k8s.gcr.io 廃止の影響について調査したことをまとめています。

k8s.gcr.io 廃止と registry.k8s.io への移行について

廃止の経緯

Kubernetes v1.25以降において、kube-system等で使用される標準のコンテナイメージは k8s.gcr.io から registry.k8s.io に変更されました。(v1.22, v1.23, v1.24にもバックポートされるようです。)
また、 k8s.gcr.io は非推奨となり、2023/3/20から段階的に registry.k8s.io へリダイレクトされます。
この件の詳細については、下記の Kubernetes 公式ブログに記載されています。

https://kubernetes.io/blog/2022/11/28/registry-k8s-io-faster-cheaper-ga/

https://kubernetes.io/blog/2023/03/10/image-registry-redirect/

k8s.gcr.io を廃止する理由は、一言でいうと Google Container Registry を使ってコミュニティ標準のイメージをホストすると Google というベンダーに依存し過ぎてしまうため、中立的なイメージホスティングサービスで管理するべきだという議論の結果のようです。

移行措置

k8s.gcr.io を使用しているシステム向けに、 k8s.gcr.io へのアクセスを registry.k8s.io にリダイレクトする移行措置を行っています。この移行措置はいつまで継続するかは不明ですが、 k8s.gcr.io でホストされているコンテナイメージを使用している場合はできるだけ早く registry.k8s.io でホストさてているコンテナイメージを使用するか、または、 crane 等のイメージコピーツールを使い、自身が管理しているプライベートコンテナレジストリ(Google Cloud であれば、Artifact Registry 等)にコピーしてコンテナを使用します。

調査方法

Kubernetes ブログGoogle Cloud 公式ブログで、 k8s.gcr.io のコンテナが使用されているかを調査する方法が紹介されています。
以下の手順で確認できます。

方法1. Pod の出力を kubectl jsonpath オプションで表示

クラスタの全 Namespace の Pod を参照可能なアカウントで、下記のコマンドラインを実行することで確認できます。

実行コマンド
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" |\
tr -s '[[:space:]]' '\n' |\
sort |\
uniq -c |\
grep "k8s.gcr.io"

以下は実際の実行結果です。
この結果の場合、k8s.gcr.io/prometheus-to-sd:v0.9.1を使っているPodが起動1つ起動していることになります。

実行結果例
      1 k8s.gcr.io/prometheus-to-sd:v0.9.1

この方法は全Namespace の Pod から spec.containers.image を機械的に表示しているだけのため、 k8s.gcr.io のコンテナを使っているかどうかは簡単にわかりますが、どの Pod が該当のコンテナを使っているかを調査することは難しいです。

方法2. kubectl krew community-images プラグインで表示

kubectl krew コマンドで community-images プラグインを導入することで、 k8s.gcr.io のコンテナの使用有無を調査することができます。
方法1に比べ、どの Pod で実行されているかまで表示されるため、スムーズに調査することが可能です。

community-images導入手順
kubectl krew install community-images
community-images実行手順
kubectl community-images

下記は kubectl community-images の実行例です。

kubectl community-images 実行結果例
kubectl community-images 実行結果

Images being used in Kubernetes cluster @ https://***.***.***.***

 ✅ gke-release/cnrm/deletiondefender:c3120b9 (Location: cnrm-system > cnrm-deletiondefender-0 > deletiondefender)
 ❌ k8s.gcr.io/prometheus-to-sd:v0.9.1 (Location: cnrm-system > cnrm-resource-stats-recorder-6dfc78996c-zb9vm > recorder)
 ✅ gke-release/cnrm/recorder:c3120b9 (Location: cnrm-system > cnrm-resource-stats-recorder-6dfc78996c-zb9vm > recorder)
 ✅ gke-release/cnrm/webhook:c3120b9 (Location: cnrm-system > cnrm-webhook-manager-778cdd84cb-9wbkp > webhook)
 ✅ gke-release/cnrm/operator:0bac0f3 (Location: configconnector-operator-system > configconnector-operator-0 > manager)
 ✅ gke.gcr.io/event-exporter:v0.3.9-gke.0 (Location: kube-system > event-exporter-gke-f66d9f855-t2v4g > prometheus-to-sd-exporter)
 ✅ gke.gcr.io/prometheus-to-sd:v0.10.0-gke.0 (Location: kube-system > event-exporter-gke-f66d9f855-t2v4g > prometheus-to-sd-exporter)
 ✅ gke.gcr.io/fluent-bit:v1.5.7-gke.3 (Location: kube-system > fluentbit-gke-5z7pj > fluentbit-gke)
 ✅ gke.gcr.io/fluent-bit-gke-exporter:v0.17.1-gke.0 (Location: kube-system > fluentbit-gke-5z7pj > fluentbit-gke)
 ✅ gke.gcr.io/gke-metadata-server:gke_metadata_server_20220719.00_p0 (Location: kube-system > gke-metadata-server-4kmwb > gke-metadata-server)
 ✅ gke.gcr.io/gke-metrics-agent:1.8.3-gke.0 (Location: kube-system > gke-metrics-agent-jbr4j > gke-metrics-agent)
 ✅ gke.gcr.io/k8s-dns-dnsmasq-nanny:1.22.12-gke.0 (Location: kube-system > kube-dns-698cf6b7dc-fzp66 > sidecar)
 ✅ gke.gcr.io/k8s-dns-kube-dns:1.22.12-gke.0 (Location: kube-system > kube-dns-698cf6b7dc-fzp66 > sidecar)
 ✅ gke.gcr.io/prometheus-to-sd:v0.11.3-gke.0 (Location: kube-system > kube-dns-698cf6b7dc-fzp66 > sidecar)
 ✅ gke.gcr.io/k8s-dns-sidecar:1.22.12-gke.0 (Location: kube-system > kube-dns-698cf6b7dc-fzp66 > sidecar)
 ✅ gke.gcr.io/cluster-proportional-autoscaler-amd64:1.8.1-gke.0 (Location: kube-system > kube-dns-autoscaler-844c9d9448-btwpk > autoscaler)
 ✅ gke.gcr.io/kube-proxy-amd64:v1.21.14-gke.18800 (Location: kube-system > kube-proxy-gke-gke-k8sgcrio-test-default-pool-70892eb7-c9b6 > kube-proxy)
 ✅ gke.gcr.io/ingress-gce-404-server-with-metrics:v1.13.4 (Location: kube-system > l7-default-backend-7dc577646d-ltzjs > default-http-backend)
 ✅ eu.gcr.io/gke-release-staging/metrics-server-amd64:v0.4.5-gke.0 (Location: kube-system > metrics-server-v0.4.5-fb4c49dd6-r9jkb > metrics-server-nanny)
 ✅ asia.gcr.io/gke-release-staging/addon-resizer:1.8.13-gke.0 (Location: kube-system > metrics-server-v0.4.5-fb4c49dd6-r9jkb > metrics-server-nanny)
 ✅ gke.gcr.io/netd-init:v0.6.10-gke.0 (Location: kube-system > netd-jg72g > install-cni)
 ✅ gke.gcr.io/netd:v0.6.10-gke.0 (Location: kube-system > netd-jg72g > netd)
 ✅ gke.gcr.io/csi-node-driver-registrar:v2.1.0-gke.3 (Location: kube-system > pdcsi-node-9zxmh > gce-pd-driver)
 ✅ gke.gcr.io/gcp-compute-persistent-disk-csi-driver:v1.3.8-gke.0 (Location: kube-system > pdcsi-node-9zxmh > gce-pd-driver)

Images in red ❌ are being pulled from *outdated* Kubernetes community registries.
The others marked in green ✅ are good as they do not use the outdated registries.
Please copy these images to your own registry and change your manifest(s)
to point to the new location.

If you are unable to do so, as a short term fix please use `registry.k8s.io`
instead of `k8s.gcr.io` until you have your own registry.

This simple change on your part will help the Kubernetes community immensely as it
reduces the cost of us serving these container images.

Why you should do this as soon as possible? Read more in the following blog
posts by the Kubernetes community:
- https://kubernetes.io/blog/2022/11/28/registry-k8s-io-faster-cheaper-ga/
- https://kubernetes.io/blog/2023/02/06/k8s-gcr-io-freeze-announcement/

この例では、 k8s.gcr.io/prometheus-to-sd:v0.9.1 が実行されていることだけでなく、コンテナが cnrm-system Namespace にある cnrm-resource-stats-recorder-6dfc78996c-zb9vm Pod の recorder で呼び出されていることが確認できます。

Google Kubernetes Engine (GKE) への影響について

k8s.gcr.io の変更は、GKEにどのような影響を与えるでしょうか?
結論から言うと、2023/4/13現在で新規作成が可能なGKEクラスタの最小バージョン(v1.21.14以降)では、 kube-system で使用する標準イメージは全て gke.gcr.io というGKE固有のコンテナレジストリでホスティングされており、本件の影響を受けないようになっています。
(なお、この仕様は最初からだったのか、それとも、あるバージョンから変更されたのかは、筆者は調査しきれませんでした。)

ただし、ユーザーが追加で導入したマニフェストで、 k8s.gcr.io のコンテナイメージを使用していないかについて調査する必要があります。
調査方法は前述の「調査方法」で示した通りです。

なお、 記事執筆時点(2023/4/14)で調査した限りでは、限定公開GKEクラスタ(ノードが外部IPを持たない)、かつ、Cloud NAT未使用、かつ、サブネットの「限定公開Googleアクセス」が有効、となっているケースにおいて下記のような実行結果になりました。

$ kubectl run hello-world -ti --rm --image=registry.k8s.io/busybox:latest --restart=Never -- date
pod "hello-world" deleted
error: timed out waiting for the condition

$ kubectl run hello-world -ti --rm --image=k8s.gcr.io/busybox:latest --restart=Never -- date
Fri Apr 14 08:57:54 UTC 2023
pod "hello-world" deleted

実行結果から、以下のように観測できました。

  • registry.k8s.io は限定公開Googleアクセスによるプライベートアクセスは許可されていない
  • 現時点の k8s.gcr.io へのアクセスは registry.k8s.io にリダイレクトされず、限定公開GoogleアクセスによるプライベートアクセスでPull可能

ただし、この動作はGoogle Blogでの周知とは異なる動作であり、いつまで続くかはわかりません。
k8s.gcr.io からPullしている設定を検出した場合、できるだけ早くコンテナイメージのPull先を修正するべきでしょう。

GKE クラスタで Config Connector を使用してる場合

Config Connector を使用している場合、一部の Pod (cnrm-resource-stats-recorder Deployment から生成)が k8s.gcr.io/prometheus-to-sd を Pull してしまうようです。前述の通り、現時点ではまだ k8s.gcr.io のリダイレクト動作は発生していないため、動作不能になるような問題になっていません。
この動作は Regular チャンネルの最新バージョンである v1.25.7-gke.1000 でも確認できたため、今後の修正に期待です。
公開バグトラッカーにも投稿しましたので、興味のある方は、 +1 ボタンを押して頂けると助かります。

cnrm-resource-stats-recorder of Config Connector is using k8s.gcr.io container

まとめ

k8s.gcr.io 廃止の影響が、 GKE でどの程度影響するかについてまとめてみました。
既にKubernetesコミュニティやGoogle Blog、その他情報源で言及されている内容ではありますが、それらの情報を補完できれば幸いです。

Discussion