1. 概述

网络是 Kubernetes 的核心组成部分,其中*服务*是其基础网络对象之一。Kubernetes 服务允许我们将网络应用暴露给外部世界。但访问它时,我们必须知道其 URL。

本篇实战教程将讨论如何查找并使用 Kubernetes 服务的 URL 作为可靠的网络接口。

2. 搭建示例环境

我们需要创建几个 Kubernetes 对象作为示例。首先创建*命名空间*对象。

2.1. 创建 Kubernetes 命名空间

Kubernetes 命名空间允许我们在同一集群内隔离资源。使用create命令创建两个命名空间——devstg

$ kubectl create ns dev
namespace/dev created

$ kubectl create ns stg
namespace/stg created

2.2. 创建 Kubernetes 部署

上一步创建了两个命名空间。现在将 Redis Pod 部署到这些命名空间:

$ kubectl create deploy redis-dev --image=redis:alpine -n dev
deployment.apps/redis-dev created

$ kubectl create deploy redis-stg --image=redis:alpine -n stg
deployment.apps/redis-stg created

验证 Pod 是否创建成功并处于健康状态:

$ kubectl get pods -n dev
NAME                         READY   STATUS    RESTARTS   AGE
redis-dev-7b647c797c-c2mmg   1/1     Running   0          16s

$ kubectl get pods -n stg
NAME                        READY   STATUS    RESTARTS   AGE
redis-stg-d66978466-plfpv   1/1     Running   0          9s

两个 Pod 状态均为 Running。基础环境已就绪,接下来我们将创建几个服务对象与这些 Pod 建立通信。

3. 查找 ClusterIP 服务的 URL

在 Kubernetes 中,默认服务类型是ClusterIP对于 ClusterIP 服务,我们可以使用服务名或其 IP 地址作为 URL。这能将通信限制在集群内部。通过简单示例理解这一点。

3.1. 创建 ClusterIP 服务

在两个命名空间中创建 ClusterIP服务对象:

$ kubectl expose deploy redis-dev --port 6379 --type ClusterIP -n dev
service/redis-dev exposed

$ kubectl expose deploy redis-stg --port 6379 --type ClusterIP -n stg
service/redis-stg exposed

这里使用expose命令创建服务。expose 命令会复用*部署*对象的标签选择器创建服务

后续章节将讨论如何查找并使用这些服务名作为 URL。

3.2. 在同一命名空间使用 ClusterIP 服务 URL

使用get命令查找 dev 命名空间的服务名:

$ kubectl get svc -n dev
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
redis-dev   ClusterIP   10.100.18.154   <none>        6379/TCP   9s

输出第一列显示服务名(本例为 redis-dev)。

现在exec进入 dev 命名空间的 Redis Pod,使用 redis-dev 作为主机名连接 Redis 服务器,执行PING命令:

$ kubectl exec -it redis-dev-7b647c797c-c2mmg -n dev -- sh
/data # redis-cli -h redis-dev PING
PONG
/data # exit

Redis 服务器返回 PONG 响应。执行exit命令退出 Pod。

3.3. 从其他命名空间使用 ClusterIP 服务 URL

ClusterIP 服务 URL 的格式:

<服务名>.<命名空间>.<集群名>:<服务端口>

前例未使用命名空间集群名,因为命令在同一命名空间和集群执行。同时省略了服务端口,因为服务暴露的是 Redis 默认端口 6379

但从其他命名空间访问 ClusterIP 服务时必须指定命名空间。通过示例理解:

先查找 stg 命名空间的服务名:

$ kubectl get svc -n stg
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
redis-stg   ClusterIP   10.110.213.51   <none>        6379/TCP   9s

现在exec进入 dev 命名空间的 Redis Pod,使用 redis-stg.stg 作为主机名连接 Redis 服务器,执行 PING 命令:

$ kubectl exec -it redis-dev-7b647c797c-c2mmg -n dev -- sh
/data # redis-cli -h redis-stg.stg PING
PONG
/data # exit

Redis 服务器返回 PONG 响应。

⚠️ 关键点:我们使用 redis-stg.stg 作为主机名,其中 redis-stg 是服务名,stg 是服务对象所在的命名空间。

