我有一个Google Kubernetes Engine集群,直到最近才开始从Google Container Registry桶中提取私有容器图像。我没有改变任何东西,但现在当我更新我的Kubernetes Deployments时,它无法启动新的pod,我得到以下事件:
Normal Pulling 14s kubelet, <node-id> pulling image "gcr.io/cloudsql-docker/gce-proxy:latest"
Normal Pulling 14s kubelet, <node-id> pulling image "gcr.io/<project-id>/backend:62d634e"
Warning Failed 14s kubelet, <node-id> Failed to pull image "gcr.io/<project-id>/backend:62d634e": rpc error: code = Unknown desc = unauthorized: authentication required
Warning Failed 14s kubelet, <node-id> Error: ErrImagePull
Normal Pulled 13s kubelet, <node-id> Successfully pulled image "gcr.io/cloudsql-docker/gce-proxy:latest"
Normal Created 13s kubelet, <node-id> Created container
Normal Started 13s kubelet, <node-id> Started container
Normal BackOff 11s (x2 over 12s) kubelet, <node-id> Back-off pulling image "gcr.io/<project-id>/backend:62d634e"
Warning Failed 11s (x2 over 12s) kubelet, <node-id> Error: ImagePullBackOff
我检查过以下的事情,这些事情似乎都是应该的:
storage-ro
权限我也尝试过禁用和重新启用container.googleapis.com和containerregistry.googleapis.com服务,但这没有帮助。
Container Registry的Google文档说明:
Kubernetes Engine集群自动配置为可以从同一项目中的Container Registry中提取私有映像。如果注册表和群集位于同一个Cloud项目中,则无需执行其他步骤来配置身份验证。
但事实似乎并非如此。
任何人都可以了解可能发生的事情吗?或者尝试其他步骤?
在我的例子中,问题是由最小规范文件生成的节点池缺少可以访问注册表的oauth2范围。添加
nodePools:
config:
oauthScopes:
- https://www.googleapis.com/auth/devstorage.read_only
- https://www.googleapis.com/auth/servicecontrol
- https://www.googleapis.com/auth/service.management.readonly
- https://www.googleapis.com/auth/trace.append
我的规格固定的东西。我认为这是重要的devstorage
范围,但我不确定,因为我只是从Web控制台生成的规范中复制粘贴整个范围列表。
好吧,这结果很棘手,但原因是:
我使用Terraform为GKE集群中的节点设置服务帐户,但是我没有使用email
资源的google_service_account
输出来指定服务帐户,而是使用了unique_id
输出。 Terraform和Google Cloud API都接受了这一点。
当Kubernetes(和其他东西)试图访问每个节点上的内部元数据API以获得它可以使用的令牌时,它正在接收Service account is invalid/disabled
的响应和403状态。
使用正确指定的服务帐户重新创建节点池可解决此问题。
当我创建一个带有terraform的集群时,我遇到了同样的问题。首先,我只在service_account
中指定了node_config
,因此节点池的OAuth范围太小。明确地写下service_account
和oauth_scope
,如下所示,节点能够从私人GCR存储库中提取图像。
resource "google_container_node_pool" "primary_preemptible_nodes" {
node_config {
service_account = "${google_service_account.gke_nodes.email}"
oauth_scopes = [
"storage-ro",
"logging-write",
"monitoring"
]
}
}