本教程将介绍如何使用 Istio,为在 Google Kubernetes Engine (GKE) 上运行的 gRPC 服务设置内部 TCP/UDP 负载平衡。此设置允许 VPC 网络中的其他资源使用专用的内部 (RFC 1918) IP 地址与 gRPC 服务进行通信,而 Istio 则负责处理运行 gRPC 服务的 Kubernetes Pod 之间的路由和负载平衡请求。
本教程假定您具备 gRPC 和 GKE 或 Kubernetes 的基础知识。
简介
Istio 为传入和离开服务网格的流量提供了管理网关。Istio 内部负载平衡器 (ILB) 网关将来自内部 VPC 网络中的源的入站流量路由到服务网格中的 Kubernetes Pod。在这种架构中,Google Cloud 内部 TCP/UDP 负载平衡机制在 GKE 集群中的节点之间执行第 4 层(传输层)负载平衡。Istio ILB 网关接收流量并执行第 7 层(应用层)负载平衡,利用在虚拟服务和目标规则中定义的规则将流量分发给 Istio 服务网格中的服务。
本教程中使用的示例 gRPC 服务会返回一个响应标头,该标头中包含处理请求的 Kubernetes Pod 的名称。根据这些信息,您可以看到 Istio ILB 网关执行负载平衡,将客户端通过单个连接发出的请求分发给 GKE 集群中的多个 Kubernetes Pod。
目标
- 使用 Istio 和 Istio ILB 网关创建 GKE 集群。
- 部署示例 gRPC 服务。
- 验证内部连接。
费用
本教程使用 Google Cloud 的以下收费组件:
您可使用价格计算器根据您的预计使用量来估算费用。 Google Cloud 新用户可能有资格申请免费试用。
完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理。
准备工作
- 登录您的 Google 帐号;如果您没有 Google 帐号,请注册一个新帐号。
-
在 Google Cloud Console 中,转到项目选择器页面。
-
选择或创建 Google Cloud 项目。
-
确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能。
初始化环境
在 Cloud Console 的选择项目下拉列表中,选择要使用的项目。
打开 Cloud Shell:
您可以使用 Cloud Shell 运行本教程中的所有命令。
启用 Cloud Build API、Google Kubernetes Engine API、Container Analysis API 和 Cloud API:
gcloud services enable \ cloudapis.googleapis.com \ cloudbuild.googleapis.com \ container.googleapis.com \ containeranalysis.googleapis.com
为您要在本教程中使用的 Compute Engine 地区设置
gcloud
默认值:gcloud config set compute/zone us-central1-b
本教程使用
us-central1-b
地区。您可以根据自己的需要更改地区。克隆包含示例 gRPC 服务的 Git 代码库,并切换到工作目录:
git clone https://github.com/GoogleCloudPlatform/istio-samples.git cd istio-samples/sample-apps/grpc-greeter-go
使用 Istio 创建 GKE 集群
在 Cloud Shell 中创建一个 GKE 集群:
gcloud beta container clusters create grpc-istio-ilb-tutorial \ --machine-type n1-standard-2 \ --enable-ip-alias
为您自己授予该集群的管理员权限:
kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin \ --user $(gcloud config get-value account)
您必须具有
cluster-admin
Kubernetes 集群角色中定义的权限才能安装 Istio。创建一个名为
istio-system
的 Kubernetes 命名空间:kubectl create namespace istio-system
下载并解压 Istio:
ISTIO_VERSION=1.2.7 curl -L https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-linux.tar.gz | tar -zxf -
使用 Helm 的本地模板渲染来安装 Istio 自定义资源定义 (CRD):
helm template \ istio-$ISTIO_VERSION/install/kubernetes/helm/istio-init \ --namespace istio-system | kubectl apply -f -
使用 Helm 通过 ILB 网关 (
istio-ilbgateway
) 安装 Istio:ISTIO_PACKAGE=$ISTIO_VERSION-gke.0 helm template \ istio-$ISTIO_VERSION/install/kubernetes/helm/istio \ --set gateways.istio-ingressgateway.enabled=false \ --set gateways.istio-ilbgateway.enabled=true \ --set gateways.istio-ilbgateway.ports[0].name=grpc-pilot-mtls \ --set gateways.istio-ilbgateway.ports[0].port=15011 \ --set gateways.istio-ilbgateway.ports[1].name=grpc \ --set gateways.istio-ilbgateway.ports[1].port=443 \ --set gateways.istio-ilbgateway.ports[2].name=tcp-citadel-grpc-tls \ --set gateways.istio-ilbgateway.ports[2].port=8060 \ --set gateways.istio-ilbgateway.ports[2].targetPort=8060 \ --set gateways.istio-ilbgateway.ports[3].name=tcp-dns \ --set gateways.istio-ilbgateway.ports[3].port=5353 \ --set global.hub=gcr.io/gke-release/istio \ --set global.tag=$ISTIO_PACKAGE \ --namespace istio-system | kubectl apply -f -
检查
istio-ilbgateway
Kubernetes 服务的外部 IP 地址的创建状态:kubectl get services istio-ilbgateway -n istio-system --watch
等待
EXTERNAL-IP
值从<pending>
更改为 IP 地址。按 Control+C 即可停止等待。
为 Istio ILB 网关创建传输层安全协议 (TLS) 证书
在 Cloud Shell 中,创建 TLS 证书和私钥以允许 Istio ILB 网关终止 TLS:
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \ -keyout privkey.pem -out cert.pem -subj "/CN=grpc.example.com"
创建用于存储 TLS 证书和私钥的 Kubernetes Secret:
kubectl -n istio-system create secret tls istio-ilbgateway-certs \ --key privkey.pem --cert cert.pem \ --dry-run -o yaml | kubectl apply -f -
安装示例应用
下一步是为示例 gRPC 服务构建一个容器映像,并将其部署到您的 GKE 集群。示例 gRPC 服务由一个客户端组件(称为 gRPC 客户端)和一个服务器组件(称为 gRPC 服务器)构成。
在 Cloud Shell 中,在
default
命名空间中启用自动 Istio 辅助信息文件注入功能:kubectl label namespace default istio-injection=enabled
使用 Cloud Build 为 gRPC 服务器创建容器映像:
gcloud builds submit server -t gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-server
为 gRPC 服务器创建 Kubernetes Deployment 和 Service 对象:
envsubst < manifests/greeter-k8s.template.yaml | kubectl apply -f -
验证系统是否已创建
ClusterIP
Kubernetes 服务,确认 Pod 是否在运行:kubectl get services,pods
输出类似于以下内容:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/greeter ClusterIP 10.0.18.67 <none> 8080/TCP 11s service/kubernetes ClusterIP 10.0.16.1 <none> 443/TCP 1h
NAME READY STATUS RESTARTS AGE pod/greeter-844cffd75-7hpcb 2/2 Running 0 56s pod/greeter-844cffd75-ffccl 2/2 Running 0 56s pod/greeter-844cffd75-zww6h 2/2 Running 0 56sPod 在
READY
列中显示2/2
。这样的输出结果表示:对于每个 Pod,gRPC 服务器容器和 Envoy Sidecar 容器都在运行。为 gRPC 服务器创建 Istio 网关、虚拟服务和目标规则对象:
kubectl apply -f manifests/greeter-istio-ilbgateway.yaml \ -f manifests/greeter-istio-virtualservice.yaml \ -f manifests/greeter-istio-destinationrule.yaml
验证是否已成功创建全部三个对象:
kubectl get gateway,virtualservice,destinationrule
输出类似于以下内容:
NAME AGE gateway.networking.istio.io/greeter 1m
NAME GATEWAYS HOSTS AGE virtualservice.networking.istio.io/greeter [greeter] [*] 1m
NAME HOST AGE destinationrule.networking.istio.io/greeter greeter 1m
验证内部连接
内部 TCP/UDP 负载平衡是区域性的,因此您可以测试相同地区或区域中的虚拟机发起的连接。
在 Cloud Shell 中,使用 Cloud Build 为 gRPC 客户端创建容器映像:
gcloud builds submit client \ -t gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-client
在 GKE 集群所在的相同地区或区域内创建一个 Compute Engine 实例:
gcloud compute instances create grpc-istio-ilb-tutorial-client-vm \ --scopes https://www.googleapis.com/auth/devstorage.read_only \ --image-project cos-cloud \ --image-family cos-stable
为了从 Container Registry 下载映像,必须使用
devstorage.read_only
范围。将 Istio ILB 网关 IP 地址存储在名为
ilb-ip.txt
的文件中:kubectl -n istio-system get services istio-ilbgateway \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}' > ilb-ip.txt
将自签名 TLS 证书和包含 Istio ILB 网关 IP 地址的文件复制到虚拟机:
gcloud compute scp cert.pem ilb-ip.txt grpc-istio-ilb-tutorial-client-vm:~
使用 SSH 连接到虚拟机:
gcloud compute ssh grpc-istio-ilb-tutorial-client-vm
在虚拟机上,从 Compute Engine 元数据服务器中查询项目 ID,并将查询结果存储在环境变量
GOOGLE_CLOUD_PROJECT
内。GOOGLE_CLOUD_PROJECT=$(curl -sH "Metadata-Flavor: Google" \ http://metadata.google.internal/computeMetadata/v1/project/project-id)
Cloud Shell 中默认会设置环境变量
GOOGLE_CLOUD_PROJECT
,但在虚拟机中则不会进行这样的默认设置。获取 Container Registry 凭据,以便配合
docker
命令使用:docker-credential-gcr configure-docker
运行 gRPC 客户端容器映像:
docker run --rm -v $(pwd)/cert.pem:/data/cert.pem \ --add-host grpc.example.com:$(cat ilb-ip.txt) \ gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-client \ --address=grpc.example.com:443
输出类似于以下内容:
2019/03/27 15:12:53 Hello world from greeter-844cffd75-ffccl 2019/03/27 15:12:53 Hello world from greeter-844cffd75-zww6h 2019/03/27 15:12:53 Hello world from greeter-844cffd75-7hpcb 2019/03/27 15:12:53 Hello world from greeter-844cffd75-ffccl 2019/03/27 15:12:53 Hello world from greeter-844cffd75-zww6h 2019/03/27 15:12:53 Hello world from greeter-844cffd75-7hpcb 2019/03/27 15:12:53 Hello world from greeter-844cffd75-ffccl 2019/03/27 15:12:53 Hello world from greeter-844cffd75-zww6h 2019/03/27 15:12:53 Hello world from greeter-844cffd75-7hpcb
此输出显示,gRPC 一元请求由 gRPC 服务器 Pod(名为
greeter-*
)根据 Istio 目标规则内的loadBalancer
配置(本例中为ROUND_ROBIN
)进行处理。退出 SSH 会话:
exit
检查源代码
为了更好地了解负载平衡配置,您可以查看示例应用的源代码。
例如,要了解 gRPC 客户端显示的消息,请查看服务器和客户端的 Go 源代码。在 gRPC 服务器处理请求时,它会查找主机名并将其添加为名为 hostname
的响应标头。由于服务器在 Kubernetes Pod 中运行,因此主机名就是这个 Pod 的名称。
在 gRPC 客户端收到来自服务器的响应时,它会获取 hostname
标头并在控制台中显示此标头。
若要了解 gRPC 客户端在控制台中显示的 Kubernetes Pod 名称,请查看 gRPC 服务器的 Istio 配置。请注意,DestinationRule
对象将 ROUND_ROBIN
指定为 loadBalancer
算法。此算法是传入请求在 Kubernetes 部署中的 Pod 之间轮转的原因。
问题排查
如果您在使用本教程时遇到问题,我们建议您查看以下文档:
清理
为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请执行以下操作:
在 Cloud Shell 中,删除 GKE 集群:
gcloud container clusters delete grpc-istio-ilb-tutorial --quiet --async
删除 Container Registry 中的映像:
gcloud container images delete gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-client \ --force-delete-tags --quiet gcloud container images delete gcr.io/$GOOGLE_CLOUD_PROJECT/grpc-greeter-go-server \ --force-delete-tags --quiet
删除 Compute Engine 实例:
gcloud compute instances delete grpc-istio-ilb-tutorial-client-vm --quiet
后续步骤
- 探索 Istio 的其他 Google Cloud 演示、教程和示例。
- 浏览示例,了解如何将 gRPC 服务公开给 Kubernetes 集群中的客户端。
- 了解 Google Kubernetes Engine 网络。
- 了解 gRPC 负载平衡的选项。
- 使用 Cloud Endpoints Extensible Service Proxy 和 Google Kubernetes Engine 部署 gRPC 服务。
- 试用其他 Google Cloud 功能。查阅我们的教程。