默认情况下,集群可以通过其专用端点访问控制器,并且已获授权的网络可以在 VPC 中进行定义。
但是,如需从本地或其他 VPC 网络访问控制器,需要执行额外步骤。这是因为托管控制器的 VPC 网络由 Google 拥有,无法从通过其他 VPC 网络对等互连连接、Cloud VPN 或 Cloud Interconnect 连接的资源进行访问。
如需从本地或从通过 Cloud VPN 或 Cloud Interconnect 连接的其他 VPC 网络访问控制器,请从您的 VPC 网络到 Google 拥有的 VPC 网络之间启用路由导出。
如需允许从其他 VPC 网络或从通过其他 VPC 网络对等互连(例如采用中心辐射型设计)连接的本地访问控制器,请创建在已获授权的 IP 地址空间中托管的代理,这是因为 VPC 网络对等互连不具有传递性。
本教程介绍了如何在您的 GKE 专用集群中配置代理。
目标
- 创建没有外部访问权限的 GKE 专用集群。
- 创建并部署 Docker 映像以运行代理。
- 创建 Kubernetes 服务以访问代理。
- 测试对代理的访问权限。
费用
本教程使用 Google Cloud Platform 的可计费组件,包括:您可使用价格计算器根据您的预计用量来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine and Google Kubernetes Engine APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine and Google Kubernetes Engine APIs.
设置环境
在本教程中,您将使用 Cloud Shell 输入命令。Cloud Shell 让您能够使用 Google Cloud 控制台中的命令行,并包含在 Google Cloud 中进行开发所需的 Google Cloud CLI 和其他工具。Cloud Shell 显示为 Google Cloud 控制台底部的一个窗口。初始化可能需要几分钟,但窗口会立即显示。
为了使用 Cloud Shell 设置您的环境,请执行以下操作:
在 Google Cloud Console 中,打开 Cloud Shell。
确保正在使用您创建或选择的项目。将
[YOUR_PROJECT_ID]
替换为您的 Google Cloud 项目。gcloud config set project [YOUR_PROJECT_ID] export PROJECT_ID=`gcloud config list --format="value(core.project)"`
设置默认计算区域。在本教程中,计算区域为
us-central1-c
。如果要部署到生产环境,请部署到您选择的区域。gcloud config set compute/region us-central1 gcloud config set compute/zone us-central1-c export REGION=us-central1 export ZONE=us-central1-c
创建 VPC 网络和客户端虚拟机
创建用于托管资源的 VPC 网络和子网。
创建 VPC 网络:
gcloud compute networks create k8s-proxy --subnet-mode=custom
在新创建的 VPC 网络中创建自定义子网:
gcloud compute networks subnets create subnet-cluster \ --network=k8s-proxy --range=10.50.0.0/16
创建将用于在 Kubernetes 集群中部署资源的客户端虚拟机:
gcloud compute instances create --subnet=subnet-cluster \ --scopes cloud-platform proxy-temp
将新创建的实例的内部 IP 地址保存在环境变量中:
export CLIENT_IP=`gcloud compute instances describe proxy-temp \ --format="value(networkInterfaces[0].networkIP)"`
创建防火墙规则以允许通过 SSH 访问 VPC 网络:
gcloud compute firewall-rules create k8s-proxy-ssh --network k8s-proxy \ --allow tcp:22
创建专用集群
现在创建一个用于本教程的专用集群。
如果您已经拥有要使用的集群,则可以跳过创建集群的步骤,但必须在客户端计算机上配置一些初始访问形式。
在 Cloud Shell 中,创建一个集群:
gcloud container clusters create frobnitz \ --master-ipv4-cidr=172.16.0.64/28 \ --network k8s-proxy \ --subnetwork=subnet-cluster \ --enable-ip-alias \ --enable-private-nodes \ --enable-private-endpoint \ --master-authorized-networks $CLIENT_IP/32 \ --enable-master-authorized-networks
该命令会创建一个名为
frobnitz
的 GKE 专用集群,并将master-authorized-networks
设置为仅允许客户端机器访问。
创建 Docker 映像
按照以下步骤构建一个名为 k8s-api-proxy,
的 Kubernetes API 代理映像,该映像充当 Kubernetes API 服务器的转发代理。
在 Cloud Shell 中,创建一个目录并切换到该目录:
mkdir k8s-api-proxy && cd k8s-api-proxy
创建
Dockerfile
。以下配置会在 Alpine 中创建容器,它是一个具有 Privoxy 代理的轻量级分发容器。Dockerfile
还会安装curl
和jq
以进行容器初始化,添加必要的配置文件,在内部向 GKE 公开端口 8118,并添加启动脚本。FROM alpine
RUN apk add -U curl privoxy jq && \ mv /etc/privoxy/templates /etc/privoxy-templates && \ rm -rf /var/cache/apk/* /etc/privoxy/* && \ mv /etc/privoxy-templates /etc/privoxy/templates ADD --chown=privoxy:privoxy config \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-only.action \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-rewrite-internal.filter \ /etc/privoxy/ ADD k8s-api-proxy.sh /
EXPOSE 8118/tcp
ENTRYPOINT ["./k8s-api-proxy.sh"]在
k8s-api-proxy
目录中,创建config
文件并向其中添加以下内容。#config directory confdir /etc/privoxy # Allow Kubernetes API access only actionsfile /etc/privoxy/k8s-only.action # Rewrite https://CLUSTER_IP to https://kubernetes.default filterfile /etc/privoxy/k8s-rewrite-internal.filter # Don't show the pod name in errors hostname k8s-privoxy # Bind to all interfaces, port :8118 listen-address :8118 # User cannot click-through a block enforce-blocks 1 # Allow more than one outbound connection tolerate-pipelining 1
在同一目录中,创建
k8s-only.action
文件并向其中添加以下内容。请注意,k8s-api-proxy.sh
运行时将替换CLUSTER_IP
。# Block everything... {+block{Not Kubernetes}} /
# ... except the internal k8s endpoint, which you rewrite (see # k8s-rewrite-internal.filter). {+client-header-filter{k8s-rewrite-internal} -block{Kubernetes}} CLUSTER_IP/创建
k8s-rewrite-internal.filter
文件并向其中添加以下内容。请注意,k8s-api-proxy.sh
运行时将替换CLUSTER_IP
。CLIENT-HEADER-FILTER: k8s-rewrite-internal\ Rewrite https://CLUSTER_IP/ to https://kubernetes.default/ s@(CONNECT) CLUSTER_IP:443\ (HTTP/\d\.\d)@$1 kubernetes.default:443 $2@ig
创建
k8s-api-proxy.sh
文件并向其中添加以下内容。#!/bin/sh set -o errexit set -o pipefail set -o nounset # Get the internal cluster IP export TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token) INTERNAL_IP=$(curl -H "Authorization: Bearer $TOKEN" -k -SsL https://kubernetes.default/api | jq -r '.serverAddressByClientCIDRs[0].serverAddress') # Replace CLUSTER_IP in the rewrite filter and action file sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\ /etc/privoxy/k8s-rewrite-internal.filter sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\ /etc/privoxy/k8s-only.action # Start Privoxy un-daemonized privoxy --no-daemon /etc/privoxy/config
将
k8s-api-proxy.sh
设为可执行文件:chmod +x k8s-api-proxy.sh
构建容器并将其推送到项目中。
docker build -t gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 . docker push gcr.io/$PROJECT_ID/k8s-api-proxy:0.1
部署映像和服务
在 Cloud Shell 中,登录您之前创建的客户端虚拟机:
gcloud compute ssh proxy-temp
安装
kubectl
工具。sudo apt-get install kubectl
将项目 ID 保存为环境变量:
export PROJECT_ID=`gcloud config list --format="value(core.project)"`
获取集群凭据:
gcloud container clusters get-credentials frobnitz \ --zone us-central1-c --internal-ip
创建一个 Kubernetes 部署,以公开您刚刚创建的容器:
kubectl run k8s-api-proxy \ --image=gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 \ --port=8118
为内部负载平衡器创建
ilb.yaml
文件,并将以下内容复制到其中:apiVersion: v1 kind: Service metadata: labels: run: k8s-api-proxy name: k8s-api-proxy namespace: default annotations: cloud.google.com/load-balancer-type: "Internal" spec: ports: - port: 8118 protocol: TCP targetPort: 8118 selector: run: k8s-api-proxy type: LoadBalancer
部署内部负载平衡器:
kubectl create -f ilb.yaml
检查服务并等待为其分配 IP 地址:
kubectl get service/k8s-api-proxy
输出将如下所示。当您看到分配了一个外部 IP 时,代理已准备就绪。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-api-proxy LoadBalancer 10.24.13.129 10.24.24.3 8118:30282/TCP 2m
此步骤中的外部 IP 地址即是您的代理地址。
将 ILB 的 IP 地址保存为环境变量:
export LB_IP=`kubectl get service/k8s-api-proxy \ -o jsonpath='{.status.loadBalancer.ingress[].ip}'`
将集群的控制器 IP 地址保存在环境变量中:
export CONTROLLER_IP=`gcloud container clusters describe frobnitz \ --zone=us-central1-c \ --format="get(privateClusterConfig.privateEndpoint)"`
通过代理访问 Kubernetes API,以验证该代理是否可用:
输出将如下所示(您的输出可能会有所不同):curl -k -x $LB_IP:8118 https://$CONTROLLER_IP/version
{ "major": "1", "minor": "15+", "gitVersion": "v1.15.11-gke.5", "gitCommit": "a5bf731ea129336a3cf32c3375317b3a626919d7", "gitTreeState": "clean", "buildDate": "2020-03-31T02:49:49Z", "goVersion": "go1.12.17b4", "compiler": "gc", "platform": "linux/amd64" }
将
https_proxy
环境变量设置为 HTTP(S) 代理,以便kubectl
命令可以从任何位置到达内部负载平衡器:export https_proxy=$LB_IP:8118
通过运行
kubectl
命令测试您的代理和https_proxy
变量:kubectl get pods
您将获得如下所示的输出,这表示您已通过代理成功连接到 Kubernetes API:
NAME READY STATUS RESTARTS AGE k8s-api-proxy-766c69dd45-mfqf4 1/1 Running 0 6m15s
退出客户端虚拟机:
exit
清除数据
为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
删除 GKE 集群
如果您不想删除项目,请删除 GKE 集群:
gcloud container clusters delete frobnitz
后续步骤
- 强化集群的安全性以进一步保护集群
- 专用 Google 访问通道无需公共 IP 即可访问 Google 服务
- 探索有关 Google Cloud 的参考架构、图表、教程和最佳做法。查看我们的 Cloud Architecture Center。