23

我正在运行带有“私有集群”选项的 Google Kubernetes Engine。我还定义了“授权主网络”以能够远程访问环境 - 这很好用。现在我想使用 Google Cloud Build 设置某种 CI/CD 管道 - 在成功构建新的 docker 镜像后,这个新镜像应该会自动部署到 GKE。当我第一次启动新管道时,部署到 GKE 失败 - 错误消息类似于:“无法连接到服务器:dial tcp xxx.xxx.xxx.xxx:443: i/o timeout”。由于我怀疑“授权主网络”选项是连接超时的根本原因,因此我添加了 0.0.0. 0/0 到允许的网络并再次启动 Cloud Build 作业 - 这次一切顺利,在创建 docker 映像后将其部署到 GKE。好的。

剩下的唯一问题是我真的不想让整个互联网都能够访问我的 Kubernetes 主服务器——这是个坏主意,不是吗?

是否有更优雅的解决方案可以通过使用允许的主网络并能够通过云构建进行部署来缩小访问范围?

4

6 回答 6

10

目前无法将 Cloud Build 机器添加到 VPC。同样,Cloud Build 不会公布构建机器的 IP 范围。因此,如果不在该 VPC 内的 GCE 上创建“ssh 堡垒实例”或“代理实例”,您今天就无法做到这一点。

我怀疑这很快就会改变。GCB 在 GKE 私有集群之前就已经存在,并且私有集群仍然是一个 beta 特性。

于 2018-08-23T04:30:48.867 回答
5

我们最终做了以下事情:

1) 从 cloudbuild.yaml 中删除部署步骤

2) 在私有集群中安装 Keel 并在 cloud builder/registry 项目中赋予它 pub/sub 编辑权限

Keel 将监控图像的变化并根据您的设置自动部署它们。

这已经很好了,因为现在我们可以推送 sha 散列图像更新,而无需添加 vm 或执行任何类型的 bastion/ssh 主机。

于 2019-08-17T06:06:44.487 回答
4

更新答案(2021 年 2 月 22 日)

不幸的是,虽然下面的方法有效,但 IAP 隧道似乎受到速率限制。如果通过 kubectl 部署的资源很多,那么隧道会在一段时间后超时。我不得不使用另一个技巧,即通过 Terraform 将 Cloud Build IP 地址动态列入白名单,然后直接申请,每次都有效。

原始答案

也可以在 Cloud Build 步骤中创建 IAP 隧道:

- id: kubectl-proxy
  name: gcr.io/cloud-builders/docker
  entrypoint: sh
  args:
  - -c
  - docker run -d --net cloudbuild --name kubectl-proxy
      gcr.io/cloud-builders/gcloud compute start-iap-tunnel
      bastion-instance 8080 --local-host-port 0.0.0.0:8080 --zone us-east1-b &&
    sleep 5

此步骤启动一个名为network的后台Docker 容器kubectl-proxy,所有其他 Cloud Build 步骤都将使用该容器。Docker 容器使用 Cloud Build 服务帐户身份建立IAP 隧道。隧道连接到 GCE 实例,其中预装了 SOCKS 或 HTTPS 代理(留给读者的练习)。cloudbuild

在后续步骤中,您可以简单地访问集群

- id: setup-k8s
  name: gcr.io/cloud-builders/kubectl
  entrypoint: sh
  args:
  - -c
  - HTTPS_PROXY=socks5://kubectl-proxy:8080 kubectl apply -f config.yml

与上面建议的其他方法相比,这种方法的主要优点是:

  • 无需拥有具有公共IP 的“堡垒”主机 -kubectl-proxy主机可以完全私有,从而维护集群的隐私
  • 隧道连接依赖于 Cloud Build 可用的默认 Google 凭据,因此无需存储/传递任何长期凭据,例如 SSH 密钥
于 2021-01-16T07:32:50.697 回答
1

现在可以创建一个连接到您的私有 VPC 并且可以从 Cloud Build 访问的 VM 池。

快速开始

于 2021-08-30T08:12:58.100 回答
1

更新:我想这不适用于生产强度,原因与上述@dinvlad 的更新相同,即 IAP 中的速率限制。我将把我原来的帖子留在这里,因为它确实解决了网络连接问题,并说明了底层网络机制。

