使用 Service 暴露 Deployment

KubernetesBeginner
立即练习

介绍

Pod 是临时的。Deployment 在滚动更新、重启或扩缩容期间会替换 Pod,因此客户端不应直接连接到单个 Pod 的 IP。Service 为客户端提供了一个稳定的名称和虚拟 IP,然后利用标签(label)将流量路由到当前匹配的 Pod。

在本实验中,你将创建一个小型 Web Deployment,使用 ClusterIP Service 将其暴露,检查 Service 如何选择后端 Pod,从客户端 Pod 测试该 Service,并对 Deployment 进行扩容以观察 Service 端点的更新情况。

创建 Web Deployment

在此步骤中,你将准备一个命名空间并创建一个稍后可通过 Service 暴露的 Deployment。

从 /home/labex/project 开始:

mkdir -p /home/labex/project
cd /home/labex/project

检查 Kubernetes API 服务器是否可达。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再运行该命令。

kubectl get nodes --request-timeout=5s

预期输出包含:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

等待集群网络 Pod 就绪。本实验通过 Service 在 Pod 之间发送流量,因此在测试访问之前,集群网络必须处于健康状态。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

预期输出:

pod/calico-node-... condition met

创建一个名为 ckad-prep-service 的命名空间,并将其设置为当前命名空间:

kubectl create namespace ckad-prep-service
kubectl config set-context --current --namespace=ckad-prep-service

创建一个名为 web-front 的 Deployment,其中包含一个 NGINX Pod。--port=80 标志用于在 Pod 模板中记录容器端口,它本身不会创建 Service。

kubectl create deployment web-front --image=nginx:1.25 --port=80

等待 Deployment 可用,然后检查 Pod 标签。标签 app=web-front 非常重要,因为 Service 将使用它来查找后端 Pod。

kubectl rollout status deployment/web-front --timeout=120s
kubectl get pods -l app=web-front --show-labels

预期输出包含:

deployment "web-front" successfully rolled out
NAME                         READY   STATUS    RESTARTS   AGE   LABELS
web-front-...                1/1     Running   0          ...   app=web-front,...

使用 ClusterIP Service 暴露 Deployment

在此步骤中,你将为 Deployment 创建一个 Service,并检查将 Service 连接到 Pod 的字段。

使用 kubectl expose deployment 创建一个 ClusterIP Service。Service 端口为 80,--target-port=80 告诉 Service 将流量转发到匹配 Pod 上的 80 端口。

kubectl expose deployment web-front --name=web-front --port=80 --target-port=80

预期输出:

service/web-front exposed

检查该 Service:

kubectl get service web-front

预期输出包含:

NAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
web-front   ClusterIP   ...          <none>        80/TCP    ...

现在检查 Service 的选择器(selector)和端口映射。选择器是 Service 查找 Pod 的方式;端口映射是客户端流量到达容器的方式。

kubectl get service web-front -o jsonpath='{.spec.selector.app}{" "}{.spec.ports[0].port}{":"}{.spec.ports[0].targetPort}{"\n"}'

预期输出:

web-front 80:80

Kubernetes 将选定的后端地址存储在 EndpointSlice 中。列出为该 Service 创建的 EndpointSlice:

kubectl get endpointslice -l kubernetes.io/service-name=web-front

预期输出包含:

NAME              ADDRESSTYPE   PORTS   ENDPOINTS   AGE
web-front-...     IPv4          80      ...         ...

从集群内部测试 Service

在此步骤中,你将创建一个临时客户端 Pod 并向 Service 发送 HTTP 请求。ClusterIP Service 旨在用于集群内访问,因此从另一个 Pod 进行测试是验证它的最直接方法。

创建一个持续运行的客户端 Pod:

kubectl run service-client --image=busybox:1.36 --restart=Never --command -- sleep 3600

等待客户端 Pod 就绪:

kubectl wait --for=condition=Ready pod/service-client --timeout=120s

预期输出:

pod/service-client condition met

在客户端 Pod 内使用 wget 请求 http://web-front。名称 web-front 会解析为命名空间内的 Service。

kubectl exec service-client -- wget -qO- http://web-front | head -n 5

预期输出包含默认 NGINX 页面的开头:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

这证明了客户端已成功连接到稳定的 Service 名称,并且 Service 已将流量转发到当前的后端 Pod。

扩容后端并重新检查端点

在此步骤中,你将对 Deployment 进行扩容,并确认 Service 在后端端点发生变化时,仍保持相同的稳定访问入口。

将 Deployment 扩容至两个副本:

kubectl scale deployment web-front --replicas=2
kubectl rollout status deployment/web-front --timeout=120s

预期输出包含:

deployment.apps/web-front scaled
deployment "web-front" successfully rolled out

列出 Pod。现在应该有两个带有相同 app=web-front 标签的运行中后端 Pod。

kubectl get pods -l app=web-front

预期输出包含两个 Pod:

NAME                         READY   STATUS    RESTARTS   AGE
web-front-...                1/1     Running   0          ...
web-front-...                1/1     Running   0          ...

统计 Service 后端的端点数量。该命令会为每个端点地址打印一行,然后统计行数。

kubectl get endpointslice -l kubernetes.io/service-name=web-front -o jsonpath='{range .items[*].endpoints[*]}{.addresses[0]}{"\n"}{end}' | wc -l

预期输出:

2

再次从同一个客户端 Pod 请求该 Service:

kubectl exec service-client -- wget -qO- http://web-front | grep '<title>Welcome to nginx'

预期输出:

<title>Welcome to nginx!</title>

总结

你使用 ClusterIP Service 暴露了一个 Deployment,并验证了完整的集群内访问路径。你创建了一个后端 Deployment,创建了一个带有选择器和端口映射的 Service,检查了为该 Service 生成的 EndpointSlice,从客户端 Pod 测试了访问,随后对 Deployment 进行了扩容,并确认 Service 继续将流量路由到更新后的后端集合。