diff --git a/content/zh/docs/concepts/services-networking/service.md b/content/zh/docs/concepts/services-networking/service.md index 5090d7d660ed0..37fdeaa6ea28c 100644 --- a/content/zh/docs/concepts/services-networking/service.md +++ b/content/zh/docs/concepts/services-networking/service.md @@ -10,12 +10,11 @@ weight: 10 --- Kubernetes Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。 Service 所针对的 Pods 集合通常是通过{{< glossary_tooltip text="选择算符" term_id="selector" >}}来确定的。 -要了解如何定义服务端点,请参阅[不带选择算符的服务](#services-without-selectors)。 +要了解定义服务端点的其他方法,请参阅[不带选择算符的服务](#services-without-selectors)。 上述配置创建一个名称为 "my-service" 的 Service 对象,它会将请求代理到使用 TCP 端口 9376,并且具有标签 `"app=MyApp"` 的 Pod 上。 + Kubernetes 为该服务分配一个 IP 地址(有时称为 "集群IP"),该 IP 地址由服务代理使用。 (请参见下面的 [VIP 和 Service 代理](#virtual-ips-and-service-proxies)). + 服务选择算符的控制器不断扫描与其选择器匹配的 Pod,然后将所有更新发布到也称为 “my-service” 的 Endpoint 对象。 @@ -206,7 +208,7 @@ Pod 中的端口定义是有名字的,你可以在服务的 `targetPort` 属 这为部署和发展服务提供了很大的灵活性。 例如,你可以更改 Pods 在新版本的后端软件中公开的端口号,而不会破坏客户端。 -服务的默认协议是TCP。 你还可以使用任何其他[受支持的协议](#protocol-support)。 +服务的默认协议是 TCP;你还可以使用任何其他[受支持的协议](#protocol-support)。 由于许多服务需要公开多个端口,因此 Kubernetes 在服务对象上支持多个端口定义。 每个端口定义可以具有相同的 `protocol`,也可以具有不同的协议。 @@ -222,7 +224,7 @@ For example: test environment you use your own databases. * You want to point your Service to a Service in a different {{< glossary_tooltip term_id="namespace" >}} or on another cluster. - * You are migrating a workload to Kubernetes. Whilst evaluating the approach, +* You are migrating a workload to Kubernetes. While evaluating the approach, you run only a proportion of your backends in Kubernetes. In any of these scenarios you can define a Service _without_ a Pod selector. @@ -287,8 +289,9 @@ because {{< glossary_tooltip term_id="kube-proxy" >}} doesn't support virtual IP as a destination. --> {{< note >}} -端点 IPs _必须不可以_ 是:本地回路(IPv4 的 `127.0.0.0/8`, IPv6 的 `::1/128`)或 -本地链接(IPv4 的 `169.254.0.0/16` 和 `224.0.0.0/24`,IPv6 的 `fe80::/64`)。 +端点 IPs _必须不可以_ 是:本地回路(IPv4 的 127.0.0.0/8, IPv6 的 ::1/128)或 +本地链接(IPv4 的 169.254.0.0/16 和 224.0.0.0/24,IPv6 的 fe80::/64)。 + 端点 IP 地址不能是其他 Kubernetes 服务的集群 IP,因为 {{< glossary_tooltip term_id ="kube-proxy">}} 不支持将虚拟 IP 作为目标。 {{< /note >}} @@ -307,7 +310,7 @@ selectors and uses DNS names instead. For more information, see the [ExternalName](#externalname) section later in this document. --> ExternalName Service 是 Service 的特例,它没有选择算符,但是使用 DNS 名称。 -有关更多信息,请参阅本文档后面的[`ExternalName`](#externalname)。 +有关更多信息,请参阅本文档后面的[ExternalName](#externalname)。 ### 应用程序协议 {#application-protocol} -{{< feature-state for_k8s_version="v1.19" state="beta" >}} - +{{< feature-state for_k8s_version="v1.20" state="stable" >}} `appProtocol` 字段提供了一种为每个 Service 端口指定应用协议的方式。 -此字段的取值会被映射到对应的 Endpoints 和 EndpointSlices 资源。 +此字段的取值会被映射到对应的 Endpoints 和 EndpointSlices 对象。 +该字段遵循标准的 Kubernetes 标签语法。 +其值可以是 [IANA 标准服务名称](http://www.iana.org/assignments/service-names)或以域名前缀的名称, +如 `mycompany.com/my-custom-protocol`。 -在 `ipvs` 模式下,kube-proxy监视Kubernetes服务和端点,调用 `netlink` 接口相应地创建 IPVS 规则, +在 `ipvs` 模式下,kube-proxy 监视 Kubernetes 服务和端点,调用 `netlink` 接口相应地创建 IPVS 规则, 并定期将 IPVS 规则与 Kubernetes 服务和端点同步。 该控制循环可确保IPVS 状态与所需状态匹配。访问服务时,IPVS 将流量定向到后端Pod之一。 @@ -511,25 +522,25 @@ IPVS代理模式基于类似于 iptables 模式的 netfilter 挂钩函数, 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。 与其他代理模式相比,IPVS 模式还支持更高的网络流量吞吐量。 -IPVS提供了更多选项来平衡后端Pod的流量。 这些是: +IPVS 提供了更多选项来平衡后端 Pod 的流量。 这些是: -- `rr`: round-robin -- `lc`: least connection (smallest number of open connections) -- `dh`: destination hashing -- `sh`: source hashing -- `sed`: shortest expected delay -- `nq`: never queue +* `rr`:轮替(Round-Robin) +* `lc`:最少链接(Least Connection),即打开链接数量最少者优先 +* `dh`:目标地址哈希(Destination Hashing) +* `sh`:源地址哈希(Source Hashing) +* `sed`:最短预期延迟(Shortest Expected Delay) +* `nq`:从不排队(Never Queue) {{< note >}} -要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS Linux 在节点上可用。 +要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS 在节点上可用。 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。 @@ -538,13 +549,13 @@ falls back to running in iptables proxy mode. @@ -667,7 +677,7 @@ variables: 简单的 `{SVCNAME}_SERVICE_HOST` 和 `{SVCNAME}_SERVICE_PORT` 变量。 这里 Service 的名称需大写,横线被转换成下划线。 -举个例子,一个名称为 `"redis-master"` 的 Service 暴露了 TCP 端口 6379, +举个例子,一个名称为 `redis-master` 的 Service 暴露了 TCP 端口 6379, 同时给它分配了 Cluster IP 地址 10.0.0.11,这个 Service 生成了如下环境变量: ```shell @@ -715,35 +725,35 @@ Services by their DNS name. 如果在整个集群中都启用了 DNS,则所有 Pod 都应该能够通过其 DNS 名称自动解析服务。 -例如,如果你在 Kubernetes 命名空间 `"my-ns"` 中有一个名为 `"my-service"` 的服务, -则控制平面和 DNS 服务共同为 `"my-service.my-ns"` 创建 DNS 记录。 -`"my-ns"` 命名空间中的 Pod 应该能够通过简单地对 `my-service` 进行名称查找来找到它 -(`"my-service.my-ns"` 也可以工作)。 +例如,如果你在 Kubernetes 命名空间 `my-ns` 中有一个名为 `my-service` 的服务, +则控制平面和 DNS 服务共同为 `my-service.my-ns` 创建 DNS 记录。 +`my-ns` 命名空间中的 Pod 应该能够通过简单地按名检索 `my-service` 来找到它 +(`my-service.my-ns` 也可以工作)。 其他命名空间中的 Pod 必须将名称限定为 `my-service.my-ns`。 这些名称将解析为为服务分配的集群 IP。 Kubernetes 还支持命名端口的 DNS SRV(服务)记录。 -如果 `"my-service.my-ns"` 服务具有名为 `"http"` 的端口,且协议设置为 TCP, +如果 `my-service.my-ns` 服务具有名为 `http` 的端口,且协议设置为 TCP, 则可以对 `_http._tcp.my-service.my-ns` 执行 DNS SRV 查询查询以发现该端口号, `"http"` 以及 IP 地址。 @@ -755,7 +765,7 @@ Kubernetes DNS 服务器是唯一的一种能够访问 `ExternalName` 类型的 ## Headless Services {#headless-services} Sometimes you don't need load-balancing and a single Service IP. In -this case, you can create what are termed “headless” Services, by explicitly +this case, you can create what are termed "headless" Services, by explicitly specifying `"None"` for the cluster IP (`.spec.clusterIP`). You can use a headless Service to interface with other service discovery mechanisms, @@ -784,12 +794,12 @@ DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。 For headless Services that define selectors, the endpoints controller creates `Endpoints` records in the API, and modifies the DNS configuration to return -records (addresses) that point directly to the `Pods` backing the Service. +records (addresses) that point directly to the `Pods` backing the `Service`. --> -### 带选择算符的服务 {#with-selectors} +### 带选择算符的服务 {#with-selectors} 对定义了选择算符的无头服务,Endpoint 控制器在 API 中创建了 Endpoints 记录, -并且修改 DNS 配置返回 A 记录(地址),通过这个地址直接到达 Service 的后端 Pod 上。 +并且修改 DNS 配置返回 A 记录(地址),通过这个地址直接到达 `Service` 的后端 Pod 上。 @@ -922,15 +931,17 @@ to configure environments that are not fully supported by Kubernetes, or even to just expose one or more nodes' IPs directly. Note that this Service is visible as `:spec.ports[*].nodePort` -and `.spec.clusterIP:spec.ports[*].port`. (If the `-nodeport-addresses` flag in kube-proxy is set, would be filtered NodeIP(s).) +and `.spec.clusterIP:spec.ports[*].port`. (If the `--nodeport-addresses` flag in kube-proxy is set, would be filtered NodeIP(s).) For example: --> -使用 NodePort 可以让你自由设置自己的负载均衡解决方案,配置 Kubernetes 不完全支持的环境, +使用 NodePort 可以让你自由设置自己的负载均衡解决方案, +配置 Kubernetes 不完全支持的环境, 甚至直接暴露一个或多个节点的 IP。 需要注意的是,Service 能够通过 `:spec.ports[*].nodePort` 和 -`spec.clusterIp:spec.ports[*].port` 而对外可见。 +`spec.clusterIp:spec.ports[*].port` 而对外可见 +(如果 kube-proxy 的 `--nodeport-addresses` 参数被设置了, 将被过滤 NodeIP。)。 例如: @@ -969,7 +980,7 @@ For example: 负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 `status.loadBalancer` 字段发布出去。 -实例: +实例: ```yaml apiVersion: v1 @@ -984,26 +995,18 @@ spec: port: 80 targetPort: 9376 clusterIP: 10.0.171.239 - loadBalancerIP: 78.11.24.19 type: LoadBalancer status: loadBalancer: ingress: - - ip: 146.148.47.155 + - ip: 192.0.2.127 ``` 来自外部负载均衡器的流量将直接重定向到后端 Pod 上,不过实际它们是如何工作的,这要依赖于云提供商。 -对于 LoadBalancer 类型的服务,当所定义的端口不止一个时,所有端口都必须 -使用相同的协议,并且其协议必须是 `TCP`、`UDP` 和 `SCTP` 之一。 - -{{< note >}} -如果你使用的是 SCTP,请参阅下面有关 `LoadBalancer` 服务类型的 -[注意事项](#caveat-sctp-loadbalancer-service-type)。 -{{< /note >}} +#### 混合协议类型的负载均衡器 + +{{< feature-state for_k8s_version="v1.20" state="alpha" >}} + +默认情况下,对于 LoadBalancer 类型的服务,当定义了多个端口时,所有 +端口必须具有相同的协议,并且该协议必须是受云提供商支持的协议。 + +如果为 kube-apiserver 启用了 `MixedProtocolLBService` 特性门控, +则当定义了多个端口时,允许使用不同的协议。 + + +{{< note >}} +可用于 LoadBalancer 类型服务的协议集仍然由云提供商决定。 +{{< /note >}} + +### 禁用负载均衡器节点端口分配 {#load-balancer-nodeport-allocation} + +{{< feature-state for_k8s_version="v1.20" state="alpha" >}} + +从 v1.20 版本开始, 你可以通过设置 `spec.allocateLoadBalancerNodePorts` 为 `false` +对类型为 LoadBalancer 的服务禁用节点端口分配。 +这仅适用于直接将流量路由到 Pod 而不是使用节点端口的负载均衡器实现。 +默认情况下,`spec.allocateLoadBalancerNodePorts` 为 `true`, +LoadBalancer 类型的服务继续分配节点端口。 +如果现有服务已被分配节点端口,将参数 `spec.allocateLoadBalancerNodePorts` 设置为 `false` 时, +这些服务上已分配置的节点端口不会被自动释放。 +你必须显式地在每个服务端口中删除 `nodePorts` 项以释放对应端口。 +你必须启用 `ServiceLBNodePortControl` 特性门控才能使用该字段。 -#### 内部负载均衡器 {#internal-load-balancer} +#### 内部负载均衡器 {#internal-load-balancer} 在混合环境中,有时有必要在同一(虚拟)网络地址块内路由来自服务的流量。 在水平分割 DNS 环境中,你需要两个服务才能将内部和外部流量都路由到你的端点(Endpoints)。 -你可以通过向服务添加以下注解之一来实现此目的。 -要添加的注解取决于你使用的云服务提供商。 + +如要设置内部负载均衡器,请根据你所使用的云运营商,为服务添加以下注解之一。 {{< tabs name="service_tabs" >}} {{% tab name="Default" %}} @@ -1207,7 +1254,7 @@ SSL, the ELB expects the Pod to authenticate itself over the encrypted connection, using a certificate. HTTP and HTTPS selects layer 7 proxying: the ELB terminates -the connection with the user, parse headers and inject the `X-Forwarded-For` +the connection with the user, parses headers, and injects the `X-Forwarded-For` header with the user's IP address (Pods only see the IP address of the ELB at the other end of its connection) when forwarding requests. @@ -1240,9 +1287,12 @@ In the above example, if the Service contained three ports, `80`, `443`, and `8443`, then `443` and `8443` would use the SSL certificate, but `80` would just be proxied HTTP. -From Kubernetes v1.9 onwards you can use [predefined AWS SSL policies](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html) with HTTPS or SSL listeners for your Services. +From Kubernetes v1.9 onwards you can use [predefined AWS SSL policies](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html) with HTTPS or SSL listeners for your Services. To see which policies are available for use, you can use the `aws` command line tool: --> +在上例中,如果服务包含 `80`、`443` 和 `8443` 三个端口, 那么 `443` 和 `8443` 将使用 SSL 证书, +而 `80` 端口将仅仅转发 HTTP 数据包。 + 从 Kubernetes v1.9 起可以使用 [预定义的 AWS SSL 策略](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html) 为你的服务使用 HTTPS 或 SSL 侦听器。 @@ -1292,44 +1342,6 @@ Since version 1.3.0, the use of this annotation applies to all ports proxied by and cannot be configured otherwise. --> 从 1.3.0 版开始,此注解的使用适用于 ELB 代理的所有端口,并且不能进行其他配置。 - - -### 外部 IP - -如果有一些外部 IP 地址能够路由到一个或多个集群节点,Kubernetes 服务可以在这些 -`externalIPs` 上暴露出来。 -通过外部 IP 进入集群的入站请求,如果指向的是服务的端口,会被路由到服务的末端之一。 -`externalIPs` 不受 Kubernets 管理;它们由集群管理员管理。 -在服务规约中,`externalIPs` 可以和 `ServiceTypes` 一起指定。 -在上面的例子中,客户端可以通过 "`80.11.12.10:80`" (`externalIP:port`) 访问 "`my-service`" -服务。 - -```yaml -kind: Service -apiVersion: v1 -metadata: - name: my-service -spec: - selector: - app: MyApp - ports: - - name: http - protocol: TCP - port: 80 - targetPort: 9376 - externalIPs: - - 80.11.12.10 -``` - -#### AWS 上负载均衡器支持 {#aws-nlb-support} +#### AWS 上网络负载均衡器支持 {#aws-nlb-support} {{< feature-state for_k8s_version="v1.15" state="beta" >}} @@ -1555,6 +1567,78 @@ in those modified security groups. 如果节点具有公共 IP 地址,请注意,非 NLB 流量也可以到达那些修改后的安全组中的所有实例。 {{< /note >}} + +#### 腾讯 Kubernetes 引擎(TKE)上的 CLB 注解 + +以下是在 TKE 上管理云负载均衡器的注解。 + +```yaml + metadata: + name: my-service + annotations: + # 绑定负载均衡器到指定的节点。 + service.kubernetes.io/qcloud-loadbalancer-backends-label: key in (value1, value2) + + # 为已有负载均衡器添加 ID。 + service.kubernetes.io/tke-existed-lbid:lb-6swtxxxx + + # 负载均衡器(LB)的自定义参数尚不支持修改 LB 类型。 + service.kubernetes.io/service.extensiveParameters: "" + + # 自定义负载均衡监听器。 + service.kubernetes.io/service.listenerParameters: "" + + # 指定负载均衡类型。 + # 可用参数: classic (Classic Cloud Load Balancer) 或 application (Application Cloud Load Balancer) + service.kubernetes.io/loadbalance-type: xxxxx + + # 指定公用网络带宽计费方法。 + # 可用参数: TRAFFIC_POSTPAID_BY_HOUR(bill-by-traffic) 和 BANDWIDTH_POSTPAID_BY_HOUR (bill-by-bandwidth). + service.kubernetes.io/qcloud-loadbalancer-internet-charge-type: xxxxxx + + # 指定带宽参数 (取值范围: [1,2000] Mbps). + service.kubernetes.io/qcloud-loadbalancer-internet-max-bandwidth-out: "10" + + # 当设置该注解时,负载平衡器将只注册正在运行 Pod 的节点, + # 否则所有节点将会被注册。 + service.kubernetes.io/local-svc-only-bind-node-with-pod: true +``` +{{< warning >}} +对于一些常见的协议,包括 HTTP 和 HTTPS, +你使用 ExternalName 可能会遇到问题。 +如果你使用 ExternalName,那么集群内客户端使用的主机名 +与 ExternalName 引用的名称不同。 + +对于使用主机名的协议,此差异可能会导致错误或意外响应。 +HTTP 请求将具有源服务器无法识别的 `Host:` 标头;TLS 服 +务器将无法提供与客户端连接的主机名匹配的证书。 +{{< /warning >}} + 你可以将 UDP 用于大多数服务。 对于 type=LoadBalancer 服务,对 UDP 的支持取决于提供此功能的云提供商。 + +### SCTP + +{{< feature-state for_k8s_version="v1.20" state="stable" >}} + +一旦你使用了支持 SCTP 流量的网络插件,你就可以使用 SCTP 于更多的服务。 +对于 type = LoadBalancer 的服务,SCTP 的支持取决于提供此设施的云供应商(多大数不支持)。 + + +#### 警告 {#caveat-sctp-overview} + +##### 支持多宿主 SCTP 关联 {#caveat-sctp-multihomed} + + +{{< warning >}} +支持多宿主SCTP关联要求 CNI 插件能够支持为一个 Pod 分配多个接口和IP地址。 + +用于多宿主 SCTP 关联的 NAT 在相应的内核模块中需要特殊的逻辑。 +{{< /warning >}} + + +##### Windows {#caveat-sctp-windows-os} + +{{< note >}} +基于 Windows 的节点不支持 SCTP。 +{{< /note >}} + + +##### 用户空间 kube-proxy {#caveat-sctp-kube-proxy-userspace} + +{{< warning >}} +当 kube-proxy 处于用户空间模式时,它不支持 SCTP 关联的管理。 +{{< /warning >}} + ### HTTP -接下来是来自客户端的数据。 - -### SCTP - -{{< feature-state for_k8s_version="v1.19" state="beta" >}} - - -Kubernetes 支持 SCTP 作为 Service、Endpoint、EndpointSlice, NetworkPolicy -和 Pod 定义中的 `protocol` 值。 -作为一种 Beta 特性,此功能默认是启用的。集群管理员需要在 API 服务器上使用 -`--feature-gates=SCTPSupport=false,...` 来关闭 -`SCTPSupport` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/) -来在集群级别禁用 SCTP。 - -启用特性门控后,你可以将 Service、Endpoints、EndpointSlice、NetworkPolicy 或 -Pod 的 `protocol` 字段设置为 `SCTP`。 -Kubernetes 相应地为 SCTP 关联设置网络,就像为 TCP 连接所做的一样。 - - - -#### 警告 {#caveat-sctp-overview} - -##### 支持多宿主SCTP关联 {#caveat-sctp-multihomed} - - -{{< warning >}} -对多宿主 SCTP 关联的支持要求 CNI 插件可以支持将多个接口和 IP 地址分配给 Pod。 -用于多宿主 SCTP 关联的 NAT 在相应的内核模块中需要特殊的逻辑。 -{{< /warning >}} - - -##### Service 类型为 LoadBalancer 的服务 {#caveat-sctp-loadbalancer-service-type} - -{{< warning >}} -如果云提供商的负载平衡器实现支持将 SCTP 作为协议,则只能使用 `type` LoadBalancer 加上 -`protocol` SCTP 创建服务。否则,服务创建请求将被拒绝。 -当前的云负载平衡器提供商(Azure、AWS、CloudStack、GCE、OpenStack)都缺乏对 SCTP 的支持。 -{{< /warning >}} - -##### Windows {#caveat-sctp-windows-os} - - -{{< warning >}} -基于 Windows 的节点不支持 SCTP。 -{{< /warning >}} - - -##### 用户空间 kube-proxy {#caveat-sctp-kube-proxy-userspace} - -{{< warning >}} - -当 kube-proxy 处于用户空间模式时,它不支持 SCTP 关联的管理。 -{{< /warning >}} +上述是来自客户端的数据。 ## {{% heading "whatsnext" %}}