3.4. 清理资源

前文展示了如何使用服务名作为 URL。现在用delete命令清理 devstg 命名空间的服务:

$ kubectl delete svc redis-dev -n dev
service "redis-dev" deleted

$ kubectl delete svc redis-stg -n stg
service "redis-stg" deleted

4. 查找 NodePort 服务的 URL

NodePort服务允许通过 Kubernetes 节点的 IP 和端口从外部访问应用。通过创建 NodePort 服务理解这一点。

4.1. 创建 NodePort 服务

使用 expose 命令创建 NodePort 类型的服务:

$ kubectl expose deploy redis-dev --port 6379 --type NodePort -n dev
service/redis-dev exposed

验证服务创建成功:

$ kubectl get svc -n dev
NAME        TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
redis-dev   NodePort   10.111.147.176   <none>        6379:30243/TCP   2s

服务类型为 NodePort。倒数第二列显示 Kubernetes 节点端口 30243 映射到 Pod 端口 6379

现在可以从集群外部使用节点 IP 和端口 30243 访问 Redis 服务器。实际操作验证:

4.2. 使用 NodePort 服务 URL

先获取 Kubernetes 节点的 IP 地址:

$ kubectl get nodes -o wide
NAME       STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
baeldung   Ready    control-plane   24h   v1.28.3   192.168.49.2   <none>        Ubuntu 22.04.3 LTS   5.15.0-41-generic   docker://24.0.7

使用 -o wide 选项显示节点额外字段。INTERNAL-IP 列显示 Kubernetes 节点的 IP 地址

从外部机器连接 Redis 服务器,使用 192.168.49.2 作为主机名,30243 作为端口号,执行 PING 命令:

$ redis-cli -h 192.168.49.2 -p 30243 PING
PONG

Redis 服务器返回 PONG 响应。

4.3. 清理资源

下一节将介绍LoadBalancer服务。先清理 dev 命名空间的 NodePort 服务:

$ kubectl delete svc redis-dev -n dev
service "redis-dev" deleted

5. 查找 LoadBalancer 服务的 URL

与 NodePort 服务类似,LoadBalancer 服务也允许通过负载均衡器的 IP 从外部访问应用。通过创建 LoadBalancer 服务理解:

5.1. 创建 LoadBalancer 服务

dev 命名空间创建 LoadBalancer 服务:

$ kubectl expose deploy redis-dev --port 6379 --type LoadBalancer -n dev
service/redis-dev exposed

5.2. 使用 LoadBalancer 服务 URL

使用 get 命令查找负载均衡器的 IP 地址:

$ kubectl get svc -n dev
NAME        TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)          AGE
redis-dev   LoadBalancer   10.111.167.249   192.168.49.10   6379:32637/TCP   7s

EXTERNAL-IP 列表示 LoadBalancer 服务的 IP 地址。本例中负载均衡器 IP 为 192.168.49.10

从外部机器连接 Redis 服务器,使用 192.168.49.10 作为主机名,执行 PING 命令:

$ redis-cli -h 192.168.49.10 PING
PONG

Redis 服务器返回 PONG 响应。

6. 清理资源

删除不需要的对象是良好实践,能降低硬件消耗成本。使用 delete 命令移除 devstg 命名空间:

$ kubectl delete ns dev
namespace "dev" deleted

$ kubectl delete ns stg
namespace "stg" deleted

此命令会删除命名空间及其包含的所有对象。

⚠️ 注意:我们直接删除了命名空间(因为是测试环境),但在生产环境执行删除操作时务必谨慎!

7. 总结

本文讨论了如何在 Kubernetes 中查找并使用服务的 URL:

ClusterIP 服务

  • 同命名空间内直接使用服务名
  • 跨命名空间使用 <服务名>.<命名空间> 格式

NodePort 服务

  • 使用 <节点IP>:<NodePort> 从外部访问

LoadBalancer 服务

  • 使用负载均衡器的 EXTERNAL-IP 从外部访问

掌握这些方法能帮你快速定位服务访问地址,避免在 Kubernetes 网络配置中踩坑。


原始标题:How to Find the URL of a Service in Kubernetes | Baeldung