kubernetes Google云构建部署到GKE私有集群

swvgeqrz  于 2023-03-12  发布在  Kubernetes
关注(0)|答案(8)|浏览(131)

我正在运行一个带有“私有集群”选项的Google Kubernetes引擎。我还定义了“授权主网络”,以便能够远程访问环境--这工作得很好。现在我想使用Google Cloud Build设置某种CI/CD管道--在成功构建一个新的Docker映像后,这个新映像应该会自动部署到GKE。当我第一次启动新管道时,部署到GKE失败-错误消息如下所示:“无法连接到服务器:拨打传输控制协议xxx. xxx.xxx.xxx:443:i/o timeout”。由于我怀疑“authorized master networks”选项是连接超时的根本原因,我将www.example.com添加0.0.0.0/0到允许的网络中,并再次启动云构建作业-这一次一切顺利,在创建Docker映像后,它被部署到GKE。
唯一的问题是,我真的不想让整个互联网都能够访问我的Kubernetes主机-这是一个坏主意,不是吗?
是否有更优雅的解决方案,通过使用允许的主网络来缩小访问范围,并能够通过云构建进行部署?

yvgpqqbh

yvgpqqbh1#

目前无法将云构建计算机添加到VPC。类似地,云构建不会公布构建计算机的IP范围。因此,如果不在该VPC内的GCE上创建“ssh bastion示例”或“代理示例”,您今天就无法执行此操作。

我怀疑这种情况很快就会改变。GCB在GKE私有集群之前就存在了,私有集群仍然是一个测试版特性。

ecfsfe2w

ecfsfe2w2#

我们最终完成了以下操作:
1)从cloudbuild.yaml中删除部署步骤
2)在私有集群中安装Keel,并在云构建器/注册表项目中给予它发布/订阅编辑器权限
Keel将监控图像中的变化,并根据您的设置自动部署它们。
这已经工作得很好,因为现在我们得到推sha散列图像更新,而不添加虚拟机或做任何类型的堡垒/ssh主机。

pes8fvy9

pes8fvy93#

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

不幸的是,虽然下面的方法工作,IAP隧道遭受速率限制,它似乎.如果有很多资源通过kubectl部署,然后隧道超时一段时间后.我不得不使用另一个技巧,这是动态白名单云构建IP地址通过Terraform,然后直接申请,这每次工作.

原始答案

还可以在云构建步骤中创建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

此步骤在cloudbuild网络中启动一个名为kubectl-proxy的 * 后台 * Docker容器,该容器由所有其他云构建步骤使用。Docker容器使用云构建服务帐户身份建立一个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密钥
hwamh0ep

hwamh0ep4#

我得到了cloudbuild与我的私人GKE集群以下谷歌文档:https://cloud.google.com/architecture/accessing-private-gke-clusters-with-cloud-build-private-pools
这允许我使用cloudbuild和terraform来管理一个GKE集群,并启用对控制平面的授权网络访问,我考虑过维护一个荒谬的白名单,但这最终会使使用授权网络访问控制的目的落空。
我注意到cloudbuild私有池通常比非私有池慢,这是由于私有池的无服务器特性,到目前为止我还没有遇到过其他人提到的速率限制。

yfjy0ee7

yfjy0ee75#

我们的解决方案是在CI/CD中添加步骤--将云构建的IP列入白名单,* 通过授权主网络 *。
注意:需要云生成服务帐户的其他权限

Kubernetes Engine Cluster Admin

在cloudbuild.yaml上,在部署之前添加白名单步骤。
此步骤获取云构建的IP,然后更新容器群集设置;

# Authorize Cloud Build to Access the Private Cluster (Enable Control Plane Authorized Networks)
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  id: 'Authorize Cloud Build'
  entrypoint: 'bash'
  args:
    - -c
    - |
      apt-get install dnsutils -y &&
      cloudbuild_external_ip=$(dig @resolver4.opendns.com myip.opendns.com +short) &&
      gcloud container clusters update my-private-cluster --zone=$_ZONE --enable-master-authorized-networks --master-authorized-networks $cloudbuild_external_ip/32 &&
      echo $cloudbuild_external_ip

由于云构建已列入白名单,因此部署将继续进行,不会出现i/o超时错误。

这消除了设置VPN /专用工作池的复杂性。

部署后禁用控制平面授权网络。

# Disable Control Plane Authorized Networks after Deployment
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  id: 'Disable Authorized Networks'
  entrypoint: 'gcloud'
  args:
    - 'container'
    - 'clusters'
    - 'update'
    - 'my-private-cluster'
    - '--zone=$_ZONE'
    - '--no-enable-master-authorized-networks'

