diff --git a/content/zh-cn/docs/tutorials/kubernetes-basics/expose/expose-intro.html b/content/zh-cn/docs/tutorials/kubernetes-basics/expose/expose-intro.html index 99e98c5857..dfa9ed5ca4 100644 --- a/content/zh-cn/docs/tutorials/kubernetes-basics/expose/expose-intro.html +++ b/content/zh-cn/docs/tutorials/kubernetes-basics/expose/expose-intro.html @@ -1,78 +1,124 @@ --- - title: 使用 Service 暴露你的应用 weight: 10 +description: |- + 了解 Kubernetes 中的 Service。 + 理解标签和选择算符如何关联到 Service。 + 在 Kubernetes 集群外暴露应用。 --- + + - -
- -

目标

+ +

目标

    - - - +
  • 了解 Kubernetes 中的 Service
  • -
  • 了解 标签(Label) 和 标签选择器(Label Selector) 对象如何与 Service 关联
  • -
  • 在 Kubernetes 集群外用 Service 暴露应用
  • +
  • 了解标签(Label)和选择算符(Selector)如何与 Service 关联
  • +
  • 在 Kubernetes 集群外用 Service 暴露应用
- -

Kubernetes Service 总览

+ +

Kubernetes Service 总览

- -

Kubernetes Pod 是转瞬即逝的。 Pod 实际上拥有 生命周期。 当一个工作 Node 挂掉后, 在 Node 上运行的 Pod 也会消亡。 ReplicaSet 会自动地通过创建新的 Pod 驱动集群回到目标状态,以保证应用程序正常运行。 换一个例子,考虑一个具有3个副本数的用作图像处理的后端程序。这些副本是可替换的; 前端系统不应该关心后端副本,即使 Pod 丢失或重新创建。也就是说,Kubernetes 集群中的每个 Pod (即使是在同一个 Node 上的 Pod )都有一个唯一的 IP 地址,因此需要一种方法自动协调 Pod 之间的变更,以便应用程序保持运行。

+ + +

Kubernetes Pod 是转瞬即逝的。 Pod 拥有 生命周期。 + 当一个工作节点挂掉后, 在节点上运行的 Pod 也会消亡。 ReplicaSet 会自动地通过创建新的 Pod 驱动集群回到目标状态,以保证应用正常运行。 + 换一个例子,考虑一个具有 3 个副本的用作图像处理的后端程序。 + 这些副本是可替换的。前端系统不应该关心后端副本,即使某个 Pod 丢失或被重新创建。 + 此外,Kubernetes 集群中的每个 Pod 都有一个唯一的 IP 地址,即使是在同一个 Node 上的 Pod 也是如此, + 因此需要一种方法来自动协调 Pod 之间的变化,以便应用保持运行。

- -

Kubernetes 中的服务(Service)是一种抽象概念,它定义了 Pod 的逻辑集和访问 Pod 的协议。Service 使从属 Pod 之间的松耦合成为可能。 和其他 Kubernetes 对象一样, Service 用 YAML (更推荐) 或者 JSON 来定义. Service 下的一组 Pod 通常由 LabelSelector (请参阅下面的说明为什么你可能想要一个 spec 中不包含selector的服务)来标记。

+ +

Kubernetes 中的服务(Service)是一种抽象概念,它定义了 Pod 的逻辑集和访问 Pod 的协议。 + Service 使从属 Pod 之间的松耦合成为可能。 + 和所有 Kubernetes 对象清单一样, Service 用 YAML 或者 JSON 来定义。 + Service 下的一组 Pod 通常由一个 标签选择算符 来标记 + (请参阅下面的说明为什么你可能想要一个 spec 中不包含 selector 的 Service)。

- -

尽管每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service ,这些 IP 不会暴露在集群外部。Service 允许你的应用程序接收流量。Service 也可以用在 ServiceSpec 标记type的方式暴露

+ +

