kubernetes.client.rest.ApiException:(401)原因:未经授权;创建/删除 GKE pod 的 IAM

Posted

技术标签:

【中文标题】kubernetes.client.rest.ApiException:(401)原因:未经授权;创建/删除 GKE pod 的 IAM【英文标题】:kubernetes.client.rest.ApiException: (401) Reason: Unauthorized; What IAM to create/delete GKE pods 【发布时间】:2020-11-12 13:59:53 【问题描述】:

我正在尝试读取 GKE 集群中的活动 pod 列表。我还希望能够使用 python 客户端以编程方式创建和/或删除 pod。我应该授予我的服务帐户哪些 IAM 访问权限来完成此操作?由于我一直在尝试几乎所有方法来使其正常工作,因此该服务帐户目前拥有 Kubernetes Engine AdminKubernetes Engine Cluster AdminKubernetes Engine Developer 访问权限。

这里有一些示例代码,它尝试读取我集群 IP 的“默认”命名空间中的 pod

import kubernetes
from oauth2client.client import GoogleCredentials


def get_access_config(cluster_ip):
    # access the k8s cluster, https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/
    credentials = GoogleCredentials.get_application_default()
    access_token = credentials.get_access_token()

    # Create a configuration object
    access_configuration = kubernetes.client.Configuration()

    # Specify the access configuration to access k8s cluster
    access_configuration.host = f"https://cluster_ip:443"
    access_configuration.verify_ssl = False
    access_configuration.api_key = "authorization": "Bearer " + access_token.access_token
    return access_configuration


def get_pod_list(access_configuration):
    v1 = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(access_configuration))
    print("Listing pods with their IPs:")
    ret = v1.list_namespaced_pod(namespace='default')


cluster_ip = '0.0.0.0'  # replace with your cluster_ip
access_configuration = get_access_config(cluster_ip)
get_pod_list(access_configuration)

每当我运行 get_pod_list 函数时,我都会得到以下 Traceback:

Traceback (most recent call last):   File "<input>", line 3, in
<module>   File
"/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/api/core_v1_api.py",
line 12803, in list_namespaced_pod
    (data) = self.list_namespaced_pod_with_http_info(namespace, **kwargs)  # noqa: E501   File "/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/api/core_v1_api.py",
line 12905, in list_namespaced_pod_with_http_info
    collection_formats=collection_formats)   File "/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/api_client.py",
line 345, in call_api
    _preload_content, _request_timeout)   File "/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/api_client.py",
line 176, in __call_api
    _request_timeout=_request_timeout)   File "/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/api_client.py",
line 366, in request
    headers=headers)   File "/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/rest.py",
line 241, in GET
    query_params=query_params)   File "/Users/<user>/miniconda3/envs/<my_env>/lib/python3.7/site-packages/kubernetes/client/rest.py",
line 231, in request
    raise ApiException(http_resp=r) kubernetes.client.rest.ApiException: (401) Reason: Unauthorized HTTP
response headers: HTTPHeaderDict('Audit-Id':
'22bd2789-30d0-4be8-a211-277a39396de7', 'Content-Type':
'application/json', 'Date': 'Wed, 22 Jul 2020 22:12:17 GMT',
'Content-Length': '129') HTTP response body:
"kind":"Status","apiVersion":"v1","metadata":,"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401 ```

如果我的 IAM 访问权限不是问题,是什么导致了这个 401“未经授权”错误,我应该如何解决它?

编辑/更新

即使按照当前答案中的说明进行操作,我仍然遇到同样的错误。这些说明似乎是必要的,但不足以解决问题。

我认为我的 GOOGLE_APPLICATION_CREDENTIALS 路径变量可能指向错误的 JSON 文件,但我检查了下面的代码,它指向了正确的文件:

import os
os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')

检查后,我尝试了https://github.com/kubernetes-client/python 的代码的更简单版本:

from kubernetes import client, config

# Configs can be set in Configuration class directly or using helper utility
config.load_kube_config()

v1 = client.CoreV1Api()
print("Listing pods with their IPs:")
ret = v1.list_namespaced_pod(namespace='default')

那个版本有效!?!那么,将api_client 加载到kubernetes.client.CoreV1ApiGoogleCredentials 版本有什么问题/区别? GoogleCredentials.get_application_default() 行是否以某种方式寻找并找到错误的凭据?如果是这样,我怎样才能将它指向正确的凭据?

【问题讨论】:

【参考方案1】:

您没有提供步骤❓,所以这对我有用,我的服务帐户具有管理员 GKE 访问权限:

创建服务帐户凭据:

gcloud iam service-accounts keys create cred.json --iam-account  mytestserviceaccount@project.iam.gserviceaccount.com
created key [xxxxxxxxxx] of type [json] as [cred.json] for [mytestserviceaccount@project.iam.gserviceaccount.com]``

激活服务帐号:

gcloud auth activate-service-account mytestserviceaccount@project.iam.gserviceaccount.com --key-file=cred.json

您可以通过以下方式检查:

gcloud auth list
                       Credentialed Accounts
ACTIVE  ACCOUNT
*       mytestserviceaccount@dproject.iam.gserviceaccount.com
        name@sample.com

然后:

gcloud container clusters get-credentials gke-cluster-name --zone us-central1-a --project project

确保您允许您的用户管理员访问您的服务帐户:

此外,该帐户具有 Kubernetes 管理员角色:

测试的好方法:

kubectl get pods 应该可以工作。

我复制了上面的代码,它适用于我的一个 GKE 集群。

✌️

【讨论】:

我按照说明进行操作,并且能够让您提供的所有测试正常工作,但我仍然遇到同样的错误。我不确定如何让我的用户成为现有服务帐户的管理员。我也没有在 IAM 中看到 Admin GKE 访问角色;你能说得更清楚些吗? 好的,添加了一张图片。 对这个问题的新编辑/更新有什么想法吗? 完全删除GOOGLE_APPLICATION_CREDENTIALS 变量怎么样。我没有任何适合我的地方。

以上是关于kubernetes.client.rest.ApiException:(401)原因:未经授权;创建/删除 GKE pod 的 IAM的主要内容,如果未能解决你的问题,请参考以下文章