【问题标题】:Authenticating to GKE master in Python在 Python 中向 GKE master 进行身份验证
【发布时间】:2019-01-28 21:16:23
【问题描述】:

我需要使用 Kubernetes Python client 和 Google Cloud python 客户端对在 GKE 中配置的 Kubernetes 集群进行身份验证。出于以下几个原因,我宁愿不向gcloud 支付费用:

  • 当我拥有原生 Google Cloud 库时,在 Python 脚本中依赖系统 shell gcloud 是不优雅的
  • 要求系统有gcloud
  • 我必须将用户切换到相关的 ServiceAccount 并切换回来
  • 它会产生启动/加入另一个进程的成本

因此,gcloud container clusters get-credentials(委托给gcloud config config-helper)的工作流程不足以让我获得所需的 API 密钥。如何使用 Google Cloud Python API 获得等效输出?

这是我目前所拥有的:

import kubernetes.client
import googleapiclient.discovery
import base64

# get the cluster object from GKE
gke = googleapiclient.discovery.build('container', 'v1', credentials=config['credentials'])
name = f'projects/{config["project_id"]}/locations/{config["location"]}/{parent}/clusters/{config["name"]}'
gke_clusters = gke.projects().locations().clusters()
gke_cluster = gke_clusters.get(name=name).execute()

# set up Kubernetes Config
kube_config = kubernetes.client.Configuration()
kube_config.host = 'https://{0}/'.format(gke_cluster['endpoint'])
kube_config.verify_ssl = True
#kube_config.api_key['authenticate'] = "don't know what goes here"

# regretably, the Kubernetes client requires `ssl_ca_cert` to be a path, not the literal cert, so I will write it here.
kube_config.ssl_ca_cert = 'ssl_ca_cert'
with open(kube_config.ssl_ca_cert, 'wb') as f:
    f.write(base64.decodestring(gke_cluster['masterAuth']['clusterCaCertificate'].encode()))

# use Kubernetes client to do something
kube_client = kubernetes.client.ApiClient(configuration=kube_config)
kube_v1 = kubernetes.client.CoreV1Api(kube_client)
kube_v1.list_pod_for_all_namespaces(watch=False)

【问题讨论】:

    标签: kubernetes google-cloud-platform google-oauth google-kubernetes-engine


    【解决方案1】:

    以下是从 googleapiclient 中提取访问令牌的解决方案,而不是手动复制粘贴内容。

    import googleapiclient.discovery
    from tempfile import NamedTemporaryFile
    import kubernetes
    import base64
    
    def token(*scopes):
        credentials = googleapiclient._auth.default_credentials()
        scopes = [f'https://www.googleapis.com/auth/{s}' for s in scopes]
        scoped = googleapiclient._auth.with_scopes(credentials, scopes)
        googleapiclient._auth.refresh_credentials(scoped)
        return scoped.token
    
    def kubernetes_api(cluster):
        config = kubernetes.client.Configuration()
        config.host = f'https://{cluster["endpoint"]}'
    
        config.api_key_prefix['authorization'] = 'Bearer'
        config.api_key['authorization'] = token('cloud-platform')
    
        with NamedTemporaryFile(delete=False) as cert:
            cert.write(base64.decodebytes(cluster['masterAuth']['clusterCaCertificate'].encode()))
            config.ssl_ca_cert = cert.name
    
        client = kubernetes.client.ApiClient(configuration=config)
        api = kubernetes.client.CoreV1Api(client)
    
        return api
    
    def run(cluster):
        """You'll need to give whichever account `googleapiclient` is using the 
        'Kubernetes Engine Developer' role so that it can access the Kubernetes API.
    
        `cluster` should be the dict you get back from `projects.zones.clusters.get`
        and the like"""
    
        api = kubernetes_api(cluster)
        print(api.list_pod_for_all_namespaces())
    

    弄清楚这一点花费的时间比我愿意承认的要长。 @Ivan 的帖子很有帮助。

    【讨论】:

    • google 令牌是否意味着是有效的 kubernetes 令牌?我的意思是如果它工作得很好......但这是否记录在某个地方?以防它在未来被“弃用”。
    • 已经六个月了,但我想我是通过检查 gcloud 的代码得出的。现在搜索,我在 GKE 的不记名令牌身份验证上找不到任何内容,所以我会说“未记录”。
    【解决方案2】:

    要对 GKE 集群进行身份验证,您可以使用 service account 连接到项目,然后使用 GKE 生成的密钥对集群进行身份验证。步骤如下:

    1. 在 GCP 中创建一个服务帐户。转到 IAM > 服务帐户 > 创建服务帐户。给它一个项目所有者角色。创建 SA 后,创建一个密钥并将其下载为 json。
    2. 将 key.json 上传到您有 .py 脚本的文件夹中
    3. 获取 API_TOKEN。这是您的主要问题,您可以通过读取令牌文件来获得它:
      • 首次运行kubectl get secrets
      • 您将获得“default-token-xxxxx”
      • 运行 kubectl describe secrets default-token-xxxxx(将 xxxxx 替换为您的令牌名称)。
      • 显示的令牌参数是您的“API-KEY”。将其复制到您的脚本中。
    4. 创建脚本。它与您的有点不同,原因如下:您需要先使用服务帐户对项目进行身份验证,然后需要传递 api_token,而且在向 GKE master 进行身份验证时还需要获取 SSL 证书。
    import base64, pprint
    import kubernetes.client
    from google.oauth2 import service_account
    
    credentials = service_account.Credentials.from_service_account_file("key.json")
    gke = googleapiclient.discovery.build('container', 'v1', credentials=credentials)
    name = 'projects/your_project/locations/your_zone/clusters/your_gke_cluster'
    gke_clusters = gke.projects().locations().clusters()
    gke_cluster = gke_clusters.get(name=name).execute()
    
    kube_config = kubernetes.client.Configuration()
    kube_config.host = 'https://{}'.format(gke_cluster['endpoint'])
    kube_config.verify_ssl = True
    
    kube_config.api_key['authorization'] = 'your_api_token'
    kube_config.api_key_prefix['authorization'] = 'Bearer'
    
    kube_config.ssl_ca_cert = 'ssl_ca_cert'
    
    with open(kube_config.ssl_ca_cert, 'wb') as f:
        f.write(base64.decodestring(gke_cluster['masterAuth']['clusterCaCertificate'].encode()))
    
    kube_client = kubernetes.client.ApiClient(configuration=kube_config)
    kube_v1 = kubernetes.client.CoreV1Api(kube_client)
    pprint.pprint(kube_v1.list_pod_for_all_namespaces())
    

    具体字段:

    • your_project - 来自 GCP
    • 您的 _zone - 创建 gke 集群的位置
    • 您的 _gke_cluster - GKE 集群名称
    • your_api_key - 您在第 3 步中获得的信息。

    这应该足以让您对 GKE 集群进行身份验证。

    【讨论】:

    • 请注意,我必须将 ClusterRoleBinding 应用到默认用户才能实际使用 API。
    猜你喜欢
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2020-02-28
    • 2015-09-23
    相关资源
    最近更新 更多