本页面介绍如何在 Google Kubernetes Engine (GKE) 集群中创建 Kubernetes Service。有关 Service 概念的说明以及各种 Service 类型的讨论,请参阅 Service。
简介
Service 的理念是将一组 Pod 端点划分为单一资源。您可以配置各种方式来访问该分组。默认情况下,您会获得稳定的集群 IP 地址,集群内部的客户端可以使用该 IP 地址与 Service 中的 Pod 通信。客户端向稳定 IP 地址发送请求,然后请求会被路由到 Service 的其中一个 Pod。
提供五种类型的 Service:
- ClusterIP(默认)
- NodePort
- LoadBalancer
- ExternalName
- Headless
默认情况下,Autopilot 集群是公开的。如果选择使用专用 Autopilot 集群,则必须配置 Cloud NAT 以进行出站互联网连接,例如从 DockerHub 拉取映像。
本主题提供多个练习。在每个练习中,您将创建 Deployment 并将通过创建 Service 来公开其 Pod。然后,您将向 Service 发送 HTTP 请求。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
创建 ClusterIP 类型的 Service
在本部分中,您将创建一项 ClusterIP
类型的 Service。
kubectl apply
以下是 Deployment 的清单:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
selector:
matchLabels:
app: metrics
department: sales
replicas: 3
template:
metadata:
labels:
app: metrics
department: sales
spec:
containers:
- name: hello
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
将此清单复制到名为 my-deployment.yaml
的文件,然后创建该 Deployment:
kubectl apply -f my-deployment.yaml
确认三个 Pod 是否正在运行:
kubectl get pods
输出会显示三个正在运行的 Pod:
NAME READY STATUS RESTARTS AGE
my-deployment-dbd86c8c4-h5wsf 1/1 Running 0 7s
my-deployment-dbd86c8c4-qfw22 1/1 Running 0 7s
my-deployment-dbd86c8c4-wt4s6 1/1 Running 0 7s
以下是 ClusterIP
类型的 Service 的清单:
apiVersion: v1
kind: Service
metadata:
name: my-cip-service
spec:
type: ClusterIP
# Uncomment the below line to create a Headless Service
# clusterIP: None
selector:
app: metrics
department: sales
ports:
- protocol: TCP
port: 80
targetPort: 8080
该 Service 所具有的选择器指定了两个标签:
app: metrics
department: sales
您之前创建的 Deployment 中的每个 Pod 都有这两个标签。因此,Deployment 中的 Pod 将成为此 Service 的成员。
将此清单复制到名为 my-cip-service.yaml
的文件,然后创建该 Service:
kubectl apply -f my-cip-service.yaml
等待 Kubernetes 为 Service 分配稳定的内部地址,然后查看 Service:
kubectl get service my-cip-service --output yaml
输出会显示 clusterIP
的值:
spec:
clusterIP: 10.59.241.241
记下您的 clusterIP
值以备后续使用。
控制台
创建 Deployment
转到 Google Cloud 控制台中的工作负载页面。
点击 add_box 部署。
在指定容器下,选择现有容器映像。
对于映像路径,请输入
us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
点击完成,然后点击继续。
在配置下,对于应用名称,输入
my-deployment
。在标签下,创建以下标签:
- 键:
app
和值:metrics
- 键:
department
和值:sales
- 键:
在集群下,选择要在其中创建 Deployment 的集群。
点击部署。
Deployment 准备就绪后,Deployment 详情页面随即打开。在托管 pod 下,您可以看到您的 Deployment 具有一个或多个正在运行的 Pod。
创建 Service 以公开您的 Deployment
- 在 Deployment 详情页面上,点击 list操作 > 公开。
在公开对话框中的端口映射下,设置以下值:
- 端口:
80
- 目标端口:
8080
- 协议:
TCP
- 端口:
从 Service 类型下拉列表中,选择集群 IP。
点击公开。
Service 准备就绪后,Service 详情页面随即打开,您可以看到有关 Service 的详细信息。在集群 IP 下,记下 Kubernetes 分配给 Service 的 IP 地址。这是内部客户端在调用 Service 时可以使用的 IP 地址。
访问 Service
列出正在运行的 Pod:
kubectl get pods
在输出中,复制以 my-deployment
开头的其中一个 Pod 名称。
NAME READY STATUS RESTARTS AGE
my-deployment-dbd86c8c4-h5wsf 1/1 Running 0 2m51s
获取其中一个正在运行的容器的 shell:
kubectl exec -it POD_NAME -- sh
将 POD_NAME
替换为 my-deployment
中其中一个 Pod 的名称。
在 shell 中,安装 curl
:
apk add --no-cache curl
在容器中,通过使用您的集群 IP 地址和端口 80,向 Service 发出请求。请注意,80 是 Service 的 port
字段的值。这是用作 Service 客户端的端口。
curl CLUSTER_IP:80
将 CLUSTER_IP
替换为 Service 中 clusterIP
的值。
您的请求将转发到 TCP 端口 8080 上的其中一个成员 Pod,而 8080 是 targetPort
字段的值。请注意,Service 的每个成员 Pod 必须具有一个监听端口 8080 的容器。
响应会显示 hello-app
的输出:
Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-h5wsf
要退出容器的 shell,请输入 exit
。
创建 NodePort 类型的 Service
在本部分中,您将创建一项 NodePort
类型的 Service。
kubectl apply
以下是 Deployment 的清单:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment-50000
spec:
selector:
matchLabels:
app: metrics
department: engineering
replicas: 3
template:
metadata:
labels:
app: metrics
department: engineering
spec:
containers:
- name: hello
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
env:
- name: "PORT"
value: "50000"
请注意清单中的 env
对象。env
对象指定正在运行的容器的 PORT
环境变量的值将为 50000
。hello-app
应用监听 PORT
环境变量所指定的端口。因此在本练习中,您指示容器监听端口 50000。
将此清单复制到名为 my-deployment-50000.yaml
的文件,然后创建该 Deployment:
kubectl apply -f my-deployment-50000.yaml
确认三个 Pod 是否正在运行:
kubectl get pods
以下是 NodePort 类型的 Service 的清单:
apiVersion: v1
kind: Service
metadata:
name: my-np-service
spec:
type: NodePort
selector:
app: metrics
department: engineering
ports:
- protocol: TCP
port: 80
targetPort: 50000
将此清单复制到名为 my-np-service.yaml
的文件,然后创建该 Service:
kubectl apply -f my-np-service.yaml
查看 Service:
kubectl get service my-np-service --output yaml
输出会显示 nodePort
值:
...
spec:
...
ports:
- nodePort: 30876
port: 80
protocol: TCP
targetPort: 50000
selector:
app: metrics
department: engineering
sessionAffinity: None
type: NodePort
...
创建一条防火墙规则以允许 TCP 流量进入节点端口:
gcloud compute firewall-rules create test-node-port \
--allow tcp:NODE_PORT
将 NODE_PORT
替换为 Service 的 nodePort
字段的值。
控制台
创建 Deployment
转到 Google Cloud 控制台中的工作负载页面。
点击 add_box 部署。
在指定容器下,选择现有容器映像。
对于映像路径,请输入
us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
。点击 add 添加环境变量。
对于键,输入
PORT
;对于值,输入50000
。点击完成,然后点击继续。
在配置下,对于应用名称,输入
my-deployment-50000
。在标签下,创建以下标签:
- 键:
app
和值:metrics
- 键:
department
和值:engineering
- 键:
在集群下,选择要在其中创建 Deployment 的集群。
点击部署。
Deployment 准备就绪后,Deployment 详情页面随即打开。在托管 pod 下,您可以看到您的 Deployment 具有一个或多个正在运行的 Pod。
创建 Service 以公开您的 Deployment
- 在 Deployment 详情页面上,点击 list操作 > 公开。
在公开对话框中的端口映射下,设置以下值:
- 端口:
80
- 目标端口:
50000
- 协议:
TCP
- 端口:
从 Service 类型下拉列表中,选择节点端口。
点击公开。
Service 准备就绪后,Service 详情页面随即打开,您可以看到有关 Service 的详细信息。在端口下,记下 Kubernetes 分配给 Service 的节点端口。
为节点端口创建防火墙规则
转到 Google Cloud 控制台中的防火墙政策页面。
点击 add_box 创建防火墙规则。
对于名称,输入
test-node-port
。从目标下拉列表中,选择网络中的所有实例。
对于来源 IPv4 范围,输入
0.0.0.0/0
。在协议和端口下,选择指定的协议和端口。
选中 tcp 复选框,然后输入您记下的节点端口值。
点击创建。
获取节点 IP 地址
找到其中一个节点的外部 IP 地址:
kubectl get nodes --output wide
输出内容类似如下:
NAME STATUS ROLES AGE VERSION EXTERNAL-IP
gke-svc-... Ready none 1h v1.9.7-gke.6 203.0.113.1
并非所有集群的节点都有外部 IP 地址。例如,专用集群中的节点没有外部 IP 地址。
访问 Service
在浏览器的地址栏中,输入以下内容:
NODE_IP_ADDRESS:NODE_PORT
替换以下内容:
NODE_IP_ADDRESS
:其中一个节点的外部 IP 地址,可在上一个任务中创建服务时找到。NODE_PORT
:您的节点端口值。
输出内容类似如下:
Hello, world!
Version: 2.0.0
Hostname: my-deployment-50000-6fb75d85c9-g8c4f
创建 LoadBalancer 类型的 Service
在本部分中,您将创建一项 LoadBalancer
类型的 Service。
kubectl apply
以下是 Deployment 的清单:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment-50001
spec:
selector:
matchLabels:
app: products
department: sales
replicas: 3
template:
metadata:
labels:
app: products
department: sales
spec:
containers:
- name: hello
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
env:
- name: "PORT"
value: "50001"
请注意,此 Deployment 中的容器将监听端口 50001。
将此清单复制到名为 my-deployment-50001.yaml
的文件,然后创建该 Deployment:
kubectl apply -f my-deployment-50001.yaml
确认三个 Pod 是否正在运行:
kubectl get pods
以下是 LoadBalancer
类型的 Service 的清单:
apiVersion: v1
kind: Service
metadata:
name: my-lb-service
spec:
type: LoadBalancer
selector:
app: products
department: sales
ports:
- protocol: TCP
port: 60000
targetPort: 50001
将此清单复制到名为 my-lb-service.yaml,
的文件,然后创建该 Service:
kubectl apply -f my-lb-service.yaml
创建 LoadBalancer
类型的 Service 时,Google Cloud 控制器会唤醒并配置外部直通网络负载均衡器。等待一分钟,让控制器配置外部直通网络负载均衡器并生成稳定 IP 地址。
查看 Service:
kubectl get service my-lb-service --output yaml
输出的 loadBalancer:ingress
下方会显示稳定的外部 IP 地址:
...
spec:
...
ports:
- ...
port: 60000
protocol: TCP
targetPort: 50001
selector:
app: products
department: sales
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.10
控制台
创建 Deployment
转到 Google Cloud 控制台中的工作负载页面。
点击 add_box 部署。
在指定容器下,选择现有容器映像。
对于映像路径,请输入
us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
。点击 add 添加环境变量。
对于键,输入
PORT
;对于值,输入50001
。点击完成,然后点击继续。
在配置下,对于应用名称,输入
my-deployment-50001
。在标签下,创建以下标签:
- 键:
app
和值:products
- 键:
department
和值:sales
- 键:
在集群下,选择要在其中创建 Deployment 的集群。
点击部署。
Deployment 准备就绪后,Deployment 详情页面随即打开。在托管 pod 下,您可以看到您的 Deployment 具有一个或多个正在运行的 Pod。
创建 Service 以公开您的 Deployment
- 在 Deployment 详情页面上,点击 list操作 > 公开。
在公开对话框中的端口映射下,设置以下值:
- 端口:
60000
- 目标端口:
50001
- 协议:
TCP
- 端口:
从 Service 类型下拉列表中,选择负载均衡器。
点击公开。
Service 准备就绪后,Service 详情页面随即打开,您可以看到有关 Service 的详细信息。在负载均衡器下,记下负载均衡器的外部 IP 地址。
访问 Service
等待几分钟,让 GKE 配置负载均衡器。
在浏览器的地址栏中,输入以下内容:
LOAD_BALANCER_ADDRESS:60000
将 LOAD_BALANCER_ADDRESS
替换为负载均衡器的外部 IP 地址。
响应会显示 hello-app
的输出:
Hello, world!
Version: 2.0.0
Hostname: my-deployment-50001-68bb7dfb4b-prvct
请注意,Service 中 port
的值是任意的。在上述示例中,使用的 port
值为 60000。
创建 ExternalName 类型的 Service
在本部分中,您将创建一项 ExternalName
类型的 Service。
ExternalName
类型的 Service 为外部 DNS 名称提供内部别名。内部客户端使用内部 DNS 名称发出请求,然后请求会被重定向到外部名称。
以下是 ExternalName
类型的 Service 的清单:
apiVersion: v1
kind: Service
metadata:
name: my-xn-service
spec:
type: ExternalName
externalName: example.com
在上述示例中,DNS 名称是 my-xn-service.default.svc.cluster.local。当内部客户端向 my-xn-service.default.svc.cluster.local 发出请求时,请求会被重定向到 example.com。
使用 kubectl expose
创建 Service
作为编写 Service 清单的替代方法,您可以使用 kubectl expose
公开 Deployment,以创建 Service。
如需公开本主题前面展示的 my-deployment
,您可以输入以下命令:
kubectl expose deployment my-deployment --name my-cip-service \
--type ClusterIP --protocol TCP --port 80 --target-port 8080
如需公开本主题前面展示的 my-deployment-50000
,您可以输入以下命令:
kubectl expose deployment my-deployment-50000 --name my-np-service \
--type NodePort --protocol TCP --port 80 --target-port 50000
如需公开本主题前面展示的 my-deployment-50001
,您可以输入以下命令:
kubectl expose deployment my-deployment-50001 --name my-lb-service \
--type LoadBalancer --port 60000 --target-port 50001
清理
完成本页面上的练习后,请按照以下步骤移除资源,防止您的账号产生不必要的费用:
kubectl apply
删除 Service
kubectl delete services my-cip-service my-np-service my-lb-service
删除 Deployment
kubectl delete deployments my-deployment my-deployment-50000 my-deployment-50001
删除防火墙规则
gcloud compute firewall-rules delete test-node-port
控制台
删除 Service
转到 Google Cloud 控制台中的服务页面。
选择您在本练习中创建的 Service,然后点击 delete 删除。
当系统提示您确认时,点击删除。
删除 Deployment
转到 Google Cloud 控制台中的工作负载页面。
选择您在本练习中创建的 Deployment,然后点击 delete 删除。
当系统提示确认时,选中删除与所选 Deployment 关联的横向 Pod 自动扩缩器复选框,然后点击删除。
删除防火墙规则
转到 Google Cloud 控制台中的防火墙政策页面。
选中 test-node-port 复选框,然后点击 delete 删除。
当系统提示您确认时,点击删除。