不使用 gcloud 工具将 kubectl 的本地实例连接到 GKE 集群?

Connect local instance of kubectl to GKE cluster without using gcloud tool?

有谁知道如何在不使用本地 gcloud 工具的情况下将 kubectl 的本地实例连接到 Google Kubernetes Engine (GKE) 集群?

例如:

如果您通过此命令使用 gcloud 工具:

gcloud container clusters get-credentials NAME [--zone=ZONE, -z ZONE] [GCLOUD_WIDE_FLAG …]

您会在 ~/.kube/config 中找到这样的用户:

- name: gke_myproj_myzone
  user:
    auth-provider:
      config:
        access-token: TOKENSTRING
        cmd-args: config config-helper --format=json
        cmd-path: /google/google-cloud-sdk/bin/gcloud
        expiry: 2018-01-22 18:05:46
        expiry-key: '{.credential.token_expiry}'
        token-key: '{.credential.access_token}'
      name: gcp

如您所见,gcloud 工具提供的默认值需要 glcoud 工具作为 auth-provider 才能登录到您的群集。

现在,我正在寻找的是一种将 kubectl 连接到未安装 gcloud 的机器上的集群的方法。

实现此目的的最简单方法是将 ~/.kube/config 文件(从经过 gcloud 身份验证的实例)复制到本地实例(笔记本电脑)中的此目录 $HOME/.kube

但首先,并使用经过身份验证的实例,您必须通过 运行 执行以下命令来根据此 document 启用遗留集群:

gcloud config set container/use_client_certificate True
export CLOUDSDK_CONTAINER_USE_CLIENT_CERTIFICATE=True

然后执行get-credentials命令,复制文件。

gcloud container clusters get-credentials NAME [--zone=ZONE, -z ZONE] [GCLOUD_WIDE_FLAG …]

请注意,您可能必须 运行 get-credentials 命令,并在每次身份验证令牌(保存在配置文件中)过期时复制配置文件。

所以我创建了这个名为 gke-kubeconfig 的工具来执行此操作。我基本上对 gcloud 进行了逆向工程并做了同样的事情。它首先请求一个短期令牌,然后使用它来获取集群数据并创建 kube 配置。

您需要确保令牌在您使用配置文件时不会过期,它目前会在 1 小时后过期,所以通常这应该不是问题。

我还创建了 mie00/gke-kubeconfig 用于我的 CI 管道。

您可以通过用户帐户或服务帐户使用 kubectl

用户帐户被设计为供人类使用,因此这些工具明显 "limitation":如果您使用 GKE 集群,则假定用户已 gcloud 安装并登录有了它。

您可以改为使用专供软件使用的服务帐户。 Kubernetes 有一个专用的资源类型 ServiceAccount(不要将其与 GCP 服务帐户混淆!)。增加的好处 - 这是一个 k8s 功能,因此它不依赖于您使用的服务实现(GKE、AKS 等)。

方法:

第一次连接集群只需要gcloud工具。访问集群后,您可以创建一个新的 k8s ServiceAccount 并在 kubectl 配置文件中使用其令牌。

然而,服务帐户需要以细粒度的方式 assigned necessary roles(k8s RoleRoleBinding 资源)。

您的集群需要启用 RBAC 身份验证才能正常工作。

注意事项:

服务帐户令牌不会过期,因此应特别注意不要expose/compromise它们。旋转它们可能是个好主意。

简单(经典)示例:

这是如何完成上述操作的简化示例。它相当简单,因为它使用默认命名空间,只添加了几个角色,并且需要相当多的手动操作,但它可以帮助您开始自己的实现。

创建文件my-service-account.yaml:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-user
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-user-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-user-role-binding
subjects:
  - kind: ServiceAccount
    name: my-user
roleRef:
  kind: Role
  name: my-user-role
  apiGroup: rbac.authorization.k8s.io

和运行kubectl apply -f my-service-account.yaml创建资源。

创建服务帐户后,您可以 运行 kubectl get secrets 找到保存用户令牌的秘密(它的名称源自服务帐户名称),然后 运行 kubectl get secret <secret-name-here> -o yaml得到密文数据,在输出的data.token字段中找到一个token。该令牌是 base64 编码的,因此您需要先对其进行解码,然后才能在 kubectl 配置文件中使用(为此,您可以在 Linux 中使用 base64 -d)。最后,kubectl 配置文件的相关部分可能如下所示:

apiVersion: v1
clusters:
  ...
contexts:
  ...
users:
- name: my-user
  user:
    token: <token-value-here>

现在您可以将 kubectl 上下文切换到您为该用户创建的上下文,并且 运行:

kubectl get pods

新创建的用户只能执行上述操作,几乎不能执行其他操作,因为这是在关联角色中配置的。您可以在 Kubernetes 文档中找到有关 RBAC 和角色配置的更多信息:Using RBAC Authorization.