尽管每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service,这些 IP 不会被公开到集群外部。 + Service 允许你的应用接收流量。 + 通过设置 Service 的 spec 中的 type,你可以用不同的方式公开 Service:

    - - - - -
  • ClusterIP (默认) - 在集群的内部 IP 上公开 Service 。这种类型使得 Service 只能从集群内访问。
  • + +
  • ClusterIP(默认)- 在集群的内部 IP 上公开 Service。这种类型使得 Service 只能从集群内访问。
  • NodePort - 使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service 。使用<NodeIP>:<NodePort> 从集群外部访问 Service。是 ClusterIP 的超集。
  • -
  • LoadBalancer - 在当前云中创建一个外部负载均衡器(如果支持的话),并为 Service 分配一个固定的外部IP。是 NodePort 的超集。
  • -
  • ExternalName - 通过返回带有该名称的 CNAME 记录,使用任意名称(由 spec 中的externalName指定)公开 Service。不使用代理。这种类型需要kube-dns的v1.7或更高版本。
  • +
  • LoadBalancer - 在当前云中创建一个外部负载均衡器(如果支持的话),并为 Service 分配一个固定的外部IP。是 NodePort 的超集。
  • +
  • ExternalName - 将 Service 映射到 externalName 字段的内容(例如 foo.bar.example.com),通过返回带有该名称的 CNAME 记录实现。不设置任何类型的代理。这种类型需要 kube-dns 的 v1.7 或更高版本,或者 CoreDNS 的 0.8 或更高版本。
- -

更多关于不同 Service 类型的信息可以在使用源 IP 教程。 也请参阅 连接应用程序和 Service

- -

另外,需要注意的是有一些 Service 的用例没有在 spec 中定义selector。 一个没有selector创建的 Service 也不会创建相应的端点对象。这允许用户手动将服务映射到特定的端点。没有 selector 的另一种可能是你严格使用type: ExternalName来标记。

+ +

关于不同 Service 类型的更多信息可以在使用源 IP 教程找到。 + 也请参阅 使用 Service 连接到应用

+ +

另外,需要注意的是有一些 Service 的用例不需要在 spec 中定义 selector。 + 一个创建时未设置 selector 的 Service 也不会创建相应的 Endpoint 对象。 + 这允许用户手动将 Service 映射到特定的端点。 + 没有 selector 的另一种可能是你在严格使用 type: ExternalName 服务。

- -

总结

+ +

总结

    - - - +
  • 将 Pod 暴露给外部通信
  • 跨多个 Pod 的负载均衡
  • -
  • 使用标签(Label)
  • +
  • 使用标签(Label)
- -

Kubernetes 的 Service 是一个抽象层,它定义了一组 Pod 的逻辑集,并为这些 Pod 支持外部流量暴露、负载平衡和服务发现。

+ +

Kubernetes 的 Service 是一个抽象层,它定义了一组 Pod 的逻辑集,并为这些 Pod 支持外部流量暴露、负载平衡和服务发现。

@@ -80,38 +126,36 @@ weight: 10
+

Service 和 Label

-

-
-
- -
-
- -

Service 通过一组 Pod 路由通信。Service 是一种抽象,它允许 Pod 死亡并在 Kubernetes 中复制,而不会影响应用程序。在依赖的 Pod (如应用程序中的前端和后端组件)之间进行发现和路由是由Kubernetes Service 处理的。

- -

Service 匹配一组 Pod 是使用 标签(Label)和选择器(Selector), 它们是允许对 Kubernetes 中的对象进行逻辑操作的一种分组原语。标签(Label)是附加在对象上的键/值对,可以以多种方式使用:

+ +

Service 为一组 Pod 提供流量路由。Service 是一种抽象,允许 Kubernetes 中的 Pod 死亡和复制,而不会影响应用。 + 在依赖的 Pod(如应用中的前端和后端组件)之间进行发现和路由是由 Kubernetes Service 处理的。

+ +