此外,即使我们不将它用于 Cloud Build,我的方法也提供了一种从我的笔记本电脑隧道到 K8s 私有主节点的方法。因此,我可以在我的笔记本电脑上编辑 K8s yaml 文件(例如,使用 VS Code),并立即kubectl从我的笔记本电脑上执行,而不必将代码发送到堡垒主机并kubectl在堡垒主机内执行。我发现这大大提高了开发时间的生产力。

原始答案

=================

我想我可能会对上面@dinvlad 提供的出色解决方案有所改进。

我认为无需安装 HTTP 代理服务器即可简化解决方案。仍然需要堡垒主机。

我提供以下概念证明(没有 HTTP 代理服务器)。这个 PoC 说明了底层网络机制,而不涉及Google Cloud Build (GCB) 的干扰。(当我将来有时间时,我会在 Google Cloud Build 上测试完整的实现。)

认为:

  1. 我有一个 GKE 集群,其主节点是私有的,例如,IP 地址为 10.xxx
  2. 我有一个名为my-bastion. 它只有私有IP,没有外部IP。私有 IP 在master authorized networksGKE 集群的 CIDR 内。因此,从内部my-bastionkubectl对​​私有 GKE 主节点起作用。因为my-bastion没有外网IP,所以我家的笔记本是通过IAP连接的。
  3. 我家中的笔记本电脑使用我的家庭互联网公共 IP 地址,无法轻松连接到上面的私有 GKE 主节点。

我的目标是kubectl在我的笔记本电脑上针对该私有 GKE 集群执行。从网络架构的角度来看,我家用笔记本电脑的位置就像Google Cloud Build服务器。

理论:知道gcloud compute ssh(以及相关的 IAP)是 SSH 的包装器,SSH动态端口转发应该为我们实现该目标。

实践:

## On laptop:
LAPTOP~$ kubectl get ns
^C            <<<=== Without setting anything up, this hangs (no connectivity to GKE).

## Set up SSH Dynamic Port Forwarding (SOCKS proxy) from laptop's port 8443 to my-bastion.
LAPTOP~$ gcloud compute ssh my-bastion --ssh-flag="-ND 8443" --tunnel-through-iap

在我笔记本电脑的另一个终端:

## Without using the SOCKS proxy, this returns my laptop's home public IP:
LAPTOP~$ curl https://checkip.amazonaws.com
199.xxx.xxx.xxx

## Using the proxy, the same curl command above now returns a different IP address, 
## i.e., the IP of my-bastion. 
## Note: Although my-bastion doesn't have an external IP, I have a GCP Cloud NAT 
## for its subnet (for purpose unrelated to GKE or tunneling).
## Anyway, this NAT is handy as a demonstration for our curl command here.
LAPTOP~$ HTTPS_PROXY=socks5://127.0.0.1:8443 curl -v --insecure https://checkip.amazonaws.com
* Uses proxy env variable HTTPS_PROXY == 'socks5://127.0.0.1:8443'  <<<=== Confirming it's using the proxy
...
* SOCKS5 communication to checkip.amazonaws.com:443
...
* TLSv1.2 (IN), TLS handshake, Finished (20):             <<<==== successful SSL handshake
...
> GET / HTTP/1.1
> Host: checkip.amazonaws.com
> User-Agent: curl/7.68.0
> Accept: */*
...
< Connection: keep-alive
<
34.xxx.xxx.xxx            <<<=== Returns the GCP Cloud NAT'ed IP address for my-bastion 

最后,关键时刻kubectl

## On laptop:
LAPTOP~$ HTTPS_PROXY=socks5://127.0.0.1:8443 kubectl --insecure-skip-tls-verify=true get ns
NAME              STATUS   AGE
default           Active   3d10h
kube-system       Active   3d10h
于 2021-02-22T04:18:45.587 回答
1

遵循此 google 文档,我让 cloudbuild 与我的私有 GKE 集群一起工作: https ://cloud.google.com/architecture/accessing-private-gke-clusters-with-cloud-build-private-pools

这允许我使用 cloudbuild 和 terraform 来管理 GKE 集群,并启用对控制平面的授权网络访问。我考虑尝试维护一个荒谬的白名单,但这最终会破坏使用授权网络访问控制的目的。

我会注意到,cloudbuild 私有池通常比非私有池慢。这是由于私有池的无服务器特性。到目前为止,我还没有经历过其他人提到的速率限制。

于 2021-10-13T03:35:13.353 回答