Google Cloud Build部署到GKE私有集群

时间:2018-08-21 08:42:05

标签: kubernetes google-kubernetes-engine google-cloud-build

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

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

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

4 个答案:

答案 0 :(得分:4)

更新答案 (02/22/2021)

不幸的是,虽然以下方法有效,但 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

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

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

- 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 密钥)

答案 1 :(得分:2)

当前当前无法将Cloud Build计算机添加到VPC。同样,Cloud Build不会宣布构建计算机的IP范围。因此,如果不立即在该VPC的GCE上创建“ ssh堡垒实例”或“代理实例”,您将无法做到这一点。

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

答案 2 :(得分: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.x.x.x。
  2. 我有一个名为 my-bastion 的堡垒计算实例。它只有私有IP,没有外部IP。私有 IP 位于 GKE 集群的 master authorized networks CIDR 内。因此,在 my-bastion 中,kubectl 对私有 GKE 主节点起作用。由于 my-bastion 没有外部 IP,我的家用笔记本电脑通过 IAP 连接到它。
  3. 我家中的笔记本电脑使用家庭互联网公共 IP 地址,无法轻松连接到上面的私有 GKE 主节点。

我的目标是在我的笔记本电脑上针对该私有 GKE 集群执行 kubectl。从网络架构的角度来看,我家用笔记本电脑的位置就像 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

答案 3 :(得分:0)

我们最终做了以下事情:

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

2)在专用集群内部安装Keel,并在云生成器/注册表项目中为其授予pub / sub编辑器权限

Keel将监视图像中的更改并根据您的设置自动部署它们。

这非常有效,因为现在我们可以推送散列图像的哈希更新,而无需添加虚拟机或执行任何类型的堡垒/ ssh主机。