
GKE 是 Google Cloud 的 Kubernetes 的服务。其架构如下:

Master Node 是 Google 免费提供的,用户自己创建 Node Pool,不同的 Node Pool 可以采用不同的硬件配置,比如带 GPU 或不带 GPU。
在 GKE 上,创建不同的对外的服务接口,相应的将自动生成不同的服务:
如果创建一个 ingress,系统将自动创建一个 http(s)的负载均衡或 L7 的 internal LB;
如果创建一个 LoadBalancer 类型的 Service,系统将自动创建一个 TCP 的负载均衡;
如果创建一个 LoadBalancer 类型的内网地址的 service,系统将自动创建一个 TCP 的 Internal loadbalancer;
如果创建一个 nodeport 类型的 Service,不会自动生成 loadBalancer
本文将介绍这几种 service 如何创建,并特别介绍如何同时支持 ingress 和内网地址的 service。
创建 GKE cluster
创建 cluster
通过界面创建 GKE 的 cluster:

Cluster 创建成功:

kubectl 与 cluster 连接
在界面上点击 connect


复制 gcloud 命令
并在 cloud shell 中运行:

连接成功,可以通过 kubectl 控制 cluster:

二 部署 workload
通过 kubectl 命令创建 3 个 pod nginx 的 deployment:
在 console 上可以看到:

通过 kubectl 查看:

cluster 网络
pod IP 地址段
查看 cluster 的详情:

因为 Google 的 GKE 采用的是 per pod per IP 的模式,Pod 的 IP 地址在 VPC 内:

这段地址是在创建 cluster 时自动创建的,专门用于 pods 的 IP 地址。另外在 VPC 内还有一段 IP 地址用于将来 Service 使用,比如 cluster IP。
node IP 地址

查看 node 的 IP:
可以看到,除标准段 primary Internal IP 外,这个 node 有一个 alias IP,是在 pods IP 内的一个 24 位掩码的地址段。在这个 node 上的 pod 将会使用这段地址。这样,每个 node 会有一段 IP 地址。这种设计和 K8s 网络的 flannel 类似:

GKE 中,这段 Alias IP 用于 Pod 间通讯,也可以用于和 GCE 的通讯。如上图,Node2 的 IP 地址为 10.1.1.22,Pod 的 IP 地址段是 10.40.2.0/24。此 Node 上的 Pod 地址都在这个 Alias IP 段内。GCE 10.100.1.10 与 Node2 的 Pod 进行通讯,可以直接和 10.40.2.10 或 10.40.2.11 直接通讯。跨 Node 的 Pod 间通讯,也直接用 Pod IP 进行通讯,比如 10.40.1.10 <-> 10.40.2.10。
pod 的 IP
查看 pod 信息可以看到 3 个 pod,运行在不同的 node 上,并且 IP 地址是 10.40.0.0/24,10.40.1.0/24, 10.40.2.0/24 的地址段。印证了我们前面观察到的 node ip 地址段。

在同一个网段的 VM 去 ping 和 curl 一个 pod,发现可以直接访问:

如前所述,这样的设计解决了在 K8s 集群中,跨 node 的 pod 通讯问题,也解决了非 cluster 内 IP 和 pod 通讯的问题。
创建 Load Balancer 类型的 service
创建 Service
在 Google Cloud console 中,

在 workload 界面中选择 expose

填入相应的参数,点击 expose:

由于类型选择的是 loadbalancer,GCP 会自动创建一个 TCP 的 loadbalancer。
Service 详情
首先查看 service:

看到 service 已经创建成功,类型是 load balancer 的。
负载均衡详情
再查看 loadbalancer:

可以看到一个 TCP 的 load balancer 已经创建成功。
后端采用的是添加 Instance 的方式:

前端生成一个公网 IP 地址:

通过这个 IP 地址,可以访问到访问:

创建内部 IP 的 service
通过 yaml 文件创建
在 cloud shell 中创建一个 yaml 文件:

apiVersion: v1
通过 kubectl 创建这个内部 IP 的 service:
service 详情

在 console 上可以看到已经创建成功。
详细信息中,可以看到:

内部 IP 是 10.1.1.27,这个地址是这个网段的 primary IP 地址段,Cluster IP 在 cluster 中定义的一致,后端有 3 个 pod,服务端口是 80,node port 是 30660,pod 内的 port 是 80.
ILB 详情
查看 ilb 信息:

在详细信息中,可以看到 backend 信息:

ILB 的后端采用 instance group 的形式。
ILB 的前端:

创建 ingress
创建基于 node port 的 service
创建 yaml 文件:
通过 kubectl 创建:
nodeport service 详情

详情如下:

创建 ingress
创建 ingress 的 yaml 文件:
创建 ingress:
Ingress 详情
可以看到 ingress 创建成功:

详细内容:

http 负载均衡详情
可以看到 http 负载均衡已经创建成功:

后端情况,有两个 backend,但 instance group 相同:

Load balancer mode 采用的是 rate 模式:

Rule 有 3 条,分布引用这两个 backend service:

前端是有公网 IP 的 HTTP 配置:

通过这个公网 IP,同样可以访问到服务:

注意事项
注意到在 ingress 的 http 负载均衡中,load balancer 模式采用的是 rate 模式。
在实际操作中,如果先创建 ingress,有可能会采用 utilization 模式,而 ILB 的 backend 只能采用 rate 模式,此时再创建内部 IP 的 service 时,会出错:

查看 HTTP 负载均衡情况:

这个是 utilization 模式。造成不能创建 ILB。
目前,建议先创建内部 IP 的 service,再创建 ingress,这样可以避免这个问题。
总结
通过介绍如何创建 GKE 上各种 Service 类型,介绍了 Cluster 的创建、GKE 的网络组成、Ingress、ILB 模式的 Service,nodeport 模式的 service 的 Yaml 文件。以及在需要同时支持 ingress 和 ILB 模式 Service 是要注意的问题。
评论