diff --git a/.vuepress/config.js b/.vuepress/config.js index 2f43884..2ae0f36 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -236,7 +236,8 @@ module.exports = { title: '服务发现、负载均衡、网络', collapsable: false, children: [ - // 'k8s-intermediate/service/service', + 'k8s-intermediate/service/service', + 'k8s-intermediate/service/service-details', // 'k8s-intermediate/service/dns', // 'k8s-intermediate/service/connecting', 'k8s-intermediate/service/ingress', diff --git a/.vuepress/public/kuboard.rp b/.vuepress/public/kuboard.rp index f5eae0d..1ef4083 100644 Binary files a/.vuepress/public/kuboard.rp and b/.vuepress/public/kuboard.rp differ diff --git a/learning/README.md b/learning/README.md index e943a83..9e4b36b 100644 --- a/learning/README.md +++ b/learning/README.md @@ -41,7 +41,8 @@ description: Kubernetes 免费中文教程 * [控制器 - Job](/learning/k8s-intermediate/workload/wl-job/) * [控制器 - CronJob](/learning/k8s-intermediate/workload/wl-cronjob/) * 服务发现、负载均衡、网络 - * [Service](/learning/k8s-intermediate/service/service.html) + * [Service 概述](/learning/k8s-intermediate/service/service.html) + * [Service 详细描述](/learning/k8s-intermediate/service/service-details.html) * [Service/Pod 的 DNS](/learning/k8s-intermediate/service/dns.html) * [Service 连接应用程序](/learning/k8s-intermediate/service/connecting.html) * [Ingress 通过互联网访问您的应用](/learning/k8s-intermediate/service/ingress.html) diff --git a/learning/k8s-intermediate/service/service-details.md b/learning/k8s-intermediate/service/service-details.md new file mode 100644 index 0000000..9e1de53 --- /dev/null +++ b/learning/k8s-intermediate/service/service-details.md @@ -0,0 +1,111 @@ +--- +layout: LearningLayout +description: 本文介绍了 Kubernetes 中服务发现的机制,以及如何使用服务发现 +--- + +# Service 详细描述 + +参考文档:Kubernetes 官网文档:[Service](https://kubernetes.io/docs/concepts/services-networking/service/) + +## 创建 Service + +Kubernetes Servies 是一个 RESTFul 接口对象,可通过 yaml 文件创建。 + +例如,假设您有一组 Pod: +* 每个 Pod 都监听 9376 TCP 端口 +* 每个 Pod 都有标签 app=MyApp + +``` yaml +apiVersion: v1 +kind: Service +metadata: + name: my-service +spec: + selector: + app: MyApp + ports: + - protocol: TCP + port: 80 + targetPort: 9376 +``` + +上述 YAML 文件可用来创建一个 Service: +* 名字为 `my-service` +* 目标端口未 TCP 9376 +* 选取所有包含标签 app=MyApp 的 Pod + +关于 Service,您还需要了解: + +* Kubernetes 将为该 Service 分配一个 IP 地址(ClusterIP 或 集群内 IP),供 Service Proxy 使用(参考[虚拟 IP 和 Service proxy](#虚拟-ip-和-service-proxy)) +* Kubernetes 将不断扫描符合该 selector 的 Pod,并将最新的结果更新到与 Service 同名 `my-service` 的 Endpoint 对象中。 + ::: tip + Service 从自己的 IP 地址和 `port` 端口接收请求,并将请求映射到符合条件的 Pod 的 `targetPort`。为了方便,默认 `targetPort` 的取值 与 `port` 字段相同 + ::: +* Pod 的定义中,Port 可能被赋予了一个名字,您可以在 Service 的 `targetPort` 字段引用这些名字,而不是直接写端口号。这种做法可以使得您在将来修改后端程序监听的端口号,而无需影响到前端程序。 +* Service 的默认传输协议是 TCP,您也可以使用其他 [支持的传输协议](#支持的传输协议)。 +* Kubernetes Service 中,可以定义多个端口,不同的端口可以使用相同或不同的传输协议。 + +## 创建 Service(无 label selector) + +Service 通常用于提供对 Kubernetes Pod 的访问,但是您也可以将其用于任何其他形式的后端。例如: + +* 您想要在生产环境中使用一个 Kubernetes 外部的数据库集群,在测试环境中使用 Kubernetes 内部的 数据库 +* 您想要将 Service 指向另一个名称空间中的 Service,或者另一个 Kubernetes 集群中的 Service +* 您正在将您的程序迁移到 Kubernetes,但是根据您的迁移路径,您只将一部分后端程序运行在 Kubernetes 中 + +在上述这些情况下,您可以定义一个没有 Pod Selector 的 Service。例如: + +``` yaml +apiVersion: v1 +kind: Service +metadata: + name: my-service +spec: + ports: + - protocol: TCP + port: 80 + targetPort: 9376 +``` + +因为该 Service 没有 selector,相应的 Endpoint 对象就无法自动创建。您可以手动创建一个 Endpoint 对象,以便将该 Service 映射到后端服务真实的 IP 地址和端口: + +``` yaml +apiVersion: v1 +kind: Endpoints +metadata: + name: my-service +subsets: + - addresses: + - ip: 192.0.2.42 + ports: + - port: 9376 +``` + +::: tip +* Endpoint 中的 IP 地址不可以是 loopback(127.0.0.0/8 IPv4 或 ::1/128 IPv6),或 link-local(169.254.0.0/16 IPv4、224.0.0.0/24 IPv4 或 fe80::/64 IPv6) +* Endpoint 中的 IP 地址不可以是集群中其他 Service 的 ClusterIP +::: + +对于 Service 的访问者来说,Service 是否有 label selector 都是一样的。在上述例子中,Service 将请求路由到 Endpoint 192.0.2.42:9376 (TCP)。 + +ExternalName Service 是一类特殊的没有 label selector 的 Service,该类 Service 使用 DNS 名字。参考 [ExternalName](#externalname) + + +An ExternalName Service is a special case of Service that does not have selectors and uses DNS names instead. For more information, see the ExternalName section later in this document + +## 虚拟 IP 和 Service proxy + +正在撰写,最后更新时间:2019年9月17日 22:55 + +## 支持的传输协议 + + +## Service 类型 + +### ClusterIP + +### NodePort + +### LoadBalancer + +### ExternalName diff --git a/learning/k8s-intermediate/service/service.assets/image-20190917210501081.png b/learning/k8s-intermediate/service/service.assets/image-20190917210501081.png new file mode 100644 index 0000000..0d5a703 Binary files /dev/null and b/learning/k8s-intermediate/service/service.assets/image-20190917210501081.png differ diff --git a/learning/k8s-intermediate/service/service.assets/image-20190917213132221.png b/learning/k8s-intermediate/service/service.assets/image-20190917213132221.png new file mode 100644 index 0000000..017ba78 Binary files /dev/null and b/learning/k8s-intermediate/service/service.assets/image-20190917213132221.png differ diff --git a/learning/k8s-intermediate/service/service.assets/image-20190917213206652.png b/learning/k8s-intermediate/service/service.assets/image-20190917213206652.png new file mode 100644 index 0000000..4b5f33f Binary files /dev/null and b/learning/k8s-intermediate/service/service.assets/image-20190917213206652.png differ diff --git a/learning/k8s-intermediate/service/service.md b/learning/k8s-intermediate/service/service.md index dc6d4b1..8ed36b0 100644 --- a/learning/k8s-intermediate/service/service.md +++ b/learning/k8s-intermediate/service/service.md @@ -3,6 +3,55 @@ layout: LearningLayout description: 本文介绍了 Kubernetes 中服务发现的机制,以及如何使用服务发现 --- -# Service +# Service 概述 -正在撰写... +参考文档:Kubernetes 官网文档:[Service](https://kubernetes.io/docs/concepts/services-networking/service/) + +## 为何需要 Service + +Kubernetes 中 Pod 是随时可以消亡的(节点故障、容器内应用程序错误等原因)。如果使用 [Deployment](learning/k8s-intermediate/workload/wl-deployment/) 运行您的应用程序,Deployment 将会在 Pod 消亡后再创建一个新的 Pod 以维持所需要的副本数。每一个 Pod 有自己的 IP 地址,然而,对于 Deployment 而言,对应 Pod 集合是动态变化的。 + +这个现象导致了如下问题: +* 如果某些 Pod(假设是 'backends')为另外一些 Pod(假设是 'frontends')提供接口,在 'backends' 中的 Pod 集合不断变化(IP 地址也跟着变化)的情况下,'frontends' 中的 Pod 如何才能知道应该将请求发送到哪个 IP 地址? + +Service 存在的意义,就是为了解决这个问题。 + +## Service + +Kubernetes 中 Service 是一个 API 对象,通过 kubectl + YAML 或者 Kuboard,定义一个 Service,可以将符合 Service 指定条件的 Pod 作为可通过网络访问的服务提供给服务调用者。 + +Service 是 Kubernetes 中的一种服务发现机制: +* Pod 有自己的 IP 地址 +* Service 被赋予一个唯一的 dns name +* Service 通过 label selector 选定一组 Pod +* Service 实现负载均衡,可将请求均衡分发到选定这一组 Pod 中 + +例如,假设有一个无状态的图像处理后端程序运行了 3 个 Pod 副本。这些副本是相互可替代的(前端程序调用其中任何一个都可以)。在后端程序的副本集中的 Pod 经常变化(销毁、重建、扩容、缩容等)的情况下,前端程序不应该关注这些变化。 + +Kubernetes 通过引入 Service 的概念,将前端与后端解耦。 + +## 在 Kuboard 中使用 Service + +从 Kuboard 工作负载编辑器的视角来看,Service 与其他重要的 Kubernetes 对象之间的关系如下图所示: + +

+ +

+ +图中,Service 先连线到 Controller,Controller 在连线到容器组,这种表示方式只是概念上的,期望用户在使用 Kubernetes 的时候总是通过 Controller 创建 Pod,然后再通过 Service 暴露为网络服务,通过 Ingress 对集群外提供互联网访问。 + +事实上,Service 与 Controller 并没有直接联系,Service 通过 label selector 选择符合条件的 Pod,并将选中的 Pod 作为网络服务的提供者。从这个意义上来讲,您可以有很多中方式去定义 Service 的 label selector,然而,最佳的实践是,在 Service 中使用与 Controller 中相同的 label selector。如上图所示。 + +::: tip +使用 Kubernetes 的最佳实践: +* Service 与 Controller 同名 +* Service 与 Controller 使用相同的 label selector + +在 Kuboard 中创建工作负载时,工作负载的名字(服务名称字段)将作为 Deployment(StatefulSet/DaemonSet)的名字,也将作为 Service、Ingress 的名字 +::: + +在 Kuboard 工作负载编辑器中,Service 如下图所示: + +![image-20190917213132221](./service.assets/image-20190917213132221.png) +... +![image-20190917213206652](./service.assets/image-20190917213206652.png) diff --git a/overview/README.md b/overview/README.md index 0e8430b..8f5f76f 100644 --- a/overview/README.md +++ b/overview/README.md @@ -133,7 +133,8 @@ Kuboard 为 Kubernetes 初学者设计了如下学习路径: * [控制器 - Job](/learning/k8s-intermediate/workload/wl-job/) * [控制器 - CronJob](/learning/k8s-intermediate/workload/wl-cronjob/) * 服务发现、负载均衡、网络 - * [Service](/learning/k8s-intermediate/service/service.html) + * [Service 概述](/learning/k8s-intermediate/service/service.html) + * [Service 详细描述](/learning/k8s-intermediate/service/service-details.html) * [Service/Pod 的 DNS](/learning/k8s-intermediate/service/dns.html) * [Service 连接应用程序](/learning/k8s-intermediate/service/connecting.html) * [Ingress 通过互联网访问您的应用](/learning/k8s-intermediate/service/ingress.html)