Service 通过标签和选择算符来匹配一组 Pod, + 它们是允许对 Kubernetes 中的对象进行逻辑操作的一种分组原语。 + 标签是附加在对象上的键/值对,可以以多种方式使用:

    - - - -
  • 指定用于开发,测试和生产的对象
  • -
  • 嵌入版本标签
  • -
  • 使用 Label 将对象进行分类
  • + +
  • 指定用于开发、测试和生产的对象
  • +
  • 嵌入版本标记
  • +
  • 使用标记将对象分类
+
-
-
-
- -

你也可以在创建 Deployment 的同时用 --expose创建一个 Service 。

-
-

@@ -124,17 +168,182 @@ weight: 10
- -

标签(Label)可以在创建时或之后附加到对象上。他们可以随时被修改。现在使用 Service 发布我们的应用程序并添加一些 Label 。

+ +

标签可以在对象创建时或之后附加到对象上。它们可以随时被修改。现在使用 Service 发布我们的应用并添加一些标签。


- - 开始交互式教程 + +

创建新 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

+ +

我们现在有一个运行中的 Service 名为 kubernetes-bootcamp。 + 这里我们看到 Service 收到了一个唯一的集群内 IP(cluster-IP),一个内部端口和一个外部 IP + (external-IP)(Node 的 IP)。

+

要得到外部打开的端口号(对于 type: NodePort 的服务),我们需要运行 describe service 子命令:

+

kubectl describe services/kubernetes-bootcamp

+ +

创建一个名为 NODE_PORT 的环境变量,它的值为所分配的 Node 端口:

+

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
+ echo "NODE_PORT=$NODE_PORT"

+ +

现在我们可以使用 curl、Node 的 IP 地址和对外暴露的端口,来测试应用是否已经被公开到了集群外部:

+

curl http://"$(minikube ip):$NODE_PORT"

+ + {{< note >}}

如果你正在使用 Docker Desktop 作为容器驱动来运行 minikube, 需要使用 minikube tunnel。 + 这是因为 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

+ {{< /note >}} +

然后我们就会收到服务器的响应。Service 已经被暴露。

+ +
+
+ +

第二步:使用标签

+
+ +

Deployment 自动给我们的 Pod 创建了一个标签。通过 describe deployment 子命令你可以看到那个标签的名称(对应 key):

+

kubectl describe deployment

+ +

让我们使用这个标签来查询 Pod 列表。我们将使用 kubectl get pods 命令和 -l 参数,后面给出标签值:

+

kubectl get pods -l app=kubernetes-bootcamp

+ +

你可以用同样的方法列出现有的 Service:

+

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 "Name of the Pod: $POD_NAME"

+ +

要应用一个新的标签,我们使用 label 子命令,接着是对象类型、对象名称和新的标签:

+

kubectl label pods "$POD_NAME" version=v1

+ +

这将会在我们的 Pod 上应用一个新标签(我们把应用版本锁定到 Pod 上),然后我们可以通过 describe pods 命令检查它:

+

kubectl describe pods "$POD_NAME"

+ +

我们可以看到现在标签已经被附加到我们的 Pod 上。我们可以通过新的标签来查询 Pod 列表:

+

kubectl get pods -l version=v1

+ +

我们看到了对应的 Pod。

+
+
+ +
+
+ +

删除一个 Service

+ +

要删除一个 Service 你可以使用 delete service 子命令。这里也可以使用标签:

+

kubectl delete service -l app=kubernetes-bootcamp

+ +

确认对应的 Service 已经消失:

+

kubectl get services

+ +

这里确认了我们的 Service 已经被删除。要确认路由已经不再被公开,你可以 curl 之前公开的 IP 和端口:

+

curl http://"$(minikube ip):$NODE_PORT"

+ +

这证明了集群外部已经不再可以访问应用。 + 你可以通过在 Pod 内部运行 curl 确认应用仍在运行:

+

kubectl exec -ti $POD_NAME -- curl http://localhost:8080

+ +

这里我们看到应用是运行状态。这是因为 Deployment 正在管理应用。 + 要关闭应用,你还需要删除 Deployment。

+
+
+
+ +

+ 准备好之后,继续学习运行应用的多个实例。 +

+ +
+ +