目标
- 了解 Kubernetes 中的 Service
- 理解标签和选择器与 Service 的关系
- 使用 Service 将应用程序暴露到 Kubernetes 集群外部
Kubernetes Service 概述
Kubernetes Pod 是有生命周期的。Pod 具有生命周期。当工作节点宕机时,在该节点上运行的 Pod 也会丢失。副本集可能会通过创建新的 Pod 来动态地将集群恢复到所需状态,以保持应用程序运行。另一个例子是具有 3 个副本的图像处理后端。这些副本是可以互换的;前端系统不应该关心后端副本,甚至不应该关心 Pod 是否丢失并重新创建。也就是说,Kubernetes 集群中的每个 Pod 都有一个唯一的 IP 地址,即使是同一节点上的 Pod 也是如此,因此需要一种自动协调 Pod 之间变化的方法,以便应用程序能够继续运行。
Kubernetes 中的 Service 是一种抽象,它定义了一组逻辑 Pod 以及访问它们的策略。Service 实现了依赖 Pod 之间的松散耦合。与所有 Kubernetes 对象清单一样,Service 是使用 YAML 或 JSON 定义的。Service 定位的 Pod 集通常由*标签选择器*确定(请参阅下文,了解为什么你可能希望 Service 的规约中不包含 `selector`)。
尽管每个 Pod 都有唯一的 IP 地址,但如果没有 Service,这些 IP 地址不会暴露到集群外部。Service 允许应用程序接收流量。通过在以下位置指定 `type`,可以用不同的方式暴露 Service规约Service 的
- *ClusterIP*(默认)- 在集群的内部 IP 上暴露 Service。此类型使 Service 只能在集群内访问。
- *NodePort* - 使用 NAT 在集群中每个选定节点的同一端口上暴露 Service。使用 `<NodeIP>:<NodePort>` 使 Service 可以从集群外部访问。ClusterIP 的超集。
- *LoadBalancer* - 在当前云中(如果支持)创建一个外部负载均衡器,并为 Service 分配一个固定的外部 IP。NodePort 的超集。
- *ExternalName* - 通过返回一个值为 `externalName` 字段内容(例如 `foo.bar.example.com`)的 `CNAME` 记录,将 Service 映射到该字段的内容。不设置任何类型的代理。此类型需要 v1.7 或更高版本的 `kube-dns` 或 CoreDNS 0.0.8 或更高版本。
有关不同类型 Service 的更多信息,请参阅使用源 IP教程。另请参阅使用 Service 连接应用程序。
此外,请注意,Service 的某些用例涉及不在规约中定义 `selector`。没有 `selector` 创建的 Service 也不会创建相应的端点对象。这允许用户手动将 Service 映射到特定端点。可能没有选择器的另一个原因是你严格使用 `type: ExternalName`。
总结
- 将 Pod 暴露给外部流量
- 在多个 Pod 之间进行负载均衡
- 使用标签
Kubernetes Service 是一个抽象层,它定义了一组逻辑 Pod,并为这些 Pod 启用外部流量暴露、负载均衡和服务发现。
Service 和标签
Service 在一组 Pod 之间路由流量。Service 是一种抽象,它允许 Pod 在 Kubernetes 中消亡和复制,而不会影响应用程序。依赖 Pod(例如应用程序中的前端和后端组件)之间的发现和路由由 Kubernetes Service 处理。
Service 使用标签和选择器来匹配一组 Pod,这是一个分组原语,允许对 Kubernetes 中的对象进行逻辑操作。标签是附加到对象的键/值对,可以以多种方式使用
- 指定用于开发、测试和生产的对象
- 嵌入版本标签
- 使用标签对对象进行分类
可以在创建对象时或之后附加标签。它们可以随时修改。现在让我们使用 Service 暴露我们的应用程序,并应用一些标签。
步骤 1:创建新 Service
让我们验证我们的应用程序是否正在运行。我们将使用 `kubectl get` 命令并查找现有的 Pod
kubectl get pods
如果没有 Pod 正在运行,则表示先前教程中的对象已被清理。在这种情况下,请返回并从使用 kubectl 创建 Deployment教程重新创建 Deployment。请等待几秒钟,然后再次列出 Pod。一旦你看到一个 Pod 正在运行,就可以继续。
接下来,让我们列出集群中当前的 Service
kubectl get services
我们有一个名为kubernetes的 Service,它是在 minikube 启动集群时默认创建的。要创建新 Service 并将其暴露给外部流量,我们将使用 expose 命令并将 NodePort 作为参数。
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
让我们再次运行 `get services` 子命令
kubectl get services
我们现在有一个名为 kubernetes-bootcamp 的正在运行的 Service。在这里,我们看到 Service 收到了唯一的集群 IP、内部端口和外部 IP(节点的 IP)。
要找出外部打开了哪个端口(对于type: NodePortService),我们将运行 `describe service` 子命令
kubectl describe services/kubernetes-bootcamp
创建一个名为NODE_PORT的环境变量,其值为分配的节点端口
export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"
现在我们可以使用 curl
、节点的 IP 地址和外部公开的端口来测试应用是否已暴露在集群外部。
curl http://"$(minikube ip):$NODE_PORT"
注意
如果您使用 Docker Desktop 作为容器驱动程序运行 minikube,则需要 minikube 隧道。这是因为 Docker Desktop 内的容器与您的主机计算机是隔离的。
在单独的终端窗口中,执行minikube service kubernetes-bootcamp --url
输出如下所示
http://127.0.0.1:51082
! Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
然后使用给定的 URL 访问应用curl 127.0.0.1:51082
我们将从服务器获得响应。服务已暴露。
步骤 2:使用标签
Deployment 会自动为我们的 Pod 创建一个标签。使用 describe deployment
子命令,您可以看到该标签的名称(即*键*)
kubectl describe deployment
让我们使用此标签来查询 Pod 列表。我们将使用 kubectl get pods
命令,并使用-l作为参数,后跟标签值
kubectl get pods -l app=kubernetes-bootcamp
您可以使用相同的命令列出现有的服务
kubectl get services -l app=kubernetes-bootcamp
获取 Pod 的名称并将其存储在POD_NAME环境变量中
export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Pod 的名称:$POD_NAME"
要应用新标签,我们使用 label
子命令,后跟对象类型、对象名称和新标签
kubectl label pods "$POD_NAME" version=v1
这将向我们的 Pod 应用一个新标签(我们将应用程序版本固定到 Pod),我们可以使用 describe pod 命令检查它
kubectl describe pods "$POD_NAME"
我们在这里看到标签现在已附加到我们的 Pod。现在我们可以使用新标签查询 Pod 列表
kubectl get pods -l version=v1
我们看到了 Pod。
步骤 3:删除服务
要删除服务,您可以使用 delete service
子命令。标签也可以在这里使用
kubectl delete service -l app=kubernetes-bootcamp
确认服务已消失
kubectl get services
这确认我们的服务已被移除。要确认路由不再暴露,您可以curl先前暴露的 IP 和端口
curl http://"$(minikube ip):$NODE_PORT"
这证明应用程序不再可以从集群外部访问。您可以使用curl从 pod 内部
kubectl exec -ti $POD_NAME -- curl https://127.0.0.1:8080
确认应用仍在运行。我们在这里看到应用程序正在运行。这是因为 Deployment 正在管理应用程序。要关闭应用程序,您还需要删除 Deployment。
准备好后,请继续阅读 运行您的应用的多个实例。