即使在跨项目/跨环境部署中,这种方法也能很好地工作。

oiopk7p5

oiopk7p56#

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

此外,即使我们不将其用于云构建,我的方法也提供了一种从我的笔记本电脑到K8s私有主节点的隧道方式,因此,我可以在笔记本电脑上编辑K8syaml文件(例如,使用VS代码),并立即从我的笔记本电脑执行kubectl,而不是必须将代码运送到Bastion主机并在Bastion主机内执行X1 M1 N1 X。我发现这对开发时间生产率有很大的推动作用。

原答复

================
我想我可能会对上面@dinvlad提供的伟大解决方案有所改进。
我认为这个解决方案可以简化而不需要安装HTTP代理服务器。仍然需要一个堡垒主机。
我提供以下概念验证(不带HTTP代理服务器)。此PoC说明了底层网络机制,但不涉及 Google Cloud Build(GCB)。(将来有时间时,我会在Google Cloud Build上测试完整的实现。)
假设:
1.我有一个GKE集群,它的主节点是私有的,例如IP地址是10.x.x.x。
1.我有一个名为my-bastion的bastion计算示例。它只有专用IP而没有外部IP。专用IP在GKE群集的master authorized networks CIDR内。因此,从my-bastion内,kubectl针对专用GKE主节点工作。因为my-bastion没有外部IP,所以我的家用笔记本电脑通过IAP连接到它。
1.我的笔记本电脑在家里,我的家庭互联网公共IP地址,不容易有连接到私人GKE主节点以上。
我的目标是在我的笔记本电脑上对那个私有GKE集群执行kubectl,从网络架构的Angular 来看,我的家用笔记本电脑的位置就像 Google Cloud Build 服务器。

理论:知道gcloud compute ssh(以及关联的IAP)是SSH的 Package 器,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
bejyjqdl

bejyjqdl7#

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

c6ubokkw

c6ubokkw8#

我的解决方案可能不是最漂亮的,但它有点直截了当。我暂时白名单的CloudBuild的公共IP运行kubectl更新部署。
这是我的cloudbuild.yaml的样子。首先,我们运行一个容器来将公共IP列入白名单:

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: bash
  args:
  - '-c'
  - |
    apt update \
    && apt install -y jq \
    && cd ~ \
    && gcloud container clusters describe CLUSTERNAME --zone=CLUSTERZONE --project GCPPROJECT --format="json(masterAuthorizedNetworksConfig.cidrBlocks)" > ~/manc.json \
    && (jq ".update.desiredMasterAuthorizedNetworksConfig = .masterAuthorizedNetworksConfig | del(.masterAuthorizedNetworksConfig) | .update.desiredMasterAuthorizedNetworksConfig.enabled = \"true\" | .name = \"projects/GCPPROJECT/locations/CLUSTERZONE/clusters/CLUSTERNAME\" | .update.desiredMasterAuthorizedNetworksConfig.cidrBlocks += [{\"cidrBlock\":\"`curl -s ifconfig.me`/32\",\"displayName\":\"CloudBuild tmp\"}]" ./manc.json) > ~/manc2.json \
    && curl -X PUT -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type:application/json" -H "Accept: application/json" --data "$(cat manc2.json)" "https://container.googleapis.com/v1beta1/{projects/GCPPROJECT/locations/CLUSTERZONE/clusters/CLUSTERNAME}"

我们现在可以运行任何您想运行的kubectl命令。
此容器将再次从autoizedNetworks中删除IP:

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: bash
  args:
  - '-c'
  - |
    apt update \
    && apt install -y jq \
    && cd ~ \
    && gcloud container clusters describe CLUSTERNAME --zone=CLUSTERZONE --project GCPPROJECT --format="json(masterAuthorizedNetworksConfig.cidrBlocks)" > ~/manc.json \
    && (jq ".update.desiredMasterAuthorizedNetworksConfig = .masterAuthorizedNetworksConfig | del(.masterAuthorizedNetworksConfig) | .update.desiredMasterAuthorizedNetworksConfig.enabled = \"true\" | .name = \"projects/GCPPROJECT/locations/CLUSTERZONE/clusters/CLUSTERNAME\" | del(.update.desiredMasterAuthorizedNetworksConfig.cidrBlocks[] | select(.displayName==\"CloudBuild tmp\"))" ./manc.json) > ~/manc2.json \
    && curl -X PUT -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type:application/json" -H "Accept: application/json" --data "$(cat manc2.json)" "https://container.googleapis.com/v1beta1/{projects/GCPPROJECT/locations/CLUSTERZONE/clusters/CLUSTERNAME}"

请填写群集名称、GCPPROJECT、群集区域。请随意改进=)

相关问题