Switch language name 'zh' to 'zh-cn'
This is the first step to rename 'zh' to 'zh-cn'. There are several reasons why we rename the language name.
- The upstream docsy theme changed the language name, leading to many warnings during site build;
The side-effect is that the i18n strings are no longer working.
- We believe renaming the language is the right thing to do, because this move can make room for other variants of Chinese language, such as 'zh-tw', 'zh-sg' etc.
There would be several follow-ups to this PR, such as fixing the intra-site links, adding redirects etc.
We will lock up changes to zh/zh-cn pages for the moment, until this one gets in.
This PR is based on commit cdad0a7342.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "服务、负载均衡和联网"
|
||||
weight: 60
|
||||
description: Kubernetes 网络背后的概念和资源。
|
||||
---
|
||||
|
||||
<!--
|
||||
## The Kubernetes network model
|
||||
|
||||
Every [`Pod`](/docs/concepts/workloads/pods/) gets its own IP address.
|
||||
This means you do not need to explicitly create links between `Pods` and you
|
||||
almost never need to deal with mapping container ports to host ports.
|
||||
This creates a clean, backwards-compatible model where `Pods` can be treated
|
||||
much like VMs or physical hosts from the perspectives of port allocation,
|
||||
naming, service discovery, [load balancing](/docs/concepts/services-networking/ingress/#load-balancing), application configuration,
|
||||
and migration.
|
||||
|
||||
Kubernetes imposes the following fundamental requirements on any networking
|
||||
implementation (barring any intentional network segmentation policies):
|
||||
|
||||
* pods on a [node](/docs/concepts/architecture/nodes/) can communicate with all pods on all nodes without NAT
|
||||
* agents on a node (e.g. system daemons, kubelet) can communicate with all
|
||||
pods on that node
|
||||
|
||||
Note: For those platforms that support `Pods` running in the host network (e.g.
|
||||
Linux):
|
||||
|
||||
* pods in the host network of a node can communicate with all pods on all
|
||||
nodes without NAT
|
||||
-->
|
||||
## Kubernetes 网络模型 {#the-kubernetes-network-model}
|
||||
|
||||
每一个 [`Pod`](/zh/docs/concepts/workloads/pods/) 都有它自己的IP地址,
|
||||
这就意味着你不需要显式地在 `Pod` 之间创建链接, 你几乎不需要处理容器端口到主机端口之间的映射。
|
||||
这将形成一个干净的、向后兼容的模型;在这个模型里,从端口分配、命名、服务发现、
|
||||
[负载均衡](/zh/docs/concepts/services-networking/ingress/#load-balancing)、应用配置和迁移的角度来看,
|
||||
`Pod` 可以被视作虚拟机或者物理主机。
|
||||
|
||||
Kubernetes 强制要求所有网络设施都满足以下基本要求(从而排除了有意隔离网络的策略):
|
||||
|
||||
* [节点](/zh/docs/concepts/architecture/nodes/)上的 Pod 可以不通过 NAT 和其他任何节点上的 Pod 通信
|
||||
* 节点上的代理(比如:系统守护进程、kubelet)可以和节点上的所有 Pod 通信
|
||||
|
||||
备注:对于支持在主机网络中运行 `Pod` 的平台(比如:Linux):
|
||||
|
||||
* 运行在节点主机网络里的 Pod 可以不通过 NAT 和所有节点上的 Pod 通信
|
||||
|
||||
<!--
|
||||
This model is not only less complex overall, but it is principally compatible
|
||||
with the desire for Kubernetes to enable low-friction porting of apps from VMs
|
||||
to containers. If your job previously ran in a VM, your VM had an IP and could
|
||||
talk to other VMs in your project. This is the same basic model.
|
||||
|
||||
Kubernetes IP addresses exist at the `Pod` scope - containers within a `Pod`
|
||||
share their network namespaces - including their IP address and MAC address.
|
||||
This means that containers within a `Pod` can all reach each other's ports on
|
||||
`localhost`. This also means that containers within a `Pod` must coordinate port
|
||||
usage, but this is no different from processes in a VM. This is called the
|
||||
"IP-per-pod" model.
|
||||
-->
|
||||
这个模型不仅不复杂,而且还和 Kubernetes 的实现从虚拟机向容器平滑迁移的初衷相符,
|
||||
如果你的任务开始是在虚拟机中运行的,你的虚拟机有一个 IP,
|
||||
可以和项目中其他虚拟机通信。这里的模型是基本相同的。
|
||||
|
||||
Kubernetes 的 IP 地址存在于 `Pod` 范围内 - 容器共享它们的网络命名空间 - 包括它们的 IP 地址和 MAC 地址。
|
||||
这就意味着 `Pod` 内的容器都可以通过 `localhost` 到达对方端口。
|
||||
这也意味着 `Pod` 内的容器需要相互协调端口的使用,但是这和虚拟机中的进程似乎没有什么不同,
|
||||
这也被称为“一个 Pod 一个 IP”模型。
|
||||
|
||||
<!--
|
||||
How this is implemented is a detail of the particular container runtime in use.
|
||||
|
||||
It is possible to request ports on the `Node` itself which forward to your `Pod`
|
||||
(called host ports), but this is a very niche operation. How that forwarding is
|
||||
implemented is also a detail of the container runtime. The `Pod` itself is
|
||||
blind to the existence or non-existence of host ports.
|
||||
-->
|
||||
如何实现以上需求是所使用的特定容器运行时的细节。
|
||||
|
||||
也可以在 `Node` 本身请求端口,并用这类端口转发到你的 `Pod`(称之为主机端口),
|
||||
但这是一个很特殊的操作。转发方式如何实现也是容器运行时的细节。
|
||||
`Pod` 自己并不知道这些主机端口的存在。
|
||||
|
||||
<!--
|
||||
Kubernetes networking addresses four concerns:
|
||||
- Containers within a Pod [use networking to communicate](/docs/concepts/services-networking/dns-pod-service/) via loopback.
|
||||
- Cluster networking provides communication between different Pods.
|
||||
- The [Service resource](/docs/concepts/services-networking/service/) lets you [expose an application running in Pods](/docs/concepts/services-networking/connect-applications-service/) to be reachable from outside your cluster.
|
||||
- You can also use Services to [publish services only for consumption inside your cluster](/docs/concepts/services-networking/service-traffic-policy/).
|
||||
-->
|
||||
|
||||
Kubernetes 网络解决四方面的问题:
|
||||
- 一个 Pod 中的容器之间[通过本地回路(loopback)通信](/zh/docs/concepts/services-networking/dns-pod-service/)。
|
||||
- 集群网络在不同 pod 之间提供通信。
|
||||
- [Service 资源](/zh/docs/concepts/services-networking/service/)允许你
|
||||
[对外暴露 Pods 中运行的应用程序](/zh/docs/concepts/services-networking/connect-applications-service/),
|
||||
以支持来自于集群外部的访问。
|
||||
- 可以使用 Services 来[发布仅供集群内部使用的服务](/zh/docs/concepts/services-networking/service-traffic-policy/)。
|
||||
@@ -0,0 +1,625 @@
|
||||
---
|
||||
title: 使用 Service 连接到应用
|
||||
content_type: concept
|
||||
weight: 30
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
<!--
|
||||
## The Kubernetes model for connecting containers
|
||||
|
||||
Now that you have a continuously running, replicated application you can expose it on a network.
|
||||
|
||||
Kubernetes assumes that pods can communicate with other pods, regardless of which host they land on. Kubernetes gives every pod its own cluster-private IP address, so you do not need to explicitly create links between pods or map container ports to host ports. This means that containers within a Pod can all reach each other's ports on localhost, and all pods in a cluster can see each other without NAT. The rest of this document elaborates on how you can run reliable services on such a networking model.
|
||||
|
||||
This guide uses a simple nginx server to demonstrate proof of concept.
|
||||
-->
|
||||
|
||||
## Kubernetes 连接容器的模型
|
||||
|
||||
既然有了一个持续运行、可复制的应用,我们就能够将它暴露到网络上。
|
||||
|
||||
Kubernetes 假设 Pod 可与其它 Pod 通信,不管它们在哪个主机上。
|
||||
Kubernetes 给每一个 Pod 分配一个集群私有 IP 地址,所以没必要在
|
||||
Pod 与 Pod 之间创建连接或将容器的端口映射到主机端口。
|
||||
这意味着同一个 Pod 内的所有容器能通过 localhost 上的端口互相连通,集群中的所有 Pod
|
||||
也不需要通过 NAT 转换就能够互相看到。
|
||||
本文档的剩余部分详述如何在上述网络模型之上运行可靠的服务。
|
||||
|
||||
本指南使用一个简单的 Nginx 服务器来演示概念验证原型。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Exposing pods to the cluster
|
||||
|
||||
We did this in a previous example, but let's do it once again and focus on the networking perspective.
|
||||
Create an nginx Pod, and note that it has a container port specification:
|
||||
-->
|
||||
## 在集群中暴露 Pod
|
||||
|
||||
我们在之前的示例中已经做过,然而让我们以网络连接的视角再重做一遍。
|
||||
创建一个 Nginx Pod,注意其中包含一个容器端口的规约:
|
||||
|
||||
{{< codenew file="service/networking/run-my-nginx.yaml" >}}
|
||||
|
||||
<!--
|
||||
This makes it accessible from any node in your cluster. Check the nodes the Pod is running on:
|
||||
-->
|
||||
|
||||
这使得可以从集群中任何一个节点来访问它。检查节点,该 Pod 正在运行:
|
||||
|
||||
```shell
|
||||
kubectl apply -f ./run-my-nginx.yaml
|
||||
kubectl get pods -l run=my-nginx -o wide
|
||||
```
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE IP NODE
|
||||
my-nginx-3800858182-jr4a2 1/1 Running 0 13s 10.244.3.4 kubernetes-minion-905m
|
||||
my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5 kubernetes-minion-ljyd
|
||||
```
|
||||
|
||||
<!--
|
||||
Check your pods' IPs:
|
||||
-->
|
||||
检查 Pod 的 IP 地址:
|
||||
|
||||
```shell
|
||||
kubectl get pods -l run=my-nginx -o yaml | grep podIP
|
||||
podIP: 10.244.3.4
|
||||
podIP: 10.244.2.5
|
||||
```
|
||||
|
||||
<!--
|
||||
You should be able to ssh into any node in your cluster and use a tool such as `curl` to make queries against both IPs. Note that the containers are *not* using port 80 on the node, nor are there any special NAT rules to route traffic to the pod. This means you can run multiple nginx pods on the same node all using the same `containerPort`, and access them from any other pod or node in your cluster using the assigned IP address for the Service. If you want to arrange for a specific port on the host Node to be forwarded to backing Pods, you can - but the networking model should mean that you do not need to do so.
|
||||
|
||||
You can read more about the [Kubernetes Networking Model](/docs/concepts/cluster-administration/networking/#the-kubernetes-network-model) if you're curious.
|
||||
-->
|
||||
你应该能够通过 ssh 登录到集群中的任何一个节点上,并使用诸如 `curl` 之类的工具向这两个 IP 地址发出查询请求。
|
||||
需要注意的是,容器不会使用该节点上的 80 端口,也不会使用任何特定的 NAT 规则去路由流量到 Pod 上。
|
||||
这意味着可以在同一个节点上运行多个 Nginx Pod,使用相同的 `containerPort`,并且可以从集群中任何其他的
|
||||
Pod 或节点上使用 IP 的方式访问到它们。
|
||||
如果你想的话,你依然可以将宿主节点的某个端口的流量转发到 Pod 中,但是出于网络模型的原因,你不必这么做。
|
||||
|
||||
如果对此好奇,请参考 [Kubernetes 网络模型](/zh/docs/concepts/cluster-administration/networking/#the-kubernetes-network-model)。
|
||||
|
||||
<!--
|
||||
## Creating a Service
|
||||
|
||||
So we have pods running nginx in a flat, cluster wide, address space. In theory, you could talk to these pods directly, but what happens when a node dies? The pods die with it, and the Deployment will create new ones, with different IPs. This is the problem a Service solves.
|
||||
|
||||
A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.
|
||||
|
||||
You can create a Service for your 2 nginx replicas with `kubectl expose`:
|
||||
-->
|
||||
## 创建 Service
|
||||
|
||||
我们有一组在一个扁平的、集群范围的地址空间中运行 Nginx 服务的 Pod。
|
||||
理论上,你可以直接连接到这些 Pod,但如果某个节点死掉了会发生什么呢?
|
||||
Pod 会终止,Deployment 将创建新的 Pod,且使用不同的 IP。这正是 Service 要解决的问题。
|
||||
|
||||
Kubernetes Service 是集群中提供相同功能的一组 Pod 的抽象表达。
|
||||
当每个 Service 创建时,会被分配一个唯一的 IP 地址(也称为 clusterIP)。
|
||||
这个 IP 地址与 Service 的生命周期绑定在一起,只要 Service 存在,它就不会改变。
|
||||
可以配置 Pod 使它与 Service 进行通信,Pod 知道与 Service 通信将被自动地负载均衡到该 Service 中的某些 Pod 上。
|
||||
|
||||
可以使用 `kubectl expose` 命令为 2个 Nginx 副本创建一个 Service:
|
||||
|
||||
```shell
|
||||
kubectl expose deployment/my-nginx
|
||||
```
|
||||
```
|
||||
service/my-nginx exposed
|
||||
```
|
||||
|
||||
<!--
|
||||
This is equivalent to `kubectl apply -f` the following yaml:
|
||||
-->
|
||||
|
||||
这等价于使用 `kubectl create -f` 命令及如下的 yaml 文件创建:
|
||||
|
||||
{{< codenew file="service/networking/nginx-svc.yaml" >}}
|
||||
|
||||
<!--
|
||||
This specification will create a Service which targets TCP port 80 on any Pod
|
||||
with the `run: my-nginx` label, and expose it on an abstracted Service port
|
||||
(`targetPort`: is the port the container accepts traffic on, `port`: is the
|
||||
abstracted Service port, which can be any port other pods use to access the
|
||||
Service).
|
||||
View [Service](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core)
|
||||
API object to see the list of supported fields in service definition.
|
||||
Check your Service:
|
||||
-->
|
||||
上述规约将创建一个 Service,该 Service 会将所有具有标签 `run: my-nginx` 的 Pod 的 TCP
|
||||
80 端口暴露到一个抽象的 Service 端口上(`targetPort`:容器接收流量的端口;`port`:可任意取值的抽象的 Service
|
||||
端口,其他 Pod 通过该端口访问 Service)。
|
||||
查看 [Service](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core)
|
||||
API 对象以了解 Service 所能接受的字段列表。
|
||||
查看你的 Service 资源:
|
||||
|
||||
```shell
|
||||
kubectl get svc my-nginx
|
||||
```
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
|
||||
```
|
||||
|
||||
<!--
|
||||
As mentioned previously, a Service is backed by a group of Pods. These Pods are
|
||||
exposed through `endpoints`. The Service's selector will be evaluated continuously
|
||||
and the results will be POSTed to an Endpoints object also named `my-nginx`.
|
||||
When a Pod dies, it is automatically removed from the endpoints, and new Pods
|
||||
matching the Service's selector will automatically get added to the endpoints.
|
||||
Check the endpoints, and note that the IPs are the same as the Pods created in
|
||||
the first step:
|
||||
-->
|
||||
正如前面所提到的,一个 Service 由一组 Pod 提供支撑。这些 Pod 通过 `endpoints` 暴露出来。
|
||||
Service Selector 将持续评估,结果被 POST 到一个名称为 `my-nginx` 的 Endpoint 对象上。
|
||||
当 Pod 终止后,它会自动从 Endpoint 中移除,新的能够匹配上 Service Selector 的 Pod 将自动地被添加到 Endpoint 中。
|
||||
检查该 Endpoint,注意到 IP 地址与在第一步创建的 Pod 是相同的。
|
||||
|
||||
```shell
|
||||
kubectl describe svc my-nginx
|
||||
```
|
||||
```
|
||||
Name: my-nginx
|
||||
Namespace: default
|
||||
Labels: run=my-nginx
|
||||
Annotations: <none>
|
||||
Selector: run=my-nginx
|
||||
Type: ClusterIP
|
||||
IP: 10.0.162.149
|
||||
Port: <unset> 80/TCP
|
||||
Endpoints: 10.244.2.5:80,10.244.3.4:80
|
||||
Session Affinity: None
|
||||
Events: <none>
|
||||
```
|
||||
```shell
|
||||
kubectl get ep my-nginx
|
||||
```
|
||||
```
|
||||
NAME ENDPOINTS AGE
|
||||
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
|
||||
```
|
||||
|
||||
<!--
|
||||
You should now be able to curl the nginx Service on `<CLUSTER-IP>:<PORT>` from
|
||||
any node in your cluster. Note that the Service IP is completely virtual, it
|
||||
never hits the wire. If you're curious about how this works you can read more
|
||||
about the [service proxy](/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies).
|
||||
-->
|
||||
|
||||
现在,你应该能够从集群中任意节点上使用 curl 命令向 `<CLUSTER-IP>:<PORT>` 发送请求以访问 Nginx Service。
|
||||
注意 Service IP 完全是虚拟的,它从来没有走过网络,如果对它如何工作的原理感到好奇,
|
||||
可以进一步阅读[服务代理](/zh/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)
|
||||
的内容。
|
||||
|
||||
<!--
|
||||
## Accessing the Service
|
||||
|
||||
Kubernetes supports 2 primary modes of finding a Service - environment variables
|
||||
and DNS. The former works out of the box while the latter requires the
|
||||
[CoreDNS cluster addon](https://releases.k8s.io/{{< param "fullversion" >}}/cluster/addons/dns/coredns).
|
||||
-->
|
||||
## 访问 Service
|
||||
|
||||
Kubernetes支持两种查找服务的主要模式: 环境变量和 DNS。前者开箱即用,而后者则需要
|
||||
[CoreDNS 集群插件](https://releases.k8s.io/{{< param "fullversion" >}}/cluster/addons/dns/coredns).
|
||||
|
||||
<!--
|
||||
If the service environment variables are not desired (because possible clashing with expected program ones,
|
||||
too many variables to process, only using DNS, etc) you can disable this mode by setting the `enableServiceLinks`
|
||||
flag to `false` on the [pod spec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core).
|
||||
-->
|
||||
{{< note >}}
|
||||
如果不需要服务环境变量(因为可能与预期的程序冲突,可能要处理的变量太多,或者仅使用DNS等),则可以通过在
|
||||
[pod spec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)
|
||||
上将 `enableServiceLinks` 标志设置为 `false` 来禁用此模式。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
### Environment Variables
|
||||
|
||||
When a Pod runs on a Node, the kubelet adds a set of environment variables for
|
||||
each active Service. This introduces an ordering problem. To see why, inspect
|
||||
the environment of your running nginx Pods (your Pod name will be different):
|
||||
-->
|
||||
### 环境变量
|
||||
|
||||
当 Pod 在节点上运行时,kubelet 会针对每个活跃的 Service 为 Pod 添加一组环境变量。
|
||||
这就引入了一个顺序的问题。为解释这个问题,让我们先检查正在运行的 Nginx Pod
|
||||
的环境变量(你的环境中的 Pod 名称将会与下面示例命令中的不同):
|
||||
|
||||
```shell
|
||||
kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
|
||||
```
|
||||
```
|
||||
KUBERNETES_SERVICE_HOST=10.0.0.1
|
||||
KUBERNETES_SERVICE_PORT=443
|
||||
KUBERNETES_SERVICE_PORT_HTTPS=443
|
||||
```
|
||||
|
||||
<!--
|
||||
Note there's no mention of your Service. This is because you created the replicas
|
||||
before the Service. Another disadvantage of doing this is that the scheduler might
|
||||
put both Pods on the same machine, which will take your entire Service down if
|
||||
it dies. We can do this the right way by killing the 2 Pods and waiting for the
|
||||
Deployment to recreate them. This time around the Service exists *before* the
|
||||
replicas. This will give you scheduler-level Service spreading of your Pods
|
||||
(provided all your nodes have equal capacity), as well as the right environment
|
||||
variables:
|
||||
-->
|
||||
|
||||
能看到环境变量中并没有你创建的 Service 相关的值。这是因为副本的创建先于 Service。
|
||||
这样做的另一个缺点是,调度器可能会将所有 Pod 部署到同一台机器上,如果该机器宕机则整个 Service 都会离线。
|
||||
要改正的话,我们可以先终止这 2 个 Pod,然后等待 Deployment 去重新创建它们。
|
||||
这次 Service 会*先于*副本存在。这将实现调度器级别的 Pod 按 Service
|
||||
分布(假定所有的节点都具有同样的容量),并提供正确的环境变量:
|
||||
|
||||
```shell
|
||||
kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
|
||||
|
||||
kubectl get pods -l run=my-nginx -o wide
|
||||
```
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE IP NODE
|
||||
my-nginx-3800858182-e9ihh 1/1 Running 0 5s 10.244.2.7 kubernetes-minion-ljyd
|
||||
my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8 kubernetes-minion-905m
|
||||
```
|
||||
|
||||
<!--
|
||||
You may notice that the pods have different names, since they are killed and recreated.
|
||||
-->
|
||||
|
||||
你可能注意到,Pod 具有不同的名称,这是因为它们是被重新创建的。
|
||||
|
||||
```shell
|
||||
kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
|
||||
```
|
||||
```
|
||||
KUBERNETES_SERVICE_PORT=443
|
||||
MY_NGINX_SERVICE_HOST=10.0.162.149
|
||||
KUBERNETES_SERVICE_HOST=10.0.0.1
|
||||
MY_NGINX_SERVICE_PORT=80
|
||||
KUBERNETES_SERVICE_PORT_HTTPS=443
|
||||
```
|
||||
|
||||
### DNS
|
||||
|
||||
<!--
|
||||
Kubernetes offers a DNS cluster addon Service that automatically assigns dns names to other Services. You can check if it's running on your cluster:
|
||||
-->
|
||||
|
||||
Kubernetes 提供了一个自动为其它 Service 分配 DNS 名字的 DNS 插件 Service。
|
||||
你可以通过如下命令检查它是否在工作:
|
||||
|
||||
```shell
|
||||
kubectl get services kube-dns --namespace=kube-system
|
||||
```
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
|
||||
```
|
||||
|
||||
<!--
|
||||
The rest of this section will assume you have a Service with a long lived IP
|
||||
(my-nginx), and a DNS server that has assigned a name to that IP. Here we use the CoreDNS cluster addon (application name `kube-dns`), so you can talk to the Service from any pod in your cluster using standard methods (e.g. `gethostbyname()`). If CoreDNS isn't running, you can enable it referring to the [CoreDNS README](https://github.com/coredns/deployment/tree/master/kubernetes) or [Installing CoreDNS](/docs/tasks/administer-cluster/coredns/#installing-coredns). Let's run another curl application to test this:
|
||||
-->
|
||||
本段剩余的内容假设你已经有一个拥有持久 IP 地址的 Service(my-nginx),以及一个为其
|
||||
IP 分配名称的 DNS 服务器。 这里我们使用 CoreDNS 集群插件(应用名为 `kube-dns`),
|
||||
所以在集群中的任何 Pod 中,你都可以使用标准方法(例如:`gethostbyname()`)与该 Service 通信。
|
||||
如果 CoreDNS 没有在运行,你可以参照
|
||||
[CoreDNS README](https://github.com/coredns/deployment/tree/master/kubernetes)
|
||||
或者[安装 CoreDNS](/zh/docs/tasks/administer-cluster/coredns/#installing-coredns) 来启用它。
|
||||
让我们运行另一个 curl 应用来进行测试:
|
||||
|
||||
```shell
|
||||
kubectl run curl --image=radial/busyboxplus:curl -i --tty
|
||||
```
|
||||
```
|
||||
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
|
||||
Hit enter for command prompt
|
||||
```
|
||||
|
||||
<!--
|
||||
Then, hit enter and run `nslookup my-nginx`:
|
||||
-->
|
||||
|
||||
然后,按回车并执行命令 `nslookup my-nginx`:
|
||||
|
||||
```shell
|
||||
[ root@curl-131556218-9fnch:/ ]$ nslookup my-nginx
|
||||
Server: 10.0.0.10
|
||||
Address 1: 10.0.0.10
|
||||
|
||||
Name: my-nginx
|
||||
Address 1: 10.0.162.149
|
||||
```
|
||||
|
||||
<!--
|
||||
## Securing the Service
|
||||
|
||||
Till now we have only accessed the nginx server from within the cluster. Before exposing the Service to the internet, you want to make sure the communication channel is secure. For this, you will need:
|
||||
|
||||
* Self signed certificates for https (unless you already have an identity certificate)
|
||||
* An nginx server configured to use the certificates
|
||||
* A [secret](/docs/concepts/configuration/secret/) that makes the certificates accessible to pods
|
||||
|
||||
You can acquire all these from the [nginx https example](https://github.com/kubernetes/examples/tree/master/staging/https-nginx/). This requires having go and make tools installed. If you don't want to install those, then follow the manual steps later. In short:
|
||||
-->
|
||||
|
||||
## 保护 Service {#securing-the-service}
|
||||
|
||||
到现在为止,我们只在集群内部访问了 Nginx 服务器。在将 Service 暴露到因特网之前,我们希望确保通信信道是安全的。
|
||||
为实现这一目的,需要:
|
||||
|
||||
* 用于 HTTPS 的自签名证书(除非已经有了一个身份证书)
|
||||
* 使用证书配置的 Nginx 服务器
|
||||
* 使 Pod 可以访问证书的 [Secret](/zh/docs/concepts/configuration/secret/)
|
||||
|
||||
你可以从
|
||||
[Nginx https 示例](https://github.com/kubernetes/examples/tree/master/staging/https-nginx/)获取所有上述内容。
|
||||
你需要安装 go 和 make 工具。如果你不想安装这些软件,可以按照后文所述的手动执行步骤执行操作。简要过程如下:
|
||||
|
||||
```shell
|
||||
make keys KEY=/tmp/nginx.key CERT=/tmp/nginx.crt
|
||||
kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
|
||||
```
|
||||
```
|
||||
secret/nginxsecret created
|
||||
```
|
||||
```shell
|
||||
kubectl get secrets
|
||||
```
|
||||
```
|
||||
NAME TYPE DATA AGE
|
||||
default-token-il9rc kubernetes.io/service-account-token 1 1d
|
||||
nginxsecret kubernetes.io/tls 2 1m
|
||||
```
|
||||
|
||||
<!--
|
||||
And also the configmap:
|
||||
-->
|
||||
以下是 configmap:
|
||||
```shell
|
||||
kubectl create configmap nginxconfigmap --from-file=default.conf
|
||||
```
|
||||
```
|
||||
configmap/nginxconfigmap created
|
||||
```
|
||||
```shell
|
||||
kubectl get configmaps
|
||||
```
|
||||
```
|
||||
NAME DATA AGE
|
||||
nginxconfigmap 1 114s
|
||||
```
|
||||
|
||||
<!--
|
||||
Following are the manual steps to follow in case you run into problems running make (on windows for example):
|
||||
-->
|
||||
以下是你在运行 make 时遇到问题时要遵循的手动步骤(例如,在 Windows 上):
|
||||
|
||||
```shell
|
||||
# 创建公钥和相对应的私钥
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
|
||||
# 对密钥实施 base64 编码
|
||||
cat /d/tmp/nginx.crt | base64
|
||||
cat /d/tmp/nginx.key | base64
|
||||
```
|
||||
|
||||
<!--
|
||||
Use the output from the previous commands to create a yaml file as follows. The base64 encoded value should all be on a single line.
|
||||
-->
|
||||
使用前面命令的输出来创建 yaml 文件,如下所示。 base64 编码的值应全部放在一行上。
|
||||
|
||||
```yaml
|
||||
apiVersion: "v1"
|
||||
kind: "Secret"
|
||||
metadata:
|
||||
name: "nginxsecret"
|
||||
namespace: "default"
|
||||
type: kubernetes.io/tls
|
||||
data:
|
||||
tls.crt: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||
tls.key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
|
||||
```
|
||||
|
||||
<!--
|
||||
Now create the secrets using the file:
|
||||
-->
|
||||
现在使用文件创建 Secret:
|
||||
|
||||
```shell
|
||||
kubectl apply -f nginxsecrets.yaml
|
||||
kubectl get secrets
|
||||
```
|
||||
```
|
||||
NAME TYPE DATA AGE
|
||||
default-token-il9rc kubernetes.io/service-account-token 1 1d
|
||||
nginxsecret kubernetes.io/tls 2 1m
|
||||
```
|
||||
|
||||
<!--
|
||||
Now modify your nginx replicas to start an https server using the certificate in the secret, and the Service, to expose both ports (80 and 443):
|
||||
-->
|
||||
现在修改 nginx 副本以启动一个使用 Secret 中的证书的 HTTPS 服务器以及相应的用于暴露其端口(80 和 443)的 Service:
|
||||
|
||||
{{< codenew file="service/networking/nginx-secure-app.yaml" >}}
|
||||
|
||||
<!--
|
||||
Noteworthy points about the nginx-secure-app manifest:
|
||||
|
||||
- It contains both Deployment and Service specification in the same file.
|
||||
- The [nginx server](https://github.com/kubernetes/examples/tree/master/staging/https-nginx/default.conf)
|
||||
serves HTTP traffic on port 80 and HTTPS traffic on 443, and nginx Service
|
||||
exposes both ports.
|
||||
- Each container has access to the keys through a volume mounted at `/etc/nginx/ssl`.
|
||||
This is setup *before* the nginx server is started.
|
||||
-->
|
||||
关于 nginx-secure-app 清单,值得注意的几点如下:
|
||||
|
||||
- 它将 Deployment 和 Service 的规约放在了同一个文件中。
|
||||
- [Nginx 服务器](https://github.com/kubernetes/examples/tree/master/staging/https-nginx/default.conf)通过
|
||||
80 端口处理 HTTP 流量,通过 443 端口处理 HTTPS 流量,而 Nginx Service 则暴露了这两个端口。
|
||||
- 每个容器能通过挂载在 `/etc/nginx/ssl` 的卷访问秘钥。卷和密钥需要在 Nginx 服务器启动*之前*配置好。
|
||||
|
||||
```shell
|
||||
kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
|
||||
```
|
||||
|
||||
<!--
|
||||
At this point you can reach the nginx server from any node.
|
||||
-->
|
||||
这时,你可以从任何节点访问到 Nginx 服务器。
|
||||
|
||||
```shell
|
||||
kubectl get pods -o yaml | grep -i podip
|
||||
podIP: 10.244.3.5
|
||||
node $ curl -k https://10.244.3.5
|
||||
...
|
||||
<h1>Welcome to nginx!</h1>
|
||||
```
|
||||
|
||||
<!--
|
||||
Note how we supplied the `-k` parameter to curl in the last step, this is because we don't know anything about the pods running nginx at certificate generation time,
|
||||
so we have to tell curl to ignore the CName mismatch. By creating a Service we linked the CName used in the certificate with the actual DNS name used by pods during Service lookup.
|
||||
Let's test this from a pod (the same secret is being reused for simplicity, the pod only needs nginx.crt to access the Service):
|
||||
-->
|
||||
注意最后一步我们是如何提供 `-k` 参数执行 curl 命令的,这是因为在证书生成时,
|
||||
我们不知道任何关于运行 nginx 的 Pod 的信息,所以不得不在执行 curl 命令时忽略 CName 不匹配的情况。
|
||||
通过创建 Service,我们连接了在证书中的 CName 与在 Service 查询时被 Pod 使用的实际 DNS 名字。
|
||||
让我们从一个 Pod 来测试(为了方便,这里使用同一个 Secret,Pod 仅需要使用 nginx.crt 去访问 Service):
|
||||
|
||||
{{< codenew file="service/networking/curlpod.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl apply -f ./curlpod.yaml
|
||||
kubectl get pods -l app=curlpod
|
||||
```
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
curl-deployment-1515033274-1410r 1/1 Running 0 1m
|
||||
```
|
||||
```shell
|
||||
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/tls.crt
|
||||
...
|
||||
<title>Welcome to nginx!</title>
|
||||
...
|
||||
```
|
||||
|
||||
<!--
|
||||
## Exposing the Service
|
||||
|
||||
For some parts of your applications you may want to expose a Service onto an
|
||||
external IP address. Kubernetes supports two ways of doing this: NodePorts and
|
||||
LoadBalancers. The Service created in the last section already used `NodePort`,
|
||||
so your nginx HTTPS replica is ready to serve traffic on the internet if your
|
||||
node has a public IP.
|
||||
-->
|
||||
## 暴露 Service
|
||||
|
||||
对应用的某些部分,你可能希望将 Service 暴露在一个外部 IP 地址上。
|
||||
Kubernetes 支持两种实现方式:NodePort 和 LoadBalancer。
|
||||
在上一段创建的 Service 使用了 `NodePort`,因此,如果你的节点有一个公网
|
||||
IP,那么 Nginx HTTPS 副本已经能够处理因特网上的流量。
|
||||
|
||||
```shell
|
||||
kubectl get svc my-nginx -o yaml | grep nodePort -C 5
|
||||
```
|
||||
|
||||
```
|
||||
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
|
||||
spec:
|
||||
clusterIP: 10.0.162.149
|
||||
ports:
|
||||
- name: http
|
||||
nodePort: 31704
|
||||
port: 8080
|
||||
protocol: TCP
|
||||
targetPort: 80
|
||||
- name: https
|
||||
nodePort: 32453
|
||||
port: 443
|
||||
protocol: TCP
|
||||
targetPort: 443
|
||||
selector:
|
||||
run: my-nginx
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get nodes -o yaml | grep ExternalIP -C 1
|
||||
```
|
||||
|
||||
```
|
||||
- address: 104.197.41.11
|
||||
type: ExternalIP
|
||||
allocatable:
|
||||
--
|
||||
- address: 23.251.152.56
|
||||
type: ExternalIP
|
||||
allocatable:
|
||||
...
|
||||
|
||||
$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
|
||||
...
|
||||
<h1>Welcome to nginx!</h1>
|
||||
```
|
||||
|
||||
<!--
|
||||
Let's now recreate the Service to use a cloud load balancer. Change the `Type` of `my-nginx` Service from `NodePort` to `LoadBalancer`:
|
||||
-->
|
||||
|
||||
让我们重新创建一个 Service 以使用云负载均衡器。
|
||||
将 `my-nginx` Service 的 `Type` 由 `NodePort` 改成 `LoadBalancer`:
|
||||
|
||||
```shell
|
||||
kubectl edit svc my-nginx
|
||||
kubectl get svc my-nginx
|
||||
```
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
my-nginx LoadBalancer 10.0.162.149 xx.xxx.xxx.xxx 8080:30163/TCP 21s
|
||||
```
|
||||
```
|
||||
curl https://<EXTERNAL-IP> -k
|
||||
...
|
||||
<title>Welcome to nginx!</title>
|
||||
```
|
||||
|
||||
<!--
|
||||
The IP address in the `EXTERNAL-IP` column is the one that is available on the public internet. The `CLUSTER-IP` is only available inside your
|
||||
cluster/private cloud network.
|
||||
|
||||
Note that on AWS, type `LoadBalancer` creates an ELB, which uses a (long)
|
||||
hostname, not an IP. It's too long to fit in the standard `kubectl get svc`
|
||||
output, in fact, so you'll need to do `kubectl describe service my-nginx` to
|
||||
see it. You'll see something like this:
|
||||
-->
|
||||
|
||||
在 `EXTERNAL-IP` 列中的 IP 地址能在公网上被访问到。`CLUSTER-IP` 只能从集群/私有云网络中访问。
|
||||
|
||||
注意,在 AWS 上,类型 `LoadBalancer` 的服务会创建一个 ELB,且 ELB 使用主机名(比较长),而不是 IP。
|
||||
ELB 的主机名太长以至于不能适配标准 `kubectl get svc` 的输出,所以需要通过执行
|
||||
`kubectl describe service my-nginx` 命令来查看它。
|
||||
可以看到类似如下内容:
|
||||
|
||||
```shell
|
||||
kubectl describe service my-nginx
|
||||
...
|
||||
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
|
||||
...
|
||||
```
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
* Learn more about [Using a Service to Access an Application in a Cluster](/docs/tasks/access-application-cluster/service-access-application-cluster/)
|
||||
* Learn more about [Connecting a Front End to a Back End Using a Service](/docs/tasks/access-application-cluster/connecting-frontend-backend/)
|
||||
* Learn more about [Creating an External Load Balancer](/docs/tasks/access-application-cluster/create-external-load-balancer/)
|
||||
-->
|
||||
* 进一步了解如何[使用 Service 访问集群中的应用](/zh/docs/tasks/access-application-cluster/service-access-application-cluster/)
|
||||
* 进一步了解如何[使用 Service 将前端连接到后端](/zh/docs/tasks/access-application-cluster/connecting-frontend-backend/)
|
||||
* 进一步了解如何[创建外部负载均衡器](/zh/docs/tasks/access-application-cluster/create-external-load-balancer/)
|
||||
@@ -0,0 +1,613 @@
|
||||
---
|
||||
title: Pod 与 Service 的 DNS
|
||||
content_type: concept
|
||||
weight: 20
|
||||
---
|
||||
<!--
|
||||
reviewers:
|
||||
- davidopp
|
||||
- thockin
|
||||
title: DNS for Services and Pods
|
||||
content_type: concept
|
||||
weight: 20
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
<!--
|
||||
Kubernetes creates DNS records for Services and Pods. You can contact
|
||||
Services with consistent DNS names instead of IP addresses.
|
||||
-->
|
||||
Kubernetes 为 Service 和 Pod 创建 DNS 记录。
|
||||
你可以使用一致的 DNS 名称而非 IP 地址访问 Service。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Introduction
|
||||
|
||||
Kubernetes DNS schedules a DNS Pod and Service on the cluster, and configures
|
||||
the kubelets to tell individual containers to use the DNS Service's IP to
|
||||
resolve DNS names.
|
||||
-->
|
||||
## 介绍 {#introduction}
|
||||
|
||||
Kubernetes DNS 除了在集群上调度 DNS Pod 和 Service,
|
||||
还配置 kubelet 以告知各个容器使用 DNS Service 的 IP 来解析 DNS 名称。
|
||||
|
||||
<!--
|
||||
Every Service defined in the cluster (including the DNS server itself) is
|
||||
assigned a DNS name. By default, a client Pod's DNS search list includes the
|
||||
Pod's own namespace and the cluster's default domain.
|
||||
-->
|
||||
集群中定义的每个 Service (包括 DNS 服务器自身)都被赋予一个 DNS 名称。
|
||||
默认情况下,客户端 Pod 的 DNS 搜索列表会包含 Pod 自身的名字空间和集群的默认域。
|
||||
|
||||
<!--
|
||||
### Namespaces of Services
|
||||
|
||||
A DNS query may return different results based on the namespace of the Pod making
|
||||
it. DNS queries that don't specify a namespace are limited to the Pod's
|
||||
namespace. Access Services in other namespaces by specifying it in the DNS query.
|
||||
|
||||
For example, consider a Pod in a `test` namespace. A `data` service is in
|
||||
the `prod` namespace.
|
||||
|
||||
A query for `data` returns no results, because it uses the Pod's `test` namespace.
|
||||
|
||||
A query for `data.prod` returns the intended result, because it specifies the
|
||||
namespace.
|
||||
-->
|
||||
### Service 的名字空间 {#namespaces-of-services}
|
||||
|
||||
DNS 查询可能因为执行查询的 Pod 所在的名字空间而返回不同的结果。
|
||||
不指定名字空间的 DNS 查询会被限制在 Pod 所在的名字空间内。
|
||||
要访问其他名字空间中的 Service,需要在 DNS 查询中指定名字空间。
|
||||
|
||||
例如,假定名字空间 `test` 中存在一个 Pod,`prod` 名字空间中存在一个服务
|
||||
`data`。
|
||||
|
||||
Pod 查询 `data` 时没有返回结果,因为使用的是 Pod 的名字空间 `test`。
|
||||
|
||||
Pod 查询 `data.prod` 时则会返回预期的结果,因为查询中指定了名字空间。
|
||||
|
||||
<!--
|
||||
DNS queries may be expanded using the Pod's `/etc/resolv.conf`. Kubelet
|
||||
sets this file for each Pod. For example, a query for just `data` may be
|
||||
expanded to `data.test.svc.cluster.local`. The values of the `search` option
|
||||
are used to expand queries. To learn more about DNS queries, see
|
||||
[the `resolv.conf` manual page.](https://www.man7.org/linux/man-pages/man5/resolv.conf.5.html)
|
||||
-->
|
||||
DNS 查询可以使用 Pod 中的 `/etc/resolv.conf` 展开。kubelet 会为每个 Pod
|
||||
生成此文件。例如,对 `data` 的查询可能被展开为 `data.test.svc.cluster.local`。
|
||||
`search` 选项的取值会被用来展开查询。要进一步了解 DNS 查询,可参阅
|
||||
[`resolv.conf` 手册页面](https://www.man7.org/linux/man-pages/man5/resolv.conf.5.html)。
|
||||
|
||||
```
|
||||
nameserver 10.32.0.10
|
||||
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
|
||||
options ndots:5
|
||||
```
|
||||
|
||||
<!--
|
||||
In summary, a Pod in the `test` namespace can successfully resolve either
|
||||
`data.prod` or `data.prod.svc.cluster.local`.
|
||||
-->
|
||||
概括起来,名字空间 `test` 中的 Pod 可以成功地解析 `data.prod` 或者
|
||||
`data.prod.svc.cluster.local`。
|
||||
|
||||
<!--
|
||||
### DNS Records
|
||||
|
||||
What objects get DNS records?
|
||||
-->
|
||||
### DNS 记录 {#dns-records}
|
||||
|
||||
哪些对象会获得 DNS 记录呢?
|
||||
|
||||
1. Services
|
||||
2. Pods
|
||||
|
||||
<!--
|
||||
The following sections detail the supported DNS record types and layout that is
|
||||
supported. Any other layout or names or queries that happen to work are
|
||||
considered implementation details and are subject to change without warning.
|
||||
For more up-to-date specification, see
|
||||
[Kubernetes DNS-Based Service Discovery](https://github.com/kubernetes/dns/blob/master/docs/specification.md).
|
||||
-->
|
||||
以下各节详细介绍已支持的 DNS 记录类型和布局。
|
||||
其它布局、名称或者查询即使碰巧可以工作,也应视为实现细节,
|
||||
将来很可能被更改而且不会因此发出警告。
|
||||
有关最新规范请查看
|
||||
[Kubernetes 基于 DNS 的服务发现](https://github.com/kubernetes/dns/blob/master/docs/specification.md)。
|
||||
|
||||
<!--
|
||||
## Services
|
||||
|
||||
### A/AAAA records
|
||||
|
||||
"Normal" (not headless) Services are assigned a DNS A or AAAA record,
|
||||
depending on the IP family of the Service, for a name of the form
|
||||
`my-svc.my-namespace.svc.cluster-domain.example`. This resolves to the cluster IP
|
||||
of the Service.
|
||||
|
||||
"Headless" (without a cluster IP) Services are also assigned a DNS A or AAAA record,
|
||||
depending on the IP family of the Service, for a name of the form
|
||||
`my-svc.my-namespace.svc.cluster-domain.example`. Unlike normal
|
||||
Services, this resolves to the set of IPs of the Pods selected by the Service.
|
||||
Clients are expected to consume the set or else use standard round-robin
|
||||
selection from the set.
|
||||
-->
|
||||
### Services
|
||||
|
||||
#### A/AAAA 记录 {#a-aaaa-records}
|
||||
|
||||
“普通” Service(除了无头 Service)会以 `my-svc.my-namespace.svc.cluster-domain.example`
|
||||
这种名字的形式被分配一个 DNS A 或 AAAA 记录,取决于 Service 的 IP 协议族。
|
||||
该名称会解析成对应 Service 的集群 IP。
|
||||
|
||||
“无头(Headless)” Service (没有集群 IP)也会以
|
||||
`my-svc.my-namespace.svc.cluster-domain.example` 这种名字的形式被指派一个 DNS A 或 AAAA 记录,
|
||||
具体取决于 Service 的 IP 协议族。
|
||||
与普通 Service 不同,这一记录会被解析成对应 Service 所选择的 Pod IP 的集合。
|
||||
客户端要能够使用这组 IP,或者使用标准的轮转策略从这组 IP 中进行选择。
|
||||
|
||||
<!--
|
||||
### SRV records
|
||||
|
||||
SRV Records are created for named ports that are part of normal or [Headless
|
||||
Services](/docs/concepts/services-networking/service/#headless-services).
|
||||
For each named port, the SRV record would have the form
|
||||
`_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example`.
|
||||
For a regular Service, this resolves to the port number and the domain name:
|
||||
`my-svc.my-namespace.svc.cluster-domain.example`.
|
||||
For a headless Service, this resolves to multiple answers, one for each Pod
|
||||
that is backing the Service, and contains the port number and the domain name of the Pod
|
||||
of the form `auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example`.
|
||||
-->
|
||||
#### SRV 记录 {#srv-records}
|
||||
|
||||
Kubernetes 根据普通 Service 或
|
||||
[Headless Service](/zh/docs/concepts/services-networking/service/#headless-services)
|
||||
中的命名端口创建 SRV 记录。每个命名端口,
|
||||
SRV 记录格式为 `_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example`。
|
||||
普通 Service,该记录会被解析成端口号和域名:`my-svc.my-namespace.svc.cluster-domain.example`。
|
||||
无头 Service,该记录会被解析成多个结果,及该服务的每个后端 Pod 各一个 SRV 记录,
|
||||
其中包含 Pod 端口号和格式为 `auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example`
|
||||
的域名。
|
||||
|
||||
## Pods
|
||||
|
||||
<!--
|
||||
### A/AAAA records
|
||||
|
||||
In general a Pod has the following DNS resolution:
|
||||
|
||||
`pod-ip-address.my-namespace.pod.cluster-domain.example`.
|
||||
|
||||
For example, if a Pod in the `default` namespace has the IP address 172.17.0.3,
|
||||
and the domain name for your cluster is `cluster.local`, then the Pod has a DNS name:
|
||||
|
||||
`172-17-0-3.default.pod.cluster.local`.
|
||||
|
||||
Any Pods exposed by a Service have the following DNS resolution available:
|
||||
|
||||
`pod-ip-address.service-name.my-namespace.svc.cluster-domain.example`.
|
||||
-->
|
||||
### A/AAAA 记录 {#a-aaaa-records}
|
||||
|
||||
一般而言,Pod 会对应如下 DNS 名字解析:
|
||||
|
||||
`pod-ip-address.my-namespace.pod.cluster-domain.example`
|
||||
|
||||
例如,对于一个位于 `default` 名字空间,IP 地址为 172.17.0.3 的 Pod,
|
||||
如果集群的域名为 `cluster.local`,则 Pod 会对应 DNS 名称:
|
||||
|
||||
`172-17-0-3.default.pod.cluster.local`.
|
||||
|
||||
通过 Service 暴露出来的所有 Pod 都会有如下 DNS 解析名称可用:
|
||||
|
||||
`pod-ip-address.service-name.my-namespace.svc.cluster-domain.example`.
|
||||
|
||||
<!--
|
||||
### Pod's hostname and subdomain fields
|
||||
|
||||
Currently when a Pod is created, its hostname is the Pod's `metadata.name` value.
|
||||
|
||||
The Pod spec has an optional `hostname` field, which can be used to specify the
|
||||
Pod's hostname. When specified, it takes precedence over the Pod's name to be
|
||||
the hostname of the Pod. For example, given a Pod with `hostname` set to
|
||||
"`my-host`", the Pod will have its hostname set to "`my-host`".
|
||||
|
||||
The Pod spec also has an optional `subdomain` field which can be used to specify
|
||||
its subdomain. For example, a Pod with `hostname` set to "`foo`", and `subdomain`
|
||||
set to "`bar`", in namespace "`my-namespace`", will have the fully qualified
|
||||
domain name (FQDN) "`foo.bar.my-namespace.svc.cluster-domain.example`".
|
||||
|
||||
Example:
|
||||
-->
|
||||
### Pod 的 hostname 和 subdomain 字段 {#pod-s-hostname-and-subdomain-fields}
|
||||
|
||||
当前,创建 Pod 时其主机名取自 Pod 的 `metadata.name` 值。
|
||||
|
||||
Pod 规约中包含一个可选的 `hostname` 字段,可以用来指定 Pod 的主机名。
|
||||
当这个字段被设置时,它将优先于 Pod 的名字成为该 Pod 的主机名。
|
||||
举个例子,给定一个 `hostname` 设置为 "`my-host`" 的 Pod,
|
||||
该 Pod 的主机名将被设置为 "`my-host`"。
|
||||
|
||||
Pod 规约还有一个可选的 `subdomain` 字段,可以用来指定 Pod 的子域名。
|
||||
举个例子,某 Pod 的 `hostname` 设置为 “`foo`”,`subdomain` 设置为 “`bar`”,
|
||||
在名字空间 “`my-namespace`” 中对应的完全限定域名(FQDN)为
|
||||
“`foo.bar.my-namespace.svc.cluster-domain.example`”。
|
||||
|
||||
示例:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: default-subdomain
|
||||
spec:
|
||||
selector:
|
||||
name: busybox
|
||||
clusterIP: None
|
||||
ports:
|
||||
- name: foo # 实际上不需要指定端口号
|
||||
port: 1234
|
||||
targetPort: 1234
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: busybox1
|
||||
labels:
|
||||
name: busybox
|
||||
spec:
|
||||
hostname: busybox-1
|
||||
subdomain: default-subdomain
|
||||
containers:
|
||||
- image: busybox:1.28
|
||||
command:
|
||||
- sleep
|
||||
- "3600"
|
||||
name: busybox
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: busybox2
|
||||
labels:
|
||||
name: busybox
|
||||
spec:
|
||||
hostname: busybox-2
|
||||
subdomain: default-subdomain
|
||||
containers:
|
||||
- image: busybox:1.28
|
||||
command:
|
||||
- sleep
|
||||
- "3600"
|
||||
name: busybox
|
||||
```
|
||||
|
||||
<!--
|
||||
If there exists a headless Service in the same namespace as the Pod and with
|
||||
the same name as the subdomain, the cluster's DNS Server also returns an A or AAAA
|
||||
record for the Pod's fully qualified hostname.
|
||||
For example, given a Pod with the hostname set to "`busybox-1`" and the subdomain set to
|
||||
"`default-subdomain`", and a headless Service named "`default-subdomain`" in
|
||||
the same namespace, the Pod will see its own FQDN as
|
||||
"`busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example`". DNS serves an
|
||||
A or AAAA record at that name, pointing to the Pod's IP. Both Pods "`busybox1`" and
|
||||
"`busybox2`" can have their distinct A or AAAA records.
|
||||
-->
|
||||
如果某无头 Service 与某 Pod 在同一个名字空间中,且它们具有相同的子域名,
|
||||
集群的 DNS 服务器也会为该 Pod 的全限定主机名返回 A 记录或 AAAA 记录。
|
||||
例如,在同一个名字空间中,给定一个主机名为 “busybox-1”、
|
||||
子域名设置为 “default-subdomain” 的 Pod,和一个名称为 “`default-subdomain`”
|
||||
的无头 Service,Pod 将看到自己的 FQDN 为
|
||||
"`busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example`"。
|
||||
DNS 会为此名字提供一个 A 记录或 AAAA 记录,指向该 Pod 的 IP。
|
||||
“`busybox1`” 和 “`busybox2`” 这两个 Pod 分别具有它们自己的 A 或 AAAA 记录。
|
||||
|
||||
<!--
|
||||
The Endpoints object can specify the `hostname` for any endpoint addresses,
|
||||
along with its IP.
|
||||
-->
|
||||
Endpoints 对象可以为任何端点地址及其 IP 指定 `hostname`。
|
||||
|
||||
<!--
|
||||
Because A or AAAA records are not created for Pod names, `hostname` is required for the Pod's A or AAAA
|
||||
record to be created. A Pod with no `hostname` but with `subdomain` will only create the
|
||||
A or AAAA record for the headless Service (`default-subdomain.my-namespace.svc.cluster-domain.example`),
|
||||
pointing to the Pod's IP address. Also, Pod needs to become ready in order to have a
|
||||
record unless `publishNotReadyAddresses=True` is set on the Service.
|
||||
-->
|
||||
{{< note >}}
|
||||
由于不是为 Pod 名称创建 A 或 AAAA 记录的,因此 Pod 的 A 或 AAAA 需要 `hostname`。
|
||||
没有设置 `hostname` 但设置了 `subdomain` 的 Pod 只会为
|
||||
无头 Service 创建 A 或 AAAA 记录(`default-subdomain.my-namespace.svc.cluster-domain.example`)
|
||||
指向 Pod 的 IP 地址。
|
||||
另外,除非在服务上设置了 `publishNotReadyAddresses=True`,否则只有 Pod 进入就绪状态
|
||||
才会有与之对应的记录。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
### Pod's setHostnameAsFQDN field {#pod-sethostnameasfqdn-field}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="stable" >}}
|
||||
-->
|
||||
### Pod 的 setHostnameAsFQDN 字段 {#pod-sethostnameasfqdn-field}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="stable" >}}
|
||||
|
||||
<!--
|
||||
When a Pod is configured to have fully qualified domain name (FQDN), its hostname is the short hostname. For example, if you have a Pod with the fully qualified domain name `busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example`, then by default the `hostname` command inside that Pod returns `busybox-1` and the `hostname --fqdn` command returns the FQDN.
|
||||
|
||||
When you set `setHostnameAsFQDN: true` in the Pod spec, the kubelet writes the Pod's FQDN into the hostname for that Pod's namespace. In this case, both `hostname` and `hostname --fqdn` return the Pod's FQDN.
|
||||
-->
|
||||
当 Pod 配置为具有全限定域名 (FQDN) 时,其主机名是短主机名。
|
||||
例如,如果你有一个具有完全限定域名 `busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example` 的 Pod,
|
||||
则默认情况下,该 Pod 内的 `hostname` 命令返回 `busybox-1`,而 `hostname --fqdn` 命令返回 FQDN。
|
||||
|
||||
当你在 Pod 规约中设置了 `setHostnameAsFQDN: true` 时,kubelet 会将 Pod
|
||||
的全限定域名(FQDN)作为该 Pod 的主机名记录到 Pod 所在名字空间。
|
||||
在这种情况下,`hostname` 和 `hostname --fqdn` 都会返回 Pod 的全限定域名。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
In Linux, the hostname field of the kernel (the `nodename` field of `struct utsname`) is limited to 64 characters.
|
||||
|
||||
If a Pod enables this feature and its FQDN is longer than 64 character, it will fail to start. The Pod will remain in `Pending` status (`ContainerCreating` as seen by `kubectl`) generating error events, such as Failed to construct FQDN from Pod hostname and cluster domain, FQDN `long-FQDN` is too long (64 characters is the max, 70 characters requested). One way of improving user experience for this scenario is to create an [admission webhook controller](/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) to control FQDN size when users create top level objects, for example, Deployment.
|
||||
-->
|
||||
在 Linux 中,内核的主机名字段(`struct utsname` 的 `nodename` 字段)限定
|
||||
最多 64 个字符。
|
||||
|
||||
如果 Pod 启用这一特性,而其 FQDN 超出 64 字符,Pod 的启动会失败。
|
||||
Pod 会一直出于 `Pending` 状态(通过 `kubectl` 所看到的 `ContainerCreating`),
|
||||
并产生错误事件,例如
|
||||
"Failed to construct FQDN from Pod hostname and cluster domain, FQDN
|
||||
`long-FQDN` is too long (64 characters is the max, 70 characters requested)."
|
||||
(无法基于 Pod 主机名和集群域名构造 FQDN,FQDN `long-FQDN` 过长,至多 64
|
||||
字符,请求字符数为 70)。
|
||||
对于这种场景而言,改善用户体验的一种方式是创建一个
|
||||
[准入 Webhook 控制器](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks),
|
||||
在用户创建顶层对象(如 Deployment)的时候控制 FQDN 的长度。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
### Pod's DNS Policy
|
||||
|
||||
DNS policies can be set on a per-Pod basis. Currently Kubernetes supports the
|
||||
following Pod-specific DNS policies. These policies are specified in the
|
||||
`dnsPolicy` field of a Pod Spec.
|
||||
|
||||
- "`Default`": The Pod inherits the name resolution configuration from the node
|
||||
that the Pods run on.
|
||||
See [related discussion](/docs/tasks/administer-cluster/dns-custom-nameservers)
|
||||
for more details.
|
||||
- "`ClusterFirst`": Any DNS query that does not match the configured cluster
|
||||
domain suffix, such as "`www.kubernetes.io`", is forwarded to the upstream
|
||||
nameserver inherited from the node. Cluster administrators may have extra
|
||||
stub-domain and upstream DNS servers configured.
|
||||
See [related discussion](/docs/tasks/administer-cluster/dns-custom-nameservers)
|
||||
for details on how DNS queries are handled in those cases.
|
||||
- "`ClusterFirstWithHostNet`": For Pods running with hostNetwork, you should
|
||||
explicitly set its DNS policy "`ClusterFirstWithHostNet`".
|
||||
- Note: This is not supported on Windows. See [below](#dns-windows) for details
|
||||
- "`None`": It allows a Pod to ignore DNS settings from the Kubernetes
|
||||
environment. All DNS settings are supposed to be provided using the
|
||||
`dnsConfig` field in the Pod Spec.
|
||||
See [Pod's DNS config](#pod-dns-config) subsection below.
|
||||
-->
|
||||
### Pod 的 DNS 策略 {#pod-s-dns-policy}
|
||||
|
||||
DNS 策略可以逐个 Pod 来设定。目前 Kubernetes 支持以下特定 Pod 的 DNS 策略。
|
||||
这些策略可以在 Pod 规约中的 `dnsPolicy` 字段设置:
|
||||
|
||||
- "`Default`": Pod 从运行所在的节点继承名称解析配置。参考
|
||||
[相关讨论](/zh/docs/tasks/administer-cluster/dns-custom-nameservers)
|
||||
获取更多信息。
|
||||
- "`ClusterFirst`": 与配置的集群域后缀不匹配的任何 DNS 查询(例如 "www.kubernetes.io")
|
||||
都将转发到从节点继承的上游名称服务器。集群管理员可能配置了额外的存根域和上游 DNS 服务器。
|
||||
参阅[相关讨论](/zh/docs/tasks/administer-cluster/dns-custom-nameservers)
|
||||
了解在这些场景中如何处理 DNS 查询的信息。
|
||||
- "`ClusterFirstWithHostNet`":对于以 hostNetwork 方式运行的 Pod,应显式设置其 DNS 策略
|
||||
"`ClusterFirstWithHostNet`"。
|
||||
- 注意:这在 Windows 上不支持。 有关详细信息,请参见[下文](#dns-windows)。
|
||||
- "`None`": 此设置允许 Pod 忽略 Kubernetes 环境中的 DNS 设置。Pod 会使用其 `dnsConfig` 字段
|
||||
所提供的 DNS 设置。
|
||||
参见 [Pod 的 DNS 配置](#pod-dns-config)节。
|
||||
|
||||
<!--
|
||||
"Default" is not the default DNS policy. If `dnsPolicy` is not
|
||||
explicitly specified, then "ClusterFirst" is used.
|
||||
-->
|
||||
{{< note >}}
|
||||
"Default" 不是默认的 DNS 策略。如果未明确指定 `dnsPolicy`,则使用 "ClusterFirst"。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
The example below shows a Pod with its DNS policy set to
|
||||
"`ClusterFirstWithHostNet`" because it has `hostNetwork` set to `true`.
|
||||
-->
|
||||
下面的示例显示了一个 Pod,其 DNS 策略设置为 "`ClusterFirstWithHostNet`",
|
||||
因为它已将 `hostNetwork` 设置为 `true`。
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: busybox
|
||||
namespace: default
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox:1.28
|
||||
command:
|
||||
- sleep
|
||||
- "3600"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: busybox
|
||||
restartPolicy: Always
|
||||
hostNetwork: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
```
|
||||
|
||||
<!--
|
||||
### Pod's DNS Config {#pod-dns-config}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.14" state="stable" >}}
|
||||
|
||||
Pod's DNS Config allows users more control on the DNS settings for a Pod.
|
||||
|
||||
The `dnsConfig` field is optional and it can work with any `dnsPolicy` settings.
|
||||
However, when a Pod's `dnsPolicy` is set to "`None`", the `dnsConfig` field has
|
||||
to be specified.
|
||||
|
||||
Below are the properties a user can specify in the `dnsConfig` field:
|
||||
-->
|
||||
### Pod 的 DNS 配置 {#pod-dns-config}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.14" state="stable" >}}
|
||||
|
||||
Pod 的 DNS 配置可让用户对 Pod 的 DNS 设置进行更多控制。
|
||||
|
||||
`dnsConfig` 字段是可选的,它可以与任何 `dnsPolicy` 设置一起使用。
|
||||
但是,当 Pod 的 `dnsPolicy` 设置为 "`None`" 时,必须指定 `dnsConfig` 字段。
|
||||
|
||||
用户可以在 `dnsConfig` 字段中指定以下属性:
|
||||
|
||||
<!--
|
||||
- `nameservers`: a list of IP addresses that will be used as DNS servers for the
|
||||
Pod. There can be at most 3 IP addresses specified. When the Pod's `dnsPolicy`
|
||||
is set to "`None`", the list must contain at least one IP address, otherwise
|
||||
this property is optional.
|
||||
The servers listed will be combined to the base nameservers generated from the
|
||||
specified DNS policy with duplicate addresses removed.
|
||||
- `searches`: a list of DNS search domains for hostname lookup in the Pod.
|
||||
This property is optional. When specified, the provided list will be merged
|
||||
into the base search domain names generated from the chosen DNS policy.
|
||||
Duplicate domain names are removed.
|
||||
Kubernetes allows for at most 6 search domains.
|
||||
- `options`: an optional list of objects where each object may have a `name`
|
||||
property (required) and a `value` property (optional). The contents in this
|
||||
property will be merged to the options generated from the specified DNS policy.
|
||||
Duplicate entries are removed.
|
||||
-->
|
||||
|
||||
- `nameservers`:将用作于 Pod 的 DNS 服务器的 IP 地址列表。
|
||||
最多可以指定 3 个 IP 地址。当 Pod 的 `dnsPolicy` 设置为 "`None`" 时,
|
||||
列表必须至少包含一个 IP 地址,否则此属性是可选的。
|
||||
所列出的服务器将合并到从指定的 DNS 策略生成的基本名称服务器,并删除重复的地址。
|
||||
|
||||
- `searches`:用于在 Pod 中查找主机名的 DNS 搜索域的列表。此属性是可选的。
|
||||
指定此属性时,所提供的列表将合并到根据所选 DNS 策略生成的基本搜索域名中。
|
||||
重复的域名将被删除。Kubernetes 最多允许 6 个搜索域。
|
||||
|
||||
- `options`:可选的对象列表,其中每个对象可能具有 `name` 属性(必需)和 `value` 属性(可选)。
|
||||
此属性中的内容将合并到从指定的 DNS 策略生成的选项。
|
||||
重复的条目将被删除。
|
||||
|
||||
<!--
|
||||
The following is an example Pod with custom DNS settings:
|
||||
-->
|
||||
以下是具有自定义 DNS 设置的 Pod 示例:
|
||||
|
||||
{{< codenew file="service/networking/custom-dns.yaml" >}}
|
||||
|
||||
<!--
|
||||
When the Pod above is created, the container `test` gets the following contents
|
||||
in its `/etc/resolv.conf` file:
|
||||
-->
|
||||
创建上面的 Pod 后,容器 `test` 会在其 `/etc/resolv.conf` 文件中获取以下内容:
|
||||
|
||||
```
|
||||
nameserver 1.2.3.4
|
||||
search ns1.svc.cluster-domain.example my.dns.search.suffix
|
||||
options ndots:2 edns0
|
||||
```
|
||||
|
||||
<!--
|
||||
For IPv6 setup, search path and name server should be setup like this:
|
||||
-->
|
||||
对于 IPv6 设置,搜索路径和名称服务器应按以下方式设置:
|
||||
|
||||
```shell
|
||||
kubectl exec -it dns-example -- cat /etc/resolv.conf
|
||||
```
|
||||
|
||||
<!--
|
||||
The output is similar to this:
|
||||
-->
|
||||
输出类似于:
|
||||
```
|
||||
nameserver fd00:79:30::a
|
||||
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
|
||||
options ndots:5
|
||||
```
|
||||
|
||||
<!--
|
||||
#### Expanded DNS Configuration
|
||||
|
||||
{{< feature-state for_k8s_version="1.22" state="alpha" >}}
|
||||
|
||||
By default, for Pod's DNS Config, Kubernetes allows at most 6 search domains and
|
||||
a list of search domains of up to 256 characters.
|
||||
|
||||
If the feature gate `ExpandedDNSConfig` is enabled for the kube-apiserver and
|
||||
the kubelet, it is allowed for Kubernetes to have at most 32 search domains and
|
||||
a list of search domains of up to 2048 characters.
|
||||
-->
|
||||
#### 扩展 DNS 配置 {#expanded-dns-configuration}
|
||||
|
||||
{{< feature-state for_k8s_version="1.22" state="alpha" >}}
|
||||
|
||||
对于 Pod DNS 配置,Kubernetes 默认允许最多 6 个 搜索域( Search Domain)
|
||||
以及一个最多 256 个字符的搜索域列表。
|
||||
|
||||
如果启用 kube-apiserver 和 kubelet 的特性门控 `ExpandedDNSConfig`,Kubernetes 将可以有最多 32 个
|
||||
搜索域以及一个最多 2048 个字符的搜索域列表。
|
||||
|
||||
<!--
|
||||
## DNS resolution on Windows nodes {#dns-windows}
|
||||
|
||||
- ClusterFirstWithHostNet is not supported for Pods that run on Windows nodes.
|
||||
Windows treats all names with a `.` as a FQDN and skips FQDN resolution.
|
||||
- On Windows, there are multiple DNS resolvers that can be used. As these come with
|
||||
slightly different behaviors, using the
|
||||
[`Resolve-DNSName`](https://docs.microsoft.com/powershell/module/dnsclient/resolve-dnsname)
|
||||
powershell cmdlet for name query resolutions is recommended.
|
||||
- On Linux, you have a DNS suffix list, which is used after resolution of a name as fully
|
||||
qualified has failed.
|
||||
On Windows, you can only have 1 DNS suffix, which is the DNS suffix associated with that
|
||||
Pod's namespace (example: `mydns.svc.cluster.local`). Windows can resolve FQDNs, Services,
|
||||
or network name which can be resolved with this single suffix. For example, a Pod spawned
|
||||
in the `default` namespace, will have the DNS suffix `default.svc.cluster.local`.
|
||||
Inside a Windows Pod, you can resolve both `kubernetes.default.svc.cluster.local`
|
||||
and `kubernetes`, but not the partially qualified names (`kubernetes.default` or
|
||||
`kubernetes.default.svc`).
|
||||
-->
|
||||
## Windows 节点上的 DNS 解析 {#dns-windows}
|
||||
|
||||
- 在 Windows 节点上运行的 Pod 不支持 ClusterFirstWithHostNet。
|
||||
Windows 将所有带有 `.` 的名称视为全限定域名(FQDN)并跳过全限定域名(FQDN)解析。
|
||||
- 在 Windows 上,可以使用的 DNS 解析器有很多。
|
||||
由于这些解析器彼此之间会有轻微的行为差别,建议使用
|
||||
[`Resolve-DNSName`](https://docs.microsoft.com/powershell/module/dnsclient/resolve-dnsname)
|
||||
powershell cmdlet 进行名称查询解析。
|
||||
- 在 Linux 上,有一个 DNS 后缀列表,当解析全名失败时可以使用。
|
||||
在 Windows 上,你只能有一个 DNS 后缀,
|
||||
即与该 Pod 的命名空间相关联的 DNS 后缀(例如:`mydns.svc.cluster.local`)。
|
||||
Windows 可以解析全限定域名(FQDN),和使用了该 DNS 后缀的 Services 或者网络名称。
|
||||
例如,在 `default` 命名空间中生成一个 Pod,该 Pod 会获得的 DNS 后缀为 `default.svc.cluster.local`。
|
||||
在 Windows 的 Pod 中,你可以解析 `kubernetes.default.svc.cluster.local` 和 `kubernetes`,
|
||||
但是不能解析部分限定名称(`kubernetes.default` 和 `kubernetes.default.svc`)。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
For guidance on administering DNS configurations, check
|
||||
[Configure DNS Service](/docs/tasks/administer-cluster/dns-custom-nameservers/)
|
||||
-->
|
||||
有关管理 DNS 配置的指导,请查看
|
||||
[配置 DNS 服务](/zh/docs/tasks/administer-cluster/dns-custom-nameservers/)
|
||||
|
||||
@@ -0,0 +1,511 @@
|
||||
---
|
||||
title: IPv4/IPv6 双协议栈
|
||||
feature:
|
||||
title: IPv4/IPv6 双协议栈
|
||||
description: >
|
||||
为 Pod 和 Service 分配 IPv4 和 IPv6 地址
|
||||
content_type: concept
|
||||
weight: 70
|
||||
---
|
||||
|
||||
<!--
|
||||
reviewers:
|
||||
- lachie83
|
||||
- khenidak
|
||||
- aramase
|
||||
- bridgetkromhout
|
||||
title: IPv4/IPv6 dual-stack
|
||||
feature:
|
||||
title: IPv4/IPv6 dual-stack
|
||||
description: >
|
||||
Allocation of IPv4 and IPv6 addresses to Pods and Services
|
||||
|
||||
content_type: concept
|
||||
weight: 70
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.23" state="stable" >}}
|
||||
|
||||
<!--
|
||||
IPv4/IPv6 dual-stack networking enables the allocation of both IPv4 and IPv6 addresses to {{< glossary_tooltip text="Pods" term_id="pod" >}} and {{< glossary_tooltip text="Services" term_id="service" >}}.
|
||||
-->
|
||||
IPv4/IPv6 双协议栈网络能够将 IPv4 和 IPv6 地址分配给
|
||||
{{< glossary_tooltip text="Pod" term_id="pod" >}} 和
|
||||
{{< glossary_tooltip text="Service" term_id="service" >}}。
|
||||
|
||||
<!--
|
||||
IPv4/IPv6 dual-stack networking is enabled by default for your Kubernetes cluster starting in 1.21, allowing the simultaneous assignment of both IPv4 and IPv6 addresses.
|
||||
-->
|
||||
从 1.21 版本开始,Kubernetes 集群默认启用 IPv4/IPv6 双协议栈网络,
|
||||
以支持同时分配 IPv4 和 IPv6 地址。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Supported Features
|
||||
-->
|
||||
## 支持的功能 {#supported-features}
|
||||
|
||||
<!--
|
||||
IPv4/IPv6 dual-stack on your Kubernetes cluster provides the following features:
|
||||
-->
|
||||
Kubernetes 集群的 IPv4/IPv6 双协议栈可提供下面的功能:
|
||||
|
||||
<!--
|
||||
* Dual-stack Pod networking (a single IPv4 and IPv6 address assignment per Pod)
|
||||
* IPv4 and IPv6 enabled Services
|
||||
* Pod off-cluster egress routing (eg. the Internet) via both IPv4 and IPv6 interfaces
|
||||
-->
|
||||
* 双协议栈 pod 网络 (每个 pod 分配一个 IPv4 和 IPv6 地址)
|
||||
* IPv4 和 IPv6 启用的服务
|
||||
* Pod 的集群外出口通过 IPv4 和 IPv6 路由
|
||||
|
||||
<!--
|
||||
## Prerequisites
|
||||
-->
|
||||
## 先决条件 {#prerequisites}
|
||||
|
||||
<!--
|
||||
The following prerequisites are needed in order to utilize IPv4/IPv6 dual-stack Kubernetes clusters:
|
||||
-->
|
||||
为了使用 IPv4/IPv6 双栈的 Kubernetes 集群,需要满足以下先决条件:
|
||||
|
||||
<!--
|
||||
* Kubernetes 1.20 or later
|
||||
For information about using dual-stack services with earlier
|
||||
Kubernetes versions, refer to the documentation for that version
|
||||
of Kubernetes.
|
||||
* Provider support for dual-stack networking (Cloud provider or otherwise must be able to provide Kubernetes nodes with routable IPv4/IPv6 network interfaces)
|
||||
* A [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) that supports dual-stack networking.
|
||||
-->
|
||||
* Kubernetes 1.20 版本或更高版本,有关更早 Kubernetes 版本的使用双栈服务的信息,
|
||||
请参考对应版本的 Kubernetes 文档。
|
||||
* 提供商支持双协议栈网络(云提供商或其他提供商必须能够为 Kubernetes
|
||||
节点提供可路由的 IPv4/IPv6 网络接口)
|
||||
* 支持双协议栈的[网络插件](/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
|
||||
|
||||
<!--
|
||||
## Configure IPv4/IPv6 dual-stack
|
||||
-->
|
||||
## 配置 IPv4/IPv6 双协议栈
|
||||
|
||||
<!--
|
||||
To configure IPv4/IPv6 dual-stack, set dual-stack cluster network assignments:
|
||||
-->
|
||||
如果配置 IPv4/IPv6 双栈,请分配双栈集群网络:
|
||||
<!--
|
||||
* kube-apiserver:
|
||||
* `--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* kube-controller-manager:
|
||||
* `--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* `--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* `--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6` defaults to /24 for IPv4 and /64 for IPv6
|
||||
* kube-proxy:
|
||||
* `--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* kubelet:
|
||||
* when there is no `--cloud-provider` the administrator can pass a comma-separated pair
|
||||
of IP addresses via `--node-ip` to manually configure dual-stack `.status.addresses`
|
||||
for that Node.
|
||||
If a Pod runs on that node in HostNetwork mode, the Pod reports these IP addresses in its
|
||||
`.status.podIPs` field.
|
||||
All `podIPs` in a node match the IP family preference defined by the
|
||||
`.status.addresses` field for that Node.
|
||||
-->
|
||||
* kube-apiserver:
|
||||
* `--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* kube-controller-manager:
|
||||
* `--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* `--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* `--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6` 对于 IPv4 默认为 /24,对于 IPv6 默认为 /64
|
||||
* kube-proxy:
|
||||
* `--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>`
|
||||
* kubelet:
|
||||
* 当没有 `--cloud-provider` 时,管理员可以通过 `--node-ip` 来传递逗号分隔的 IP 地址,
|
||||
为该节点手动配置双栈 `.status.addresses`。
|
||||
如果 Pod 以 HostNetwork 模式在该节点上运行,则 Pod 会用 `.status.podIPs` 字段来报告它的 IP 地址。
|
||||
一个节点中的所有 `podIP` 都会匹配该节点的由 `.status.addresses` 字段定义的 IP 组。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
An example of an IPv4 CIDR: `10.244.0.0/16` (though you would supply your own address range)
|
||||
|
||||
An example of an IPv6 CIDR: `fdXY:IJKL:MNOP:15::/64` (this shows the format but is not a valid address - see [RFC 4193](https://tools.ietf.org/html/rfc4193))
|
||||
-->
|
||||
IPv4 CIDR 的一个例子:`10.244.0.0/16`(尽管你会提供你自己的地址范围)。
|
||||
|
||||
IPv6 CIDR 的一个例子:`fdXY:IJKL:MNOP:15::/64`
|
||||
(这里演示的是格式而非有效地址 - 请看 [RFC 4193](https://tools.ietf.org/html/rfc4193))。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
## Services
|
||||
-->
|
||||
## 服务
|
||||
|
||||
<!--
|
||||
You can create {{< glossary_tooltip text="Services" term_id="service" >}} which can use IPv4, IPv6, or both.
|
||||
|
||||
The address family of a Service defaults to the address family of the first service cluster IP range (configured via the `--service-cluster-ip-range` flag to the kube-apiserver).
|
||||
|
||||
When you define a Service you can optionally configure it as dual stack. To specify the behavior you want, you
|
||||
set the `.spec.ipFamilyPolicy` field to one of the following values:
|
||||
-->
|
||||
你可以使用 IPv4 或 IPv6 地址来创建
|
||||
{{< glossary_tooltip text="Service" term_id="service" >}}。
|
||||
服务的地址族默认为第一个服务集群 IP 范围的地址族(通过 kube-apiserver 的
|
||||
`--service-cluster-ip-range` 参数配置)。
|
||||
当你定义服务时,可以选择将其配置为双栈。若要指定所需的行为,你可以设置
|
||||
`.spec.ipFamilyPolicy` 字段为以下值之一:
|
||||
|
||||
<!--
|
||||
* `SingleStack`: Single-stack service. The control plane allocates a cluster IP for the Service, using the first configured service cluster IP range.
|
||||
* `PreferDualStack`:
|
||||
* Allocates IPv4 and IPv6 cluster IPs for the Service.
|
||||
* `RequireDualStack`: Allocates Service `.spec.ClusterIPs` from both IPv4 and IPv6 address ranges.
|
||||
* Selects the `.spec.ClusterIP` from the list of `.spec.ClusterIPs` based on the address family of the first element in the `.spec.ipFamilies` array.
|
||||
-->
|
||||
|
||||
* `SingleStack`:单栈服务。控制面使用第一个配置的服务集群 IP 范围为服务分配集群 IP。
|
||||
* `PreferDualStack`:
|
||||
* 为服务分配 IPv4 和 IPv6 集群 IP 地址。
|
||||
* `RequireDualStack`:从 IPv4 和 IPv6 的地址范围分配服务的 `.spec.ClusterIPs`
|
||||
* 从基于在 `.spec.ipFamilies` 数组中第一个元素的地址族的 `.spec.ClusterIPs`
|
||||
列表中选择 `.spec.ClusterIP`
|
||||
|
||||
<!--
|
||||
If you would like to define which IP family to use for single stack or define the order of IP families for dual-stack, you can choose the address families by setting an optional field, `.spec.ipFamilies`, on the Service.
|
||||
-->
|
||||
如果你想要定义哪个 IP 族用于单栈或定义双栈 IP 族的顺序,可以通过设置
|
||||
服务上的可选字段 `.spec.ipFamilies` 来选择地址族。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
The `.spec.ipFamilies` field is immutable because the `.spec.ClusterIP` cannot be reallocated on a Service that already exists. If you want to change `.spec.ipFamilies`, delete and recreate the Service.
|
||||
-->
|
||||
`.spec.ipFamilies` 字段是不可变的,因为系统无法为已经存在的服务重新分配
|
||||
`.spec.ClusterIP`。如果你想改变 `.spec.ipFamilies`,则需要删除并重新创建服务。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
You can set `.spec.ipFamilies` to any of the following array values:
|
||||
-->
|
||||
你可以设置 `.spec.ipFamily` 为以下任何数组值:
|
||||
|
||||
<!--
|
||||
- `["IPv4"]`
|
||||
- `["IPv6"]`
|
||||
- `["IPv4","IPv6"]` (dual stack)
|
||||
- `["IPv6","IPv4"]` (dual stack)
|
||||
-->
|
||||
- `["IPv4"]`
|
||||
- `["IPv6"]`
|
||||
- `["IPv4","IPv6"]` (双栈)
|
||||
- `["IPv6","IPv4"]` (双栈)
|
||||
|
||||
<!--
|
||||
The first family you list is used for the legacy `.spec.ClusterIP` field.
|
||||
-->
|
||||
你所列出的第一个地址族用于原来的 `.spec.ClusterIP` 字段。
|
||||
|
||||
<!--
|
||||
### Dual-stack Service configuration scenarios
|
||||
|
||||
These examples demonstrate the behavior of various dual-stack Service configuration scenarios.
|
||||
-->
|
||||
### 双栈服务配置场景
|
||||
|
||||
以下示例演示多种双栈服务配置场景下的行为。
|
||||
|
||||
<!--
|
||||
#### Dual-stack options on new Services
|
||||
-->
|
||||
#### 新服务的双栈选项
|
||||
|
||||
<!--
|
||||
1. This Service specification does not explicitly define `.spec.ipFamilyPolicy`. When you create this Service, Kubernetes assigns a cluster IP for the Service from the first configured `service-cluster-ip-range` and sets the `.spec.ipFamilyPolicy` to `SingleStack`. ([Services without selectors](/docs/concepts/services-networking/service/#services-without-selectors) and [headless Services](/docs/concepts/services-networking/service/#headless-services) with selectors will behave in this same way.)
|
||||
-->
|
||||
1. 此服务规约中没有显式设定 `.spec.ipFamilyPolicy`。当你创建此服务时,Kubernetes
|
||||
从所配置的第一个 `service-cluster-ip-range` 种为服务分配一个集群IP,并设置
|
||||
`.spec.ipFamilyPolicy` 为 `SingleStack`。
|
||||
([无选择算符的服务](/zh/docs/concepts/services-networking/service/#services-without-selectors)
|
||||
和[无头服务](/zh/docs/concepts/services-networking/service/#headless-services)的行为方式
|
||||
与此相同。)
|
||||
|
||||
{{< codenew file="service/networking/dual-stack-default-svc.yaml" >}}
|
||||
|
||||
<!--
|
||||
1. This Service specification explicitly defines `PreferDualStack` in `.spec.ipFamilyPolicy`. When you create this Service on a dual-stack cluster, Kubernetes assigns both IPv4 and IPv6 addresses for the service. The control plane updates the `.spec` for the Service to record the IP address assignments. The field `.spec.ClusterIPs` is the primary field, and contains both assigned IP addresses; `.spec.ClusterIP` is a secondary field with its value calculated from `.spec.ClusterIPs`.
|
||||
|
||||
* For the `.spec.ClusterIP` field, the control plane records the IP address that is from the same address family as the first service cluster IP range.
|
||||
* On a single-stack cluster, the `.spec.ClusterIPs` and `.spec.ClusterIP` fields both only list one address.
|
||||
* On a cluster with dual-stack enabled, specifying `RequireDualStack` in `.spec.ipFamilyPolicy` behaves the same as `PreferDualStack`.
|
||||
|
||||
-->
|
||||
2. 此服务规约显式地将 `.spec.ipFamilyPolicy` 设置为 `PreferDualStack`。
|
||||
当你在双栈集群上创建此服务时,Kubernetes 会为该服务分配 IPv4 和 IPv6 地址。
|
||||
控制平面更新服务的 `.spec` 以记录 IP 地址分配。
|
||||
字段 `.spec.ClusterIPs` 是主要字段,包含两个分配的 IP 地址;`.spec.ClusterIP` 是次要字段,
|
||||
其取值从 `.spec.ClusterIPs` 计算而来。
|
||||
|
||||
* 对于 `.spec.ClusterIP` 字段,控制面记录来自第一个服务集群 IP 范围
|
||||
对应的地址族的 IP 地址。
|
||||
* 对于单协议栈的集群,`.spec.ClusterIPs` 和 `.spec.ClusterIP` 字段都
|
||||
仅仅列出一个地址。
|
||||
* 对于启用了双协议栈的集群,将 `.spec.ipFamilyPolicy` 设置为
|
||||
`RequireDualStack` 时,其行为与 `PreferDualStack` 相同。
|
||||
|
||||
{{< codenew file="service/networking/dual-stack-preferred-svc.yaml" >}}
|
||||
|
||||
<!--
|
||||
1. This Service specification explicitly defines `IPv6` and `IPv4` in `.spec.ipFamilies` as well as defining `PreferDualStack` in `.spec.ipFamilyPolicy`. When Kubernetes assigns an IPv6 and IPv4 address in `.spec.ClusterIPs`, `.spec.ClusterIP` is set to the IPv6 address because that is the first element in the `.spec.ClusterIPs` array, overriding the default.
|
||||
-->
|
||||
3. 下面的服务规约显式地在 `.spec.ipFamilies` 中指定 `IPv6` 和 `IPv4`,并
|
||||
将 `.spec.ipFamilyPolicy` 设定为 `PreferDualStack`。
|
||||
当 Kubernetes 为 `.spec.ClusterIPs` 分配一个 IPv6 和一个 IPv4 地址时,
|
||||
`.spec.ClusterIP` 被设置成 IPv6 地址,因为它是 `.spec.ClusterIPs` 数组中的第一个元素,
|
||||
覆盖其默认值。
|
||||
|
||||
{{< codenew file="service/networking/dual-stack-preferred-ipfamilies-svc.yaml" >}}
|
||||
|
||||
<!--
|
||||
#### Dual-stack defaults on existing Services
|
||||
-->
|
||||
#### 现有服务的双栈默认值
|
||||
|
||||
<!--
|
||||
These examples demonstrate the default behavior when dual-stack is newly enabled on a cluster where Services already exist. (Upgrading an existing cluster to 1.21 or beyond will enable dual-stack.)
|
||||
-->
|
||||
下面示例演示了在服务已经存在的集群上新启用双栈时的默认行为。
|
||||
(将现有集群升级到 1.21 或者更高版本会启用双协议栈支持。)
|
||||
|
||||
<!--
|
||||
1. When dual-stack is enabled on a cluster, existing Services (whether `IPv4` or `IPv6`) are configured by the control plane to set `.spec.ipFamilyPolicy` to `SingleStack` and set `.spec.ipFamilies` to the address family of the existing Service. The existing Service cluster IP will be stored in `.spec.ClusterIPs`.
|
||||
-->
|
||||
1. 在集群上启用双栈时,控制面会将现有服务(无论是 `IPv4` 还是 `IPv6`)配置
|
||||
`.spec.ipFamilyPolicy` 为 `SingleStack` 并设置 `.spec.ipFamilies`
|
||||
为服务的当前地址族。
|
||||
|
||||
{{< codenew file="service/networking/dual-stack-default-svc.yaml" >}}
|
||||
|
||||
<!--
|
||||
You can validate this behavior by using kubectl to inspect an existing service.
|
||||
-->
|
||||
你可以通过使用 kubectl 检查现有服务来验证此行为。
|
||||
|
||||
```shell
|
||||
kubectl get svc my-service -o yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: MyApp
|
||||
name: my-service
|
||||
spec:
|
||||
clusterIP: 10.0.197.123
|
||||
clusterIPs:
|
||||
- 10.0.197.123
|
||||
ipFamilies:
|
||||
- IPv4
|
||||
ipFamilyPolicy: SingleStack
|
||||
ports:
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: MyApp
|
||||
type: ClusterIP
|
||||
status:
|
||||
loadBalancer: {}
|
||||
```
|
||||
|
||||
<!--
|
||||
1. When dual-stack is enabled on a cluster, existing [headless Services](/docs/concepts/services-networking/service/#headless-services) with selectors are configured by the control plane to set `.spec.ipFamilyPolicy` to `SingleStack` and set `.spec.ipFamilies` to the address family of the first service cluster IP range (configured via the `--service-cluster-ip-range` flag to the kube-apiserver) even though `.spec.ClusterIP` is set to `None`.
|
||||
-->
|
||||
2. 在集群上启用双栈时,带有选择算符的现有
|
||||
[无头服务](/zh/docs/concepts/services-networking/service/#headless-services)
|
||||
由控制面设置 `.spec.ipFamilyPolicy` 为 `SingleStack`
|
||||
并设置 `.spec.ipFamilies` 为第一个服务集群 IP 范围的地址族(通过配置 kube-apiserver 的
|
||||
`--service-cluster-ip-range` 参数),即使 `.spec.ClusterIP` 的设置值为 `None` 也如此。
|
||||
|
||||
{{< codenew file="service/networking/dual-stack-default-svc.yaml" >}}
|
||||
|
||||
<!--
|
||||
You can validate this behavior by using kubectl to inspect an existing headless service with selectors.
|
||||
-->
|
||||
你可以通过使用 kubectl 检查带有选择算符的现有无头服务来验证此行为。
|
||||
|
||||
```shell
|
||||
kubectl get svc my-service -o yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: MyApp
|
||||
name: my-service
|
||||
spec:
|
||||
clusterIP: None
|
||||
clusterIPs:
|
||||
- None
|
||||
ipFamilies:
|
||||
- IPv4
|
||||
ipFamilyPolicy: SingleStack
|
||||
ports:
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: MyApp
|
||||
```
|
||||
|
||||
<!--
|
||||
#### Switching Services between single-stack and dual-stack
|
||||
-->
|
||||
#### 在单栈和双栈之间切换服务
|
||||
|
||||
<!--
|
||||
Services can be changed from single-stack to dual-stack and from dual-stack to single-stack.
|
||||
-->
|
||||
服务可以从单栈更改为双栈,也可以从双栈更改为单栈。
|
||||
|
||||
<!--
|
||||
1. To change a Service from single-stack to dual-stack, change `.spec.ipFamilyPolicy` from `SingleStack` to `PreferDualStack` or `RequireDualStack` as desired. When you change this Service from single-stack to dual-stack, Kubernetes assigns the missing address family so that the Service now has IPv4 and IPv6 addresses.
|
||||
|
||||
Edit the Service specification updating the `.spec.ipFamilyPolicy` from `SingleStack` to `PreferDualStack`.
|
||||
-->
|
||||
1. 要将服务从单栈更改为双栈,根据需要将 `.spec.ipFamilyPolicy` 从 `SingleStack` 改为
|
||||
`PreferDualStack` 或 `RequireDualStack`。
|
||||
当你将此服务从单栈更改为双栈时,Kubernetes 将分配缺失的地址族,以便现在
|
||||
该服务具有 IPv4 和 IPv6 地址。
|
||||
编辑服务规约将 `.spec.ipFamilyPolicy` 从 `SingleStack` 改为 `PreferDualStack`。
|
||||
|
||||
<!--
|
||||
Before:
|
||||
-->
|
||||
之前:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
ipFamilyPolicy: SingleStack
|
||||
```
|
||||
|
||||
<!--
|
||||
After:
|
||||
-->
|
||||
之后:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
ipFamilyPolicy: PreferDualStack
|
||||
```
|
||||
|
||||
<!--
|
||||
1. To change a Service from dual-stack to single-stack, change `.spec.ipFamilyPolicy` from `PreferDualStack` or `RequireDualStack` to `SingleStack`. When you change this Service from dual-stack to single-stack, Kubernetes retains only the first element in the `.spec.ClusterIPs` array, and sets `.spec.ClusterIP` to that IP address and sets `.spec.ipFamilies` to the address family of `.spec.ClusterIPs`.
|
||||
-->
|
||||
|
||||
2. 要将服务从双栈更改为单栈,请将 `.spec.ipFamilyPolicy` 从 `PreferDualStack` 或
|
||||
`RequireDualStack` 改为 `SingleStack`。
|
||||
当你将此服务从双栈更改为单栈时,Kubernetes 只保留 `.spec.ClusterIPs`
|
||||
数组中的第一个元素,并设置 `.spec.ClusterIP` 为那个 IP 地址,
|
||||
并设置 `.spec.ipFamilies` 为 `.spec.ClusterIPs` 地址族。
|
||||
|
||||
<!--
|
||||
### Headless Services without selector
|
||||
-->
|
||||
### 无选择算符的无头服务
|
||||
|
||||
<!--
|
||||
For [Headless Services without selectors](/docs/concepts/services-networking/service/#without-selectors) and without `.spec.ipFamilyPolicy` explicitly set, the `.spec.ipFamilyPolicy` field defaults to `RequireDualStack`.
|
||||
-->
|
||||
对于[不带选择算符的无头服务](/zh/docs/concepts/services-networking/service/#without-selectors),
|
||||
若没有显式设置 `.spec.ipFamilyPolicy`,则 `.spec.ipFamilyPolicy`
|
||||
字段默认设置为 `RequireDualStack`。
|
||||
|
||||
<!--
|
||||
### Service type LoadBalancer
|
||||
-->
|
||||
### LoadBalancer 类型服务
|
||||
|
||||
<!--
|
||||
To provision a dual-stack load balancer for your Service:
|
||||
* Set the `.spec.type` field to `LoadBalancer`
|
||||
* Set `.spec.ipFamilyPolicy` field to `PreferDualStack` or `RequireDualStack`
|
||||
-->
|
||||
要为你的服务提供双栈负载均衡器:
|
||||
|
||||
* 将 `.spec.type` 字段设置为 `LoadBalancer`
|
||||
* 将 `.spec.ipFamilyPolicy` 字段设置为 `PreferDualStack` 或者 `RequireDualStack`
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
To use a dual-stack `LoadBalancer` type Service, your cloud provider must support IPv4 and IPv6 load balancers.
|
||||
-->
|
||||
为了使用双栈的负载均衡器类型服务,你的云驱动必须支持 IPv4 和 IPv6 的负载均衡器。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
## Egress traffic
|
||||
-->
|
||||
## 出站流量
|
||||
|
||||
<!--
|
||||
If you want to enable egress traffic in order to reach off-cluster destinations (eg. the public Internet) from a Pod that uses non-publicly routable IPv6 addresses, you need to enable the Pod to use a publicly routed IPv6 address via a mechanism such as transparent proxying or IP masquerading. The [ip-masq-agent](https://github.com/kubernetes-sigs/ip-masq-agent) project supports IP masquerading on dual-stack clusters.
|
||||
-->
|
||||
如果你要启用出站流量,以便使用非公开路由 IPv6 地址的 Pod 到达集群外地址
|
||||
(例如公网),则需要通过透明代理或 IP 伪装等机制使 Pod 使用公共路由的
|
||||
IPv6 地址。
|
||||
[ip-masq-agent](https://github.com/kubernetes-sigs/ip-masq-agent)项目
|
||||
支持在双栈集群上进行 IP 伪装。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
Ensure your {{< glossary_tooltip text="CNI" term_id="cni" >}} provider supports IPv6.
|
||||
-->
|
||||
确认你的 {{< glossary_tooltip text="CNI" term_id="cni" >}} 驱动支持 IPv6。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
## Windows support
|
||||
|
||||
Kubernetes on Windows does not support single-stack "IPv6-only" networking. However,
|
||||
dual-stack IPv4/IPv6 networking for pods and nodes with single-family services
|
||||
is supported.
|
||||
|
||||
You can use IPv4/IPv6 dual-stack networking with `l2bridge` networks.
|
||||
|
||||
{{< note >}}
|
||||
Overlay (VXLAN) networks on Windows **do not** support dual-stack networking.
|
||||
{{< /note >}}
|
||||
|
||||
You can read more about the different network modes for Windows within the
|
||||
[Networking on Windows](/docs/concepts/services-networking/windows-networking#network-modes) topic.
|
||||
-->
|
||||
## Windows 支持
|
||||
|
||||
Windows 上的 Kubernetes 不支持单栈“仅 IPv6” 网络。 然而,
|
||||
对于 Pod 和节点而言,仅支持单栈形式服务的双栈 IPv4/IPv6 网络是被支持的。
|
||||
|
||||
你可以使用 `l2bridge` 网络来实现 IPv4/IPv6 双栈联网。
|
||||
|
||||
{{< note >}}
|
||||
Windows 上的 Overlay (VXLAN) 网络**不**支持双栈网络。
|
||||
{{< /note >}}
|
||||
|
||||
关于 Windows 的不同网络模式,你可以进一步阅读
|
||||
[Windows 上的网络](/zh/docs/concepts/services-networking/windows-networking#network-modes)。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
* [Validate IPv4/IPv6 dual-stack](/docs/tasks/network/validate-dual-stack) networking
|
||||
* [Enable dual-stack networking using kubeadm](/docs/setup/production-environment/tools/kubeadm/dual-stack-support/)
|
||||
-->
|
||||
* [验证 IPv4/IPv6 双协议栈](/zh/docs/tasks/network/validate-dual-stack)网络
|
||||
* [使用 kubeadm 启用双协议栈网络](/zh/docs/setup/production-environment/tools/kubeadm/dual-stack-support/)
|
||||
@@ -0,0 +1,463 @@
|
||||
---
|
||||
title: 端点切片(Endpoint Slices)
|
||||
content_type: concept
|
||||
weight: 45
|
||||
---
|
||||
|
||||
<!--
|
||||
reviewers:
|
||||
- freehan
|
||||
title: Endpoint Slices
|
||||
content_type: concept
|
||||
weight: 45
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.21" state="stable" >}}
|
||||
|
||||
<!--
|
||||
_EndpointSlices_ provide a simple way to track network endpoints within a
|
||||
Kubernetes cluster. They offer a more scalable and extensible alternative to
|
||||
Endpoints.
|
||||
-->
|
||||
_端点切片(EndpointSlices)_ 提供了一种简单的方法来跟踪 Kubernetes 集群中的网络端点
|
||||
(network endpoints)。它们为 Endpoints 提供了一种可伸缩和可拓展的替代方案。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Motivation
|
||||
|
||||
The Endpoints API has provided a simple and straightforward way of
|
||||
tracking network endpoints in Kubernetes. Unfortunately as Kubernetes clusters
|
||||
and {{< glossary_tooltip text="Services" term_id="service" >}} have grown to handle and
|
||||
send more traffic to more backend Pods, limitations of that original API became
|
||||
more visible.
|
||||
Most notably, those included challenges with scaling to larger numbers of
|
||||
network endpoints.
|
||||
-->
|
||||
## 动机 {#motivation}
|
||||
|
||||
Endpoints API 提供了在 Kubernetes 跟踪网络端点的一种简单而直接的方法。
|
||||
不幸的是,随着 Kubernetes 集群和 {{< glossary_tooltip text="服务" term_id="service" >}}
|
||||
逐渐开始为更多的后端 Pods 处理和发送请求,原来的 API 的局限性变得越来越明显。
|
||||
最重要的是那些因为要处理大量网络端点而带来的挑战。
|
||||
|
||||
<!--
|
||||
Since all network endpoints for a Service were stored in a single Endpoints
|
||||
resource, those resources could get quite large. That affected the performance
|
||||
of Kubernetes components (notably the master control plane) and resulted in
|
||||
significant amounts of network traffic and processing when Endpoints changed.
|
||||
EndpointSlices help you mitigate those issues as well as provide an extensible
|
||||
platform for additional features such as topological routing.
|
||||
-->
|
||||
由于任一 Service 的所有网络端点都保存在同一个 Endpoints 资源中,
|
||||
这类资源可能变得非常巨大,而这一变化会影响到 Kubernetes
|
||||
组件(比如主控组件)的性能,并在 Endpoints 变化时产生大量的网络流量和额外的处理。
|
||||
EndpointSlice 能够帮助你缓解这一问题,
|
||||
还能为一些诸如拓扑路由这类的额外功能提供一个可扩展的平台。
|
||||
|
||||
<!--
|
||||
## Endpoint Slice resources {#endpointslice-resource}
|
||||
|
||||
In Kubernetes, an EndpointSlice contains references to a set of network
|
||||
endpoints. The control plane automatically creates EndpointSlices
|
||||
for any Kubernetes Service that has a {{< glossary_tooltip text="selector"
|
||||
term_id="selector" >}} specified. These EndpointSlices include
|
||||
references to any Pods that match the Service selector. EndpointSlices group
|
||||
network endpoints together by unique combinations of protocol, port number, and
|
||||
Service name.
|
||||
The name of a EndpointSlice object must be a valid
|
||||
[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
|
||||
|
||||
As an example, here's a sample EndpointSlice resource for the `example`
|
||||
Kubernetes Service.
|
||||
-->
|
||||
## Endpoint Slice 资源 {#endpointslice-resource}
|
||||
|
||||
在 Kubernetes 中,`EndpointSlice` 包含对一组网络端点的引用。
|
||||
指定选择器后控制面会自动为设置了 {{< glossary_tooltip text="选择算符" term_id="selector" >}}
|
||||
的 Kubernetes Service 创建 EndpointSlice。
|
||||
这些 EndpointSlice 将包含对与 Service 选择算符匹配的所有 Pod 的引用。
|
||||
EndpointSlice 通过唯一的协议、端口号和 Service 名称将网络端点组织在一起。
|
||||
EndpointSlice 的名称必须是合法的
|
||||
[DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。
|
||||
|
||||
例如,下面是 Kubernetes Service `example` 的 EndpointSlice 资源示例。
|
||||
|
||||
```yaml
|
||||
apiVersion: discovery.k8s.io/v1
|
||||
kind: EndpointSlice
|
||||
metadata:
|
||||
name: example-abc
|
||||
labels:
|
||||
kubernetes.io/service-name: example
|
||||
addressType: IPv4
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
endpoints:
|
||||
- addresses:
|
||||
- "10.1.2.3"
|
||||
conditions:
|
||||
ready: true
|
||||
hostname: pod-1
|
||||
nodeName: node-1
|
||||
zone: us-west2-a
|
||||
```
|
||||
|
||||
<!--
|
||||
By default, the control plane creates and manages EndpointSlices to have no
|
||||
more than 100 endpoints each. You can configure this with the
|
||||
`-max-endpoints-per-slice`
|
||||
{{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}}
|
||||
flag, up to a maximum of 1000.
|
||||
|
||||
EndpointSlices can act as the source of truth for
|
||||
{{< glossary_tooltip term_id="kube-proxy" text="kube-proxy" >}} when it comes to
|
||||
how to route internal traffic. When enabled, they should provide a performance
|
||||
improvement for services with large numbers of endpoints.
|
||||
-->
|
||||
默认情况下,控制面创建和管理的 EndpointSlice 将包含不超过 100 个端点。
|
||||
你可以使用 {{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}}
|
||||
的 `--max-endpoints-per-slice` 标志设置此值,最大值为 1000。
|
||||
|
||||
当涉及如何路由内部流量时,EndpointSlice 可以充当
|
||||
{{< glossary_tooltip term_id="kube-proxy" text="kube-proxy" >}}
|
||||
的决策依据。
|
||||
启用该功能后,在服务的端点数量庞大时会有可观的性能提升。
|
||||
|
||||
<!--
|
||||
## Address Types
|
||||
|
||||
EndpointSlices support three address types:
|
||||
|
||||
* IPv4
|
||||
* IPv6
|
||||
* FQDN (Fully Qualified Domain Name)
|
||||
-->
|
||||
## 地址类型
|
||||
|
||||
EndpointSlice 支持三种地址类型:
|
||||
|
||||
* IPv4
|
||||
* IPv6
|
||||
* FQDN (完全合格的域名)
|
||||
|
||||
<!--
|
||||
### Conditions
|
||||
|
||||
The EndpointSlice API stores conditions about endpoints that may be useful for consumers.
|
||||
The three conditions are `ready`, `serving`, and `terminating`.
|
||||
-->
|
||||
### 状况
|
||||
|
||||
EndpointSlice API 存储了可能对使用者有用的、有关端点的状况。
|
||||
这三个状况分别是 `ready`、`serving` 和 `terminating`。
|
||||
|
||||
|
||||
<!--
|
||||
#### Ready
|
||||
|
||||
`ready` is a condition that maps to a Pod's `Ready` condition. A running Pod with the `Ready`
|
||||
condition set to `True` should have this EndpointSlice condition also set to `true`. For
|
||||
compatibility reasons, `ready` is NEVER `true` when a Pod is terminating. Consumers should refer
|
||||
to the `serving` condition to inspect the readiness of terminating Pods. The only exception to
|
||||
this rule is for Services with `spec.publishNotReadyAddresses` set to `true`. Endpoints for these
|
||||
Services will always have the `ready` condition set to `true`.
|
||||
-->
|
||||
#### Ready(就绪)
|
||||
|
||||
`ready` 状况是映射 Pod 的 `Ready` 状况的。
|
||||
处于运行中的 Pod,它的 `Ready` 状况被设置为 `True`,应该将此 EndpointSlice 状况也设置为 `true`。
|
||||
出于兼容性原因,当 Pod 处于终止过程中,`ready` 永远不会为 `true`。
|
||||
消费者应参考 `serving` 状况来检查处于终止中的 Pod 的就绪情况。
|
||||
该规则的唯一例外是将 `spec.publishNotReadyAddresses` 设置为 `true` 的 Service。
|
||||
这些 Service 的端点将始终将 `ready` 状况设置为 `true`。
|
||||
|
||||
<!--
|
||||
#### Serving
|
||||
|
||||
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
|
||||
|
||||
`serving` is identical to the `ready` condition, except it does not account for terminating states.
|
||||
Consumers of the EndpointSlice API should check this condition if they care about pod readiness while
|
||||
the pod is also terminating.
|
||||
-->
|
||||
#### Serving(服务中)
|
||||
|
||||
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
|
||||
|
||||
`serving` 状况与 `ready` 状况相同,不同之处在于它不考虑终止状态。
|
||||
如果 EndpointSlice API 的使用者关心 Pod 终止时的就绪情况,就应检查此状况。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
Although `serving` is almost identical to `ready`, it was added to prevent break the existing meaning
|
||||
of `ready`. It may be unexpected for existing clients if `ready` could be `true` for terminating
|
||||
endpoints, since historically terminating endpoints were never included in the Endpoints or
|
||||
EndpointSlice API to begin with. For this reason, `ready` is _always_ `false` for terminating
|
||||
endpoints, and a new condition `serving` was added in v1.20 so that clients can track readiness
|
||||
for terminating pods independent of the existing semantics for `ready`.
|
||||
-->
|
||||
尽管 `serving` 与 `ready` 几乎相同,但是它是为防止破坏 `ready` 的现有含义而增加的。
|
||||
如果对于处于终止中的端点,`ready` 可能是 `true`,那么对于现有的客户端来说可能是有些意外的,
|
||||
因为从始至终,Endpoints 或 EndpointSlice API 从未包含处于终止中的端点。
|
||||
出于这个原因,`ready` 对于处于终止中的端点 _总是_ `false`,
|
||||
并且在 v1.20 中添加了新的状况 `serving`,以便客户端可以独立于 `ready`
|
||||
的现有语义来跟踪处于终止中的 Pod 的就绪情况。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
#### Terminating
|
||||
|
||||
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
|
||||
|
||||
`Terminating` is a condition that indicates whether an endpoint is terminating.
|
||||
For pods, this is any pod that has a deletion timestamp set.
|
||||
-->
|
||||
#### Terminating(终止中)
|
||||
|
||||
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
|
||||
|
||||
`Terminating` 是表示端点是否处于终止中的状况。
|
||||
对于 Pod 来说,这是设置了删除时间戳的 Pod。
|
||||
|
||||
|
||||
<!--
|
||||
### Topology information {#topology}
|
||||
|
||||
Each endpoint within an EndpointSlice can contain relevant topology information.
|
||||
The topology information includes the location of the endpoint and information
|
||||
about the corresponding Node and zone. These are available in the following
|
||||
per endpoint fields on EndpointSlices:
|
||||
-->
|
||||
### 拓扑信息 {#topology}
|
||||
|
||||
EndpointSlice 中的每个端点都可以包含一定的拓扑信息。
|
||||
拓扑信息包括端点的位置,对应节点、可用区的信息。
|
||||
这些信息体现为 EndpointSlices 的如下端点字段:
|
||||
|
||||
<!--
|
||||
* `nodeName` - The name of the Node this endpoint is on.
|
||||
* `zone` - The zone this endpoint is in.
|
||||
-->
|
||||
* `nodeName` - 端点所在的 Node 名称;
|
||||
* `zone` - 端点所处的可用区。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
In the v1 API, the per endpoint `topology` was effectively removed in favor of
|
||||
the dedicated fields `nodeName` and `zone`.
|
||||
-->
|
||||
在 v1 API 中,逐个端点设置的 `topology` 实际上被去除,
|
||||
以鼓励使用专用的字段 `nodeName` 和 `zone`。
|
||||
|
||||
<!--
|
||||
Setting arbitrary topology fields on the `endpoint` field of an `EndpointSlice`
|
||||
resource has been deprecated and is not supported in the v1 API.
|
||||
Instead, the v1 API supports setting individual `nodeName` and `zone` fields.
|
||||
These fields are automatically translated between API versions. For example, the
|
||||
value of the `"topology.kubernetes.io/zone"` key in the `topology` field in
|
||||
the v1beta1 API is accessible as the `zone` field in the v1 API.
|
||||
-->
|
||||
对 `EndpointSlice` 对象的 `endpoint` 字段设置任意的拓扑结构信息这一操作已被废弃,
|
||||
不再被 v1 API 所支持。取而代之的是 v1 API 所支持的 `nodeName` 和 `zone`
|
||||
这些独立的字段。这些字段可以在不同的 API 版本之间自动完成转译。
|
||||
例如,v1beta1 API 中 `topology` 字段的 `topology.kubernetes.io/zone`
|
||||
取值可以在 v1 API 中通过 `zone` 字段访问。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
### Management
|
||||
|
||||
Most often, the control plane (specifically, the endpoint slice
|
||||
{{< glossary_tooltip text="controller" term_id="controller" >}}) creates and
|
||||
manages EndpointSlice objects. There are a variety of other use cases for
|
||||
EndpointSlices, such as service mesh implementations, that could result in other
|
||||
entities or controllers managing additional sets of EndpointSlices.
|
||||
-->
|
||||
### 管理 {#management}
|
||||
|
||||
通常,控制面(尤其是端点切片的 {{< glossary_tooltip text="控制器" term_id="controller" >}})
|
||||
会创建和管理 EndpointSlice 对象。EndpointSlice 对象还有一些其他使用场景,
|
||||
例如作为服务网格(Service Mesh)的实现。
|
||||
这些场景都会导致有其他实体或者控制器负责管理额外的 EndpointSlice 集合。
|
||||
|
||||
<!--
|
||||
To ensure that multiple entities can manage EndpointSlices without interfering
|
||||
with each other, Kubernetes defines the
|
||||
{{< glossary_tooltip term_id="label" text="label" >}}
|
||||
`endpointslice.kubernetes.io/managed-by`, which indicates the entity managing
|
||||
an EndpointSlice.
|
||||
The endpoint slice controller sets `endpointslice-controller.k8s.io` as the value
|
||||
for this label on all EndpointSlices it manages. Other entities managing
|
||||
EndpointSlices should also set a unique value for this label.
|
||||
-->
|
||||
为了确保多个实体可以管理 EndpointSlice 而且不会相互产生干扰,Kubernetes 定义了
|
||||
{{< glossary_tooltip term_id="label" text="标签" >}}
|
||||
`endpointslice.kubernetes.io/managed-by`,用来标明哪个实体在管理某个
|
||||
EndpointSlice。端点切片控制器会在自己所管理的所有 EndpointSlice 上将该标签值设置为
|
||||
`endpointslice-controller.k8s.io`。
|
||||
管理 EndpointSlice 的其他实体也应该为此标签设置一个唯一值。
|
||||
|
||||
<!--
|
||||
### Ownership
|
||||
|
||||
In most use cases, EndpointSlices are owned by the Service that the endpoint
|
||||
slice object tracks endpoints for. This ownership is indicated by an owner
|
||||
reference on each EndpointSlice as well as a `kubernetes.io/service-name`
|
||||
label that enables simple lookups of all EndpointSlices belonging to a Service.
|
||||
-->
|
||||
### 属主关系 {#ownership}
|
||||
|
||||
在大多数场合下,EndpointSlice 都由某个 Service 所有,
|
||||
(因为)该端点切片正是为该服务跟踪记录其端点。这一属主关系是通过为每个 EndpointSlice
|
||||
设置一个属主(owner)引用,同时设置 `kubernetes.io/service-name` 标签来标明的,
|
||||
目的是方便查找隶属于某 Service 的所有 EndpointSlice。
|
||||
|
||||
<!--
|
||||
### EndpointSlice mirroring
|
||||
|
||||
In some cases, applications create custom Endpoints resources. To ensure that
|
||||
these applications do not need to concurrently write to both Endpoints and
|
||||
EndpointSlice resources, the cluster's control plane mirrors most Endpoints
|
||||
resources to corresponding EndpointSlices.
|
||||
-->
|
||||
### EndpointSlice 镜像 {#endpointslice-mirroring}
|
||||
|
||||
在某些场合,应用会创建定制的 Endpoints 资源。为了保证这些应用不需要并发的更改
|
||||
Endpoints 和 EndpointSlice 资源,集群的控制面将大多数 Endpoints
|
||||
映射到对应的 EndpointSlice 之上。
|
||||
|
||||
<!--
|
||||
The control plane mirrors Endpoints resources unless:
|
||||
|
||||
* the Endpoints resource has a `endpointslice.kubernetes.io/skip-mirror` label
|
||||
set to `true`.
|
||||
* the Endpoints resource has a `control-plane.alpha.kubernetes.io/leader`
|
||||
annotation.
|
||||
* the corresponding Service resource does not exist.
|
||||
* the corresponding Service resource has a non-nil selector.
|
||||
-->
|
||||
控制面对 Endpoints 资源进行映射的例外情况有:
|
||||
|
||||
* Endpoints 资源上标签 `endpointslice.kubernetes.io/skip-mirror` 值为 `true`。
|
||||
* Endpoints 资源包含标签 `control-plane.alpha.kubernetes.io/leader`。
|
||||
* 对应的 Service 资源不存在。
|
||||
* 对应的 Service 的选择算符不为空。
|
||||
|
||||
<!--
|
||||
Individual Endpoints resources may translate into multiple EndpointSlices. This
|
||||
will occur if an Endpoints resource has multiple subsets or includes endpoints
|
||||
with multiple IP families (IPv4 and IPv6). A maximum of 1000 addresses per
|
||||
subset will be mirrored to EndpointSlices.
|
||||
-->
|
||||
每个 Endpoints 资源可能会被翻译到多个 EndpointSlices 中去。
|
||||
当 Endpoints 资源中包含多个子网或者包含多个 IP 地址族(IPv4 和 IPv6)的端点时,
|
||||
就有可能发生这种状况。
|
||||
每个子网最多有 1000 个地址会被镜像到 EndpointSlice 中。
|
||||
|
||||
<!--
|
||||
### Distribution of EndpointSlices
|
||||
|
||||
Each EndpointSlice has a set of ports that applies to all endpoints within the
|
||||
resource. When named ports are used for a Service, Pods may end up with
|
||||
different target port numbers for the same named port, requiring different
|
||||
EndpointSlices. This is similar to the logic behind how subsets are grouped
|
||||
with Endpoints.
|
||||
-->
|
||||
### EndpointSlices 的分布问题 {#distribution-of-endpointslices}
|
||||
|
||||
每个 EndpointSlice 都有一组端口值,适用于资源内的所有端点。
|
||||
当为 Service 使用命名端口时,Pod 可能会就同一命名端口获得不同的端口号,
|
||||
因而需要不同的 EndpointSlice。这有点像 Endpoints 用来对子网进行分组的逻辑。
|
||||
|
||||
<!--
|
||||
The control plane tries to fill EndpointSlices as full as possible, but does not
|
||||
actively rebalance them. The logic is fairly straightforward:
|
||||
|
||||
1. Iterate through existing EndpointSlices, remove endpoints that are no longer
|
||||
desired and update matching endpoints that have changed.
|
||||
2. Iterate through EndpointSlices that have been modified in the first step and
|
||||
fill them up with any new endpoints needed.
|
||||
3. If there's still new endpoints left to add, try to fit them into a previously
|
||||
unchanged slice and/or create new ones.
|
||||
-->
|
||||
控制面尝试尽量将 EndpointSlice 填满,不过不会主动地在若干 EndpointSlice
|
||||
之间执行再平衡操作。这里的逻辑也是相对直接的:
|
||||
|
||||
1. 列举所有现有的 EndpointSlices,移除那些不再需要的端点并更新那些已经变化的端点。
|
||||
2. 列举所有在第一步中被更改过的 EndpointSlices,用新增加的端点将其填满。
|
||||
3. 如果还有新的端点未被添加进去,尝试将这些端点添加到之前未更改的切片中,
|
||||
或者创建新切片。
|
||||
|
||||
<!--
|
||||
Importantly, the third step prioritizes limiting EndpointSlice updates over a
|
||||
perfectly full distribution of EndpointSlices. As an example, if there are 10
|
||||
new endpoints to add and 2 EndpointSlices with room for 5 more endpoints each,
|
||||
this approach will create a new EndpointSlice instead of filling up the 2
|
||||
existing EndpointSlices. In other words, a single EndpointSlice creation is
|
||||
preferrable to multiple EndpointSlice updates.
|
||||
-->
|
||||
这里比较重要的是,与在 EndpointSlice 之间完成最佳的分布相比,第三步中更看重限制
|
||||
EndpointSlice 更新的操作次数。例如,如果有 10 个端点待添加,有两个 EndpointSlice
|
||||
中各有 5 个空位,上述方法会创建一个新的 EndpointSlice 而不是将现有的两个
|
||||
EndpointSlice 都填满。换言之,与执行多个 EndpointSlice 更新操作相比较,
|
||||
方法会优先考虑执行一个 EndpointSlice 创建操作。
|
||||
|
||||
<!--
|
||||
With kube-proxy running on each Node and watching EndpointSlices, every change
|
||||
to an EndpointSlice becomes relatively expensive since it will be transmitted to
|
||||
every Node in the cluster. This approach is intended to limit the number of
|
||||
changes that need to be sent to every Node, even if it may result with multiple
|
||||
EndpointSlices that are not full.
|
||||
-->
|
||||
由于 kube-proxy 在每个节点上运行并监视 EndpointSlice 状态,EndpointSlice
|
||||
的每次变更都变得相对代价较高,因为这些状态变化要传递到集群中每个节点上。
|
||||
这一方法尝试限制要发送到所有节点上的变更消息个数,即使这样做可能会导致有多个
|
||||
EndpointSlice 没有被填满。
|
||||
|
||||
<!--
|
||||
In practice, this less than ideal distribution should be rare. Most changes
|
||||
processed by the EndpointSlice controller will be small enough to fit in an
|
||||
existing EndpointSlice, and if not, a new EndpointSlice is likely going to be
|
||||
necessary soon anyway. Rolling updates of Deployments also provide a natural
|
||||
repacking of EndpointSlices with all Pods and their corresponding endpoints
|
||||
getting replaced.
|
||||
-->
|
||||
在实践中,上面这种并非最理想的分布是很少出现的。大多数被 EndpointSlice
|
||||
控制器处理的变更都是足够小的,可以添加到某已有 EndpointSlice 中去的。
|
||||
并且,假使无法添加到已有的切片中,不管怎样都会快就会需要一个新的
|
||||
EndpointSlice 对象。Deployment 的滚动更新为重新为 EndpointSlice
|
||||
打包提供了一个自然的机会,所有 Pod 及其对应的端点在这一期间都会被替换掉。
|
||||
|
||||
<!--
|
||||
### Duplicate endpoints
|
||||
|
||||
Due to the nature of EndpointSlice changes, endpoints may be represented in more
|
||||
than one EndpointSlice at the same time. This naturally occurs as changes to
|
||||
different EndpointSlice objects can arrive at the Kubernetes client watch/cache
|
||||
at different times. Implementations using EndpointSlice must be able to have the
|
||||
endpoint appear in more than one slice. A reference implementation of how to
|
||||
perform endpoint deduplication can be found in the `EndpointSliceCache`
|
||||
implementation in `kube-proxy`.
|
||||
-->
|
||||
### 重复的端点 {#duplicate-endpoints}
|
||||
|
||||
由于 EndpointSlice 变化的自身特点,端点可能会同时出现在不止一个 EndpointSlice
|
||||
中。鉴于不同的 EndpointSlice 对象在不同时刻到达 Kubernetes 的监视/缓存中,
|
||||
这种情况的出现是很自然的。
|
||||
使用 EndpointSlice 的实现必须能够处理端点出现在多个切片中的状况。
|
||||
关于如何执行端点去重(deduplication)的参考实现,你可以在 `kube-proxy` 的
|
||||
`EndpointSlice` 实现中找到。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
* Read [Connecting Applications with Services](/docs/concepts/services-networking/connect-applications-service/)
|
||||
-->
|
||||
* 阅读[使用 Service 连接到应用](/zh/docs/concepts/services-networking/connect-applications-service/)
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
---
|
||||
title: Ingress 控制器
|
||||
content_type: concept
|
||||
weight: 40
|
||||
---
|
||||
|
||||
<!--
|
||||
title: Ingress Controllers
|
||||
content_type: concept
|
||||
weight: 40
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
<!--
|
||||
In order for the Ingress resource to work, the cluster must have an ingress controller running.
|
||||
|
||||
Unlike other types of controllers which run as part of the `kube-controller-manager` binary, Ingress controllers
|
||||
are not started automatically with a cluster. Use this page to choose the ingress controller implementation
|
||||
that best fits your cluster.
|
||||
|
||||
Kubernetes as a project supports and maintains [AWS](https://github.com/kubernetes-sigs/aws-load-balancer-controller#readme), [GCE](https://git.k8s.io/ingress-gce/README.md#readme), and
|
||||
[nginx](https://git.k8s.io/ingress-nginx/README.md#readme) ingress controllers.
|
||||
-->
|
||||
为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。
|
||||
|
||||
与作为 `kube-controller-manager` 可执行文件的一部分运行的其他类型的控制器不同,
|
||||
Ingress 控制器不是随集群自动启动的。
|
||||
基于此页面,你可选择最适合你的集群的 ingress 控制器实现。
|
||||
|
||||
Kubernetes 作为一个项目,目前支持和维护
|
||||
[AWS](https://github.com/kubernetes-sigs/aws-load-balancer-controller#readme)、
|
||||
[GCE](https://git.k8s.io/ingress-gce/README.md)
|
||||
和 [Nginx](https://git.k8s.io/ingress-nginx/README.md#readme) Ingress 控制器。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Additional controllers
|
||||
-->
|
||||
## 其他控制器
|
||||
|
||||
{{% thirdparty-content %}}
|
||||
|
||||
<!--
|
||||
* [AKS Application Gateway Ingress Controller](https://docs.microsoft.com/azure/application-gateway/tutorial-ingress-controller-add-on-existing?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Faks%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json) is an ingress controller that configures the [Azure Application Gateway](https://docs.microsoft.com/azure/application-gateway/overview).
|
||||
* [Ambassador](https://www.getambassador.io/) API Gateway is an [Envoy](https://www.envoyproxy.io)-based ingress
|
||||
controller.
|
||||
* [Apache APISIX ingress controller](https://github.com/apache/apisix-ingress-controller) is an [Apache APISIX](https://github.com/apache/apisix)-based ingress controller.
|
||||
* [Avi Kubernetes Operator](https://github.com/vmware/load-balancer-and-ingress-services-for-kubernetes) provides L4-L7 load-balancing using [VMware NSX Advanced Load Balancer](https://avinetworks.com/).
|
||||
-->
|
||||
* [AKS 应用程序网关 Ingress 控制器](https://docs.microsoft.com/azure/application-gateway/tutorial-ingress-controller-add-on-existing?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Faks%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json)
|
||||
是一个配置 [Azure 应用程序网关](https://docs.microsoft.com/azure/application-gateway/overview)
|
||||
的 Ingress 控制器。
|
||||
* [Ambassador](https://www.getambassador.io/) API 网关是一个基于
|
||||
[Envoy](https://www.envoyproxy.io) 的 Ingress 控制器。
|
||||
* [Apache APISIX Ingress 控制器](https://github.com/apache/apisix-ingress-controller)
|
||||
是一个基于 [Apache APISIX 网关](https://github.com/apache/apisix) 的 Ingress 控制器。
|
||||
* [Avi Kubernetes Operator](https://github.com/vmware/load-balancer-and-ingress-services-for-kubernetes)
|
||||
使用 [VMware NSX Advanced Load Balancer](https://avinetworks.com/)
|
||||
提供第 4 到第 7 层的负载均衡。
|
||||
<!--
|
||||
* [BFE Ingress Controller](https://github.com/bfenetworks/ingress-bfe) is a [BFE](https://www.bfe-networks.net)-based ingress controller.
|
||||
* The [Citrix ingress controller](https://github.com/citrix/citrix-k8s-ingress-controller#readme) works with
|
||||
Citrix Application Delivery Controller.
|
||||
* [Contour](https://projectcontour.io/) is an [Envoy](https://www.envoyproxy.io/) based ingress controller.
|
||||
* [EnRoute](https://getenroute.io/) is an [Envoy](https://www.envoyproxy.io) based API gateway that can run as an ingress controller.
|
||||
* [Easegress IngressController](https://github.com/megaease/easegress/blob/main/doc/reference/ingresscontroller.md) is an [Easegress](https://megaease.com/easegress/) based API gateway that can run as an ingress controller.
|
||||
-->
|
||||
* [BFE Ingress 控制器](https://github.com/bfenetworks/ingress-bfe)是一个基于
|
||||
[BFE](https://www.bfe-networks.net) 的 Ingress 控制器。
|
||||
* [Citrix Ingress 控制器](https://github.com/citrix/citrix-k8s-ingress-controller#readme)
|
||||
可以用来与 Citrix Application Delivery Controller 一起使用。
|
||||
* [Contour](https://projectcontour.io/) 是一个基于 [Envoy](https://www.envoyproxy.io/)
|
||||
的 Ingress 控制器。
|
||||
* [EnRoute](https://getenroute.io/) 是一个基于 [Envoy](https://www.envoyproxy.io)
|
||||
的 API 网关,可以用作 Ingress 控制器。
|
||||
* [Easegress IngressController](https://github.com/megaease/easegress/blob/main/doc/reference/ingresscontroller.md)
|
||||
是一个基于 [Easegress](https://megaease.com/easegress/) 的 API 网关,可以用作 Ingress 控制器。
|
||||
<!--
|
||||
* F5 BIG-IP [Container Ingress Services for Kubernetes](https://clouddocs.f5.com/containers/latest/userguide/kubernetes/)
|
||||
lets you use an Ingress to configure F5 BIG-IP virtual servers.
|
||||
* [Gloo](https://gloo.solo.io) is an open-source ingress controller based on [Envoy](https://www.envoyproxy.io),
|
||||
which offers API gateway functionality.
|
||||
* [HAProxy Ingress](https://haproxy-ingress.github.io/) is an ingress controller for
|
||||
[HAProxy](https://www.haproxy.org/#desc).
|
||||
* The [HAProxy Ingress Controller for Kubernetes](https://github.com/haproxytech/kubernetes-ingress#readme)
|
||||
is also an ingress controller for [HAProxy](https://www.haproxy.org/#desc).
|
||||
* [Istio Ingress](https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/)
|
||||
is an [Istio](https://istio.io/) based ingress controller.
|
||||
-->
|
||||
* F5 BIG-IP 的
|
||||
[用于 Kubernetes 的容器 Ingress 服务](https://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest)
|
||||
让你能够使用 Ingress 来配置 F5 BIG-IP 虚拟服务器。
|
||||
* [Gloo](https://gloo.solo.io) 是一个开源的、基于 [Envoy](https://www.envoyproxy.io) 的
|
||||
Ingress 控制器,能够提供 API 网关功能。
|
||||
* [HAProxy Ingress](https://haproxy-ingress.github.io/) 是一个针对
|
||||
[HAProxy](https://www.haproxy.org/#desc) 的 Ingress 控制器。
|
||||
* [用于 Kubernetes 的 HAProxy Ingress 控制器](https://github.com/haproxytech/kubernetes-ingress#readme)
|
||||
也是一个针对 [HAProxy](https://www.haproxy.org/#desc) 的 Ingress 控制器。
|
||||
* [Istio Ingress](https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/)
|
||||
是一个基于 [Istio](https://istio.io/) 的 Ingress 控制器。
|
||||
<!--
|
||||
* The [Kong Ingress Controller for Kubernetes](https://github.com/Kong/kubernetes-ingress-controller#readme)
|
||||
is an ingress controller driving [Kong Gateway](https://konghq.com/kong/).
|
||||
* The [NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx-ingress-controller/)
|
||||
works with the [NGINX](https://www.nginx.com/resources/glossary/nginx/) webserver (as a proxy).
|
||||
* The [Pomerium Ingress Controller](https://www.pomerium.com/docs/k8s/ingress.html) is based on [Pomerium](https://pomerium.com/), which offers context-aware access policy.
|
||||
* [Skipper](https://opensource.zalando.com/skipper/kubernetes/ingress-controller/) HTTP router and reverse proxy for service composition, including use cases like Kubernetes Ingress, designed as a library to build your custom proxy.
|
||||
-->
|
||||
* [用于 Kubernetes 的 Kong Ingress 控制器](https://github.com/Kong/kubernetes-ingress-controller#readme)
|
||||
是一个用来驱动 [Kong Gateway](https://konghq.com/kong/) 的 Ingress 控制器。
|
||||
* [用于 Kubernetes 的 NGINX Ingress 控制器](https://www.nginx.com/products/nginx-ingress-controller/)
|
||||
能够与 [NGINX](https://www.nginx.com/resources/glossary/nginx/)
|
||||
网页服务器(作为代理)一起使用。
|
||||
* [Pomerium Ingress 控制器](https://www.pomerium.com/docs/k8s/ingress.html)
|
||||
基于 [Pomerium](https://pomerium.com/),能提供上下文感知的准入策略。
|
||||
* [Skipper](https://opensource.zalando.com/skipper/kubernetes/ingress-controller/) HTTP
|
||||
路由器和反向代理可用于服务组装,支持包括 Kubernetes Ingress
|
||||
这类使用场景,是一个用以构造你自己的定制代理的库。
|
||||
<!--
|
||||
* The [Traefik Kubernetes Ingress provider](https://doc.traefik.io/traefik/providers/kubernetes-ingress/) is an
|
||||
ingress controller for the [Traefik](https://traefik.io/traefik/) proxy.
|
||||
* [Tyk Operator](https://github.com/TykTechnologies/tyk-operator) extends Ingress with Custom Resources to bring API Management capabilities to Ingress. Tyk Operator works with the Open Source Tyk Gateway & Tyk Cloud control plane.
|
||||
* [Voyager](https://appscode.com/products/voyager) is an ingress controller for
|
||||
[HAProxy](https://www.haproxy.org/#desc).
|
||||
-->
|
||||
* [Traefik Kubernetes Ingress 提供程序](https://doc.traefik.io/traefik/providers/kubernetes-ingress/)
|
||||
是一个用于 [Traefik](https://traefik.io/traefik/) 代理的 Ingress 控制器。
|
||||
* [Tyk Operator](https://github.com/TykTechnologies/tyk-operator)
|
||||
使用自定义资源扩展 Ingress,为之带来 API 管理能力。Tyk Operator
|
||||
使用开源的 Tyk Gateway & Tyk Cloud 控制面。
|
||||
* [Voyager](https://appscode.com/products/voyager) 是一个针对
|
||||
[HAProxy](https://www.haproxy.org/#desc) 的 Ingress 控制器。
|
||||
|
||||
<!--
|
||||
## Using multiple Ingress controllers
|
||||
-->
|
||||
## 使用多个 Ingress 控制器
|
||||
|
||||
<!--
|
||||
You may deploy any number of ingress controllers using [ingress class](/docs/concepts/services-networking/ingress/#ingress-class)
|
||||
within a cluster. Note the `.metadata.name` of your ingress class resource. When you create an ingress you would need that name to specify the `ingressClassName` field on your Ingress object (refer to [IngressSpec v1 reference](/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec). `ingressClassName` is a replacement of the older [annotation method](/docs/concepts/services-networking/ingress/#deprecated-annotation).
|
||||
-->
|
||||
你可以使用
|
||||
[Ingress 类](/zh/docs/concepts/services-networking/ingress/#ingress-class)在集群中部署任意数量的
|
||||
Ingress 控制器。
|
||||
请注意你的 Ingress 类资源的 `.metadata.name` 字段。
|
||||
当你创建 Ingress 时,你需要用此字段的值来设置 Ingress 对象的 `ingressClassName` 字段(请参考
|
||||
[IngressSpec v1 reference](/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec))。
|
||||
`ingressClassName`
|
||||
是之前的[注解](/zh/docs/concepts/services-networking/ingress/#deprecated-annotation)做法的替代。
|
||||
|
||||
<!--
|
||||
If you do not specify an IngressClass for an Ingress, and your cluster has exactly one IngressClass marked as default, then Kubernetes [applies](/docs/concepts/services-networking/ingress/#default-ingress-class) the cluster's default IngressClass to the Ingress.
|
||||
You mark an IngressClass as default by setting the [`ingressclass.kubernetes.io/is-default-class` annotation](/docs/reference/labels-annotations-taints/#ingressclass-kubernetes-io-is-default-class) on that IngressClass, with the string value `"true"`.
|
||||
|
||||
Ideally, all ingress controllers should fulfill this specification, but the various ingress
|
||||
controllers operate slightly differently.
|
||||
-->
|
||||
如果你不为 Ingress 指定 IngressClass,并且你的集群中只有一个 IngressClass 被标记为默认,那么
|
||||
Kubernetes 会将此集群的默认 IngressClass
|
||||
[应用](/zh/docs/concepts/services-networking/ingress/#default-ingress-class)到 Ingress 上。
|
||||
IngressClass。
|
||||
你可以通过将
|
||||
[`ingressclass.kubernetes.io/is-default-class` 注解](/zh/docs/reference/labels-annotations-taints/#ingressclass-kubernetes-io-is-default-class)
|
||||
的值设置为 `"true"` 来将一个 IngressClass 标记为集群默认。
|
||||
|
||||
理想情况下,所有 Ingress 控制器都应满足此规范,但各种 Ingress 控制器的操作略有不同。
|
||||
|
||||
<!--
|
||||
Make sure you review your ingress controller's documentation to understand the caveats of choosing it.
|
||||
-->
|
||||
{{< note >}}
|
||||
确保你查看了 ingress 控制器的文档,以了解选择它的注意事项。
|
||||
{{< /note >}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
* Learn more about [Ingress](/docs/concepts/services-networking/ingress/).
|
||||
* [Set up Ingress on Minikube with the NGINX Controller](/docs/tasks/access-application-cluster/ingress-minikube).
|
||||
-->
|
||||
* 进一步了解 [Ingress](/zh/docs/concepts/services-networking/ingress/)。
|
||||
* [在 Minikube 上使用 NGINX 控制器安装 Ingress](/zh/docs/tasks/access-application-cluster/ingress-minikube)。
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,594 @@
|
||||
---
|
||||
title: 网络策略
|
||||
content_type: concept
|
||||
weight: 50
|
||||
---
|
||||
|
||||
<!--
|
||||
title: Network Policies
|
||||
content_type: concept
|
||||
weight: 50
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
<!--
|
||||
If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), then you might consider using Kubernetes NetworkPolicies for particular applications in your cluster. NetworkPolicies are an application-centric construct which allow you to specify how a {{< glossary_tooltip text="pod" term_id="pod">}} is allowed to communicate with various network "entities" (we use the word "entity" here to avoid overloading the more common terms such as "endpoints" and "services", which have specific Kubernetes connotations) over the network. NetworkPolicies apply to a connection with a pod on one or both ends, and are not relevant to other connections.
|
||||
-->
|
||||
如果你希望在 IP 地址或端口层面(OSI 第 3 层或第 4 层)控制网络流量,
|
||||
则你可以考虑为集群中特定应用使用 Kubernetes 网络策略(NetworkPolicy)。
|
||||
NetworkPolicy 是一种以应用为中心的结构,允许你设置如何允许
|
||||
{{< glossary_tooltip text="Pod" term_id="pod">}} 与网络上的各类网络“实体”
|
||||
(我们这里使用实体以避免过度使用诸如“端点”和“服务”这类常用术语,
|
||||
这些术语在 Kubernetes 中有特定含义)通信。
|
||||
NetworkPolicies 适用于一端或两端与 Pod 的连接,与其他连接无关。
|
||||
|
||||
<!--
|
||||
The entities that a Pod can communicate with are identified through a combination of the following 3 identifiers:
|
||||
|
||||
1. Other pods that are allowed (exception: a pod cannot block access to itself)
|
||||
2. Namespaces that are allowed
|
||||
3. IP blocks (exception: traffic to and from the node where a Pod is running is always allowed, regardless of the IP address of the Pod or the node)
|
||||
-->
|
||||
Pod 可以通信的 Pod 是通过如下三个标识符的组合来辩识的:
|
||||
|
||||
1. 其他被允许的 Pods(例外:Pod 无法阻塞对自身的访问)
|
||||
2. 被允许的名字空间
|
||||
3. IP 组块(例外:与 Pod 运行所在的节点的通信总是被允许的,
|
||||
无论 Pod 或节点的 IP 地址)
|
||||
|
||||
<!--
|
||||
When defining a pod- or namespace- based NetworkPolicy, you use a {{< glossary_tooltip text="selector" term_id="selector">}} to specify what traffic is allowed to and from the Pod(s) that match the selector.
|
||||
|
||||
Meanwhile, when IP based NetworkPolicies are created, we define policies based on IP blocks (CIDR ranges).
|
||||
-->
|
||||
在定义基于 Pod 或名字空间的 NetworkPolicy 时,你会使用
|
||||
{{< glossary_tooltip text="选择算符" term_id="selector">}} 来设定哪些流量
|
||||
可以进入或离开与该算符匹配的 Pod。
|
||||
|
||||
同时,当基于 IP 的 NetworkPolicy 被创建时,我们基于 IP 组块(CIDR 范围)
|
||||
来定义策略。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Prerequisites
|
||||
|
||||
Network policies are implemented by the [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/). To use network policies, you must be using a networking solution which supports NetworkPolicy. Creating a NetworkPolicy resource without a controller that implements it will have no effect.
|
||||
-->
|
||||
## 前置条件 {#prerequisites}
|
||||
|
||||
网络策略通过[网络插件](/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
|
||||
来实现。要使用网络策略,你必须使用支持 NetworkPolicy 的网络解决方案。
|
||||
创建一个 NetworkPolicy 资源对象而没有控制器来使它生效的话,是没有任何作用的。
|
||||
|
||||
<!--
|
||||
## The Two Sorts of Pod Isolation
|
||||
|
||||
There are two sorts of isolation for a pod: isolation for egress, and isolation for ingress. They concern what connections may be established. "Isolation" here is not absolute, rather it means "some restrictions apply". The alternative, "non-isolated for $direction", means that no restrictions apply in the stated direction. The two sorts of isolation (or not) are declared independently, and are both relevant for a connection from one pod to another.
|
||||
-->
|
||||
|
||||
## Pod 隔离的两种类型 {#the-two-sorts-of-pod-isolation}
|
||||
|
||||
Pod 有两种隔离: 出口的隔离和入口的隔离。它们涉及到可以建立哪些连接。
|
||||
这里的“隔离”不是绝对的,而是意味着“有一些限制”。
|
||||
另外的,“非隔离方向”意味着在所述方向上没有限制。这两种隔离(或不隔离)是独立声明的,
|
||||
并且都与从一个 Pod 到另一个 Pod 的连接有关。
|
||||
|
||||
<!--
|
||||
By default, a pod is non-isolated for egress; all outbound connections are allowed. A pod is isolated for egress if there is any NetworkPolicy that both selects the pod and has "Egress" in its `policyTypes`; we say that such a policy applies to the pod for egress. When a pod is isolated for egress, the only allowed connections from the pod are those allowed by the `egress` list of some NetworkPolicy that applies to the pod for egress. The effects of those `egress` lists combine additively.
|
||||
-->
|
||||
|
||||
默认情况下,一个 Pod 的出口是非隔离的,即所有外向连接都是被允许的。如果有任何的 NetworkPolicy
|
||||
选择该 Pod 并在其 `policyTypes` 中包含 “Egress”,则该 Pod 是出口隔离的,
|
||||
我们称这样的策略适用于该 Pod 的出口。当一个 Pod 的出口被隔离时,
|
||||
唯一允许的来自 Pod 的连接是适用于出口的 Pod 的某个 NetworkPolicy 的 `egress` 列表所允许的连接。
|
||||
这些 `egress` 列表的效果是相加的。
|
||||
|
||||
<!--
|
||||
By default, a pod is non-isolated for ingress; all inbound connections are allowed. A pod is isolated for ingress if there is any NetworkPolicy that both selects the pod and has "Ingress" in its `policyTypes`; we say that such a policy applies to the pod for ingress. When a pod is isolated for ingress, the only allowed connections into the pod are those from the pod's node and those allowed by the `ingress` list of some NetworkPolicy that applies to the pod for ingress. The effects of those `ingress` lists combine additively.
|
||||
-->
|
||||
|
||||
默认情况下,一个 Pod 对入口是非隔离的,即所有入站连接都是被允许的。如果有任何的 NetworkPolicy
|
||||
选择该 Pod 并在其 `policyTypes` 中包含 “Ingress”,则该 Pod 被隔离入口,
|
||||
我们称这种策略适用于该 Pod 的入口。当一个 Pod 的入口被隔离时,唯一允许进入该 Pod
|
||||
的连接是来自该 Pod 节点的连接和适用于入口的 Pod 的某个 NetworkPolicy 的 `ingress`
|
||||
列表所允许的连接。这些 `ingress` 列表的效果是相加的。
|
||||
|
||||
<!--
|
||||
Network policies do not conflict; they are additive. If any policy or policies apply to a given pod for a given direction, the connections allowed in that direction from that pod is the union of what the applicable policies allow. Thus, order of evaluation does not affect the policy result.
|
||||
|
||||
For a connection from a source pod to a destination pod to be allowed, both the egress policy on the source pod and the ingress policy on the destination pod need to allow the connection. If either side does not allow the connection, it will not happen.
|
||||
-->
|
||||
|
||||
网络策略是相加的,所以不会产生冲突。如果策略适用于 Pod 某一特定方向的流量,
|
||||
Pod 在对应方向所允许的连接是适用的网络策略所允许的集合。
|
||||
因此,评估的顺序不影响策略的结果。
|
||||
|
||||
要允许从源 Pod 到目的 Pod 的连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。
|
||||
如果任何一方不允许连接,建立连接将会失败。
|
||||
|
||||
<!--
|
||||
## The NetworkPolicy resource {#networkpolicy-resource}
|
||||
|
||||
See the [NetworkPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#networkpolicy-v1-networking-k8s-io) reference for a full definition of the resource.
|
||||
|
||||
An example NetworkPolicy might look like this:
|
||||
-->
|
||||
## NetworkPolicy 资源 {#networkpolicy-resource}
|
||||
|
||||
参阅 [NetworkPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#networkpolicy-v1-networking-k8s-io)
|
||||
来了解资源的完整定义。
|
||||
|
||||
下面是一个 NetworkPolicy 的示例:
|
||||
|
||||
{{< codenew file="service/networking/networkpolicy.yaml" >}}
|
||||
|
||||
<!--
|
||||
POSTing this to the API server for your cluster will have no effect unless your chosen networking solution supports network policy.
|
||||
-->
|
||||
{{< note >}}
|
||||
除非选择支持网络策略的网络解决方案,否则将上述示例发送到API服务器没有任何效果。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
__Mandatory Fields__: As with all other Kubernetes config, a NetworkPolicy
|
||||
needs `apiVersion`, `kind`, and `metadata` fields. For general information
|
||||
about working with config files, see
|
||||
[Configure a Pod to Use a ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/),
|
||||
and [Object Management](/docs/concepts/overview/working-with-objects/object-management).
|
||||
|
||||
__spec__: NetworkPolicy [spec](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status) has all the information needed to define a particular network policy in the given namespace.
|
||||
|
||||
__podSelector__: Each NetworkPolicy includes a `podSelector` which selects the grouping of pods to which the policy applies. The example policy selects pods with the label "role=db". An empty `podSelector` selects all pods in the namespace.
|
||||
-->
|
||||
__必需字段__:与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要 `apiVersion`、
|
||||
`kind` 和 `metadata` 字段。关于配置文件操作的一般信息,请参考
|
||||
[配置 Pod 以使用 ConfigMap](/zh/docs/tasks/configure-pod-container/configure-pod-configmap/),
|
||||
和[对象管理](/zh/docs/concepts/overview/working-with-objects/object-management)。
|
||||
|
||||
__spec__:NetworkPolicy [规约](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status)
|
||||
中包含了在一个名字空间中定义特定网络策略所需的所有信息。
|
||||
|
||||
__podSelector__:每个 NetworkPolicy 都包括一个 `podSelector`,它对该策略所
|
||||
适用的一组 Pod 进行选择。示例中的策略选择带有 "role=db" 标签的 Pod。
|
||||
空的 `podSelector` 选择名字空间下的所有 Pod。
|
||||
|
||||
<!--
|
||||
__policyTypes__: Each NetworkPolicy includes a `policyTypes` list which may include either `Ingress`, `Egress`, or both. The `policyTypes` field indicates whether or not the given policy applies to ingress traffic to selected pod, egress traffic from selected pods, or both. If no `policyTypes` are specified on a NetworkPolicy then by default `Ingress` will always be set and `Egress` will be set if the NetworkPolicy has any egress rules.
|
||||
|
||||
__ingress__: Each NetworkPolicy may include a list of allowed `ingress` rules. Each rule allows traffic which matches both the `from` and `ports` sections. The example policy contains a single rule, which matches traffic on a single port, from one of three sources, the first specified via an `ipBlock`, the second via a `namespaceSelector` and the third via a `podSelector`.
|
||||
|
||||
__egress__: Each NetworkPolicy may include a list of allowed `egress` rules. Each rule allows traffic which matches both the `to` and `ports` sections. The example policy contains a single rule, which matches traffic on a single port to any destination in `10.0.0.0/24`.
|
||||
-->
|
||||
|
||||
__policyTypes__: 每个 NetworkPolicy 都包含一个 `policyTypes` 列表,其中包含
|
||||
`Ingress` 或 `Egress` 或两者兼具。`policyTypes` 字段表示给定的策略是应用于
|
||||
进入所选 Pod 的入站流量还是来自所选 Pod 的出站流量,或两者兼有。
|
||||
如果 NetworkPolicy 未指定 `policyTypes` 则默认情况下始终设置 `Ingress`;
|
||||
如果 NetworkPolicy 有任何出口规则的话则设置 `Egress`。
|
||||
|
||||
__ingress__: 每个 NetworkPolicy 可包含一个 `ingress` 规则的白名单列表。
|
||||
每个规则都允许同时匹配 `from` 和 `ports` 部分的流量。示例策略中包含一条
|
||||
简单的规则:它匹配某个特定端口,来自三个来源中的一个,第一个通过 `ipBlock`
|
||||
指定,第二个通过 `namespaceSelector` 指定,第三个通过 `podSelector` 指定。
|
||||
|
||||
__egress__: 每个 NetworkPolicy 可包含一个 `egress` 规则的白名单列表。
|
||||
每个规则都允许匹配 `to` 和 `port` 部分的流量。该示例策略包含一条规则,
|
||||
该规则将指定端口上的流量匹配到 `10.0.0.0/24` 中的任何目的地。
|
||||
|
||||
<!--
|
||||
So, the example NetworkPolicy:
|
||||
|
||||
1. isolates "role=db" pods in the "default" namespace for both ingress and egress traffic (if they weren't already isolated)
|
||||
2. (Ingress rules) allows connections to all pods in the "default" namespace with the label "role=db" on TCP port 6379 from:
|
||||
|
||||
* any pod in the "default" namespace with the label "role=frontend"
|
||||
* any pod in a namespace with the label "project=myproject"
|
||||
* IP addresses in the ranges 172.17.0.0–172.17.0.255 and 172.17.2.0–172.17.255.255 (ie, all of 172.17.0.0/16 except 172.17.1.0/24)
|
||||
3. (Egress rules) allows connections from any pod in the "default" namespace with the label "role=db" to CIDR 10.0.0.0/24 on TCP port 5978
|
||||
|
||||
See the [Declare Network Policy](/docs/tasks/administer-cluster/declare-network-policy/) walkthrough for further examples.
|
||||
-->
|
||||
所以,该网络策略示例:
|
||||
|
||||
1. 隔离 "default" 名字空间下 "role=db" 的 Pod (如果它们不是已经被隔离的话)。
|
||||
2. (Ingress 规则)允许以下 Pod 连接到 "default" 名字空间下的带有 "role=db"
|
||||
标签的所有 Pod 的 6379 TCP 端口:
|
||||
|
||||
* "default" 名字空间下带有 "role=frontend" 标签的所有 Pod
|
||||
* 带有 "project=myproject" 标签的所有名字空间中的 Pod
|
||||
* IP 地址范围为 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255
|
||||
(即,除了 172.17.1.0/24 之外的所有 172.17.0.0/16)
|
||||
|
||||
3. (Egress 规则)允许 “default” 命名空间中任何带有标签 “role=db” 的 Pod 到 CIDR
|
||||
10.0.0.0/24 下 5978 TCP 端口的连接。
|
||||
|
||||
参阅[声明网络策略](/zh/docs/tasks/administer-cluster/declare-network-policy/)演练
|
||||
了解更多示例。
|
||||
|
||||
<!--
|
||||
## Behavior of `to` and `from` selectors
|
||||
|
||||
There are four kinds of selectors that can be specified in an `ingress` `from` section or `egress` `to` section:
|
||||
|
||||
__podSelector__: This selects particular Pods in the same namespace as the NetworkPolicy which should be allowed as ingress sources or egress destinations.
|
||||
|
||||
__namespaceSelector__: This selects particular namespaces for which all Pods should be allowed as ingress sources or egress destinations.
|
||||
|
||||
__namespaceSelector__ *and* __podSelector__: A single `to`/`from` entry that specifies both `namespaceSelector` and `podSelector` selects particular Pods within particular namespaces. Be careful to use correct YAML syntax; this policy:
|
||||
-->
|
||||
## 选择器 `to` 和 `from` 的行为 {#behavior-of-to-and-from-selectors}
|
||||
|
||||
可以在 `ingress` 的 `from` 部分或 `egress` 的 `to` 部分中指定四种选择器:
|
||||
|
||||
__podSelector__: 此选择器将在与 NetworkPolicy 相同的名字空间中选择特定的
|
||||
Pod,应将其允许作为入站流量来源或出站流量目的地。
|
||||
|
||||
__namespaceSelector__:此选择器将选择特定的名字空间,应将所有 Pod 用作其
|
||||
入站流量来源或出站流量目的地。
|
||||
|
||||
__namespaceSelector__ *和* __podSelector__:一个指定 `namespaceSelector`
|
||||
和 `podSelector` 的 `to`/`from` 条目选择特定名字空间中的特定 Pod。
|
||||
注意使用正确的 YAML 语法;下面的策略:
|
||||
|
||||
```yaml
|
||||
...
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
user: alice
|
||||
podSelector:
|
||||
matchLabels:
|
||||
role: client
|
||||
...
|
||||
```
|
||||
|
||||
<!--
|
||||
contains a single `from` element allowing connections from Pods with the label `role=client` in namespaces with the label `user=alice`. But *this* policy:
|
||||
-->
|
||||
在 `from` 数组中仅包含一个元素,只允许来自标有 `role=client` 的 Pod 且
|
||||
该 Pod 所在的名字空间中标有 `user=alice` 的连接。但是 *这项* 策略:
|
||||
|
||||
```yaml
|
||||
...
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
user: alice
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
role: client
|
||||
...
|
||||
```
|
||||
|
||||
<!--
|
||||
contains two elements in the `from` array, and allows connections from Pods in the local Namespace with the label `role=client`, *or* from any Pod in any namespace with the label `user=alice`.
|
||||
-->
|
||||
在 `from` 数组中包含两个元素,允许来自本地名字空间中标有 `role=client` 的
|
||||
Pod 的连接,*或* 来自任何名字空间中标有 `user=alice` 的任何 Pod 的连接。
|
||||
|
||||
<!--
|
||||
When in doubt, use `kubectl describe` to see how Kubernetes has interpreted the policy.
|
||||
|
||||
<a name="behavior-of-ipblock-selectors"></a>
|
||||
__ipBlock__: This selects particular IP CIDR ranges to allow as ingress sources or egress destinations. These should be cluster-external IPs, since Pod IPs are ephemeral and unpredictable.
|
||||
|
||||
Cluster ingress and egress mechanisms often require rewriting the source or destination IP
|
||||
of packets. In cases where this happens, it is not defined whether this happens before or
|
||||
after NetworkPolicy processing, and the behavior may be different for different
|
||||
combinations of network plugin, cloud provider, `Service` implementation, etc.
|
||||
|
||||
In the case of ingress, this means that in some cases you may be able to filter incoming
|
||||
packets based on the actual original source IP, while in other cases, the "source IP" that
|
||||
the NetworkPolicy acts on may be the IP of a `LoadBalancer` or of the Pod's node, etc.
|
||||
|
||||
For egress, this means that connections from pods to `Service` IPs that get rewritten to
|
||||
cluster-external IPs may or may not be subject to `ipBlock`-based policies.
|
||||
-->
|
||||
如有疑问,请使用 `kubectl describe` 查看 Kubernetes 如何解释该策略。
|
||||
|
||||
__ipBlock__: 此选择器将选择特定的 IP CIDR 范围以用作入站流量来源或出站流量目的地。
|
||||
这些应该是集群外部 IP,因为 Pod IP 存在时间短暂的且随机产生。
|
||||
|
||||
集群的入站和出站机制通常需要重写数据包的源 IP 或目标 IP。
|
||||
在发生这种情况时,不确定在 NetworkPolicy 处理之前还是之后发生,
|
||||
并且对于网络插件、云提供商、`Service` 实现等的不同组合,其行为可能会有所不同。
|
||||
|
||||
对入站流量而言,这意味着在某些情况下,你可以根据实际的原始源 IP 过滤传入的数据包,
|
||||
而在其他情况下,NetworkPolicy 所作用的 `源IP` 则可能是 `LoadBalancer` 或
|
||||
Pod 的节点等。
|
||||
|
||||
对于出站流量而言,这意味着从 Pod 到被重写为集群外部 IP 的 `Service` IP
|
||||
的连接可能会或可能不会受到基于 `ipBlock` 的策略的约束。
|
||||
|
||||
<!--
|
||||
## Default policies
|
||||
|
||||
By default, if no policies exist in a namespace, then all ingress and egress traffic is allowed to and from pods in that namespace. The following examples let you change the default behavior
|
||||
in that namespace.
|
||||
-->
|
||||
## 默认策略 {#default-policies}
|
||||
|
||||
默认情况下,如果名字空间中不存在任何策略,则所有进出该名字空间中 Pod 的流量都被允许。
|
||||
以下示例使你可以更改该名字空间中的默认行为。
|
||||
|
||||
<!--
|
||||
### Default deny all ingress traffic
|
||||
-->
|
||||
### 默认拒绝所有入站流量 {#default-deny-all-ingress-traffic}
|
||||
|
||||
<!--
|
||||
You can create a "default" ingress isolation policy for a namespace by creating a NetworkPolicy that selects all pods but does not allow any ingress traffic to those pods.
|
||||
-->
|
||||
你可以通过创建选择所有容器但不允许任何进入这些容器的入站流量的 NetworkPolicy
|
||||
来为名字空间创建 “default” 隔离策略。
|
||||
|
||||
{{< codenew file="service/networking/network-policy-default-deny-ingress.yaml" >}}
|
||||
|
||||
<!--
|
||||
This ensures that even pods that aren't selected by any other NetworkPolicy will still be isolated for ingress. This policy does not affect isolation for egress from any pod.
|
||||
-->
|
||||
这确保即使没有被任何其他 NetworkPolicy 选择的 Pod 仍将被隔离以进行入口。
|
||||
此策略不影响任何 Pod 的出口隔离。
|
||||
|
||||
<!--
|
||||
### Allow all ingress traffic
|
||||
-->
|
||||
### 允许所有入站流量 {#allow-all-ingress-traffic}
|
||||
|
||||
<!--
|
||||
If you want to allow all incoming connections to all pods in a namespace, you can create a policy that explicitly allows that.
|
||||
-->
|
||||
如果你想允许一个命名空间中所有 Pod 的所有入站连接,你可以创建一个明确允许的策略。
|
||||
|
||||
{{< codenew file="service/networking/network-policy-allow-all-ingress.yaml" >}}
|
||||
|
||||
<!--
|
||||
With this policy in place, no additional policy or policies can cause any incoming connection to those pods to be denied. This policy has no effect on isolation for egress from any pod.
|
||||
-->
|
||||
有了这个策略,任何额外的策略都不会导致到这些 Pod 的任何入站连接被拒绝。
|
||||
此策略对任何 Pod 的出口隔离没有影响。
|
||||
|
||||
<!--
|
||||
### Default deny all egress traffic
|
||||
|
||||
You can create a "default" egress isolation policy for a namespace by creating a NetworkPolicy that selects all pods but does not allow any egress traffic from those pods.
|
||||
-->
|
||||
### 默认拒绝所有出站流量 {#default-deny-all-egress-traffic}
|
||||
|
||||
你可以通过创建选择所有容器但不允许来自这些容器的任何出站流量的 NetworkPolicy
|
||||
来为名字空间创建 “default” 隔离策略。
|
||||
|
||||
{{< codenew file="service/networking/network-policy-default-deny-egress.yaml" >}}
|
||||
|
||||
<!--
|
||||
This ensures that even pods that aren't selected by any other NetworkPolicy will not be allowed egress traffic. This policy does not
|
||||
change the ingress isolation behavior of any pod.
|
||||
-->
|
||||
此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。
|
||||
此策略不会更改任何 Pod 的入站流量隔离行为。
|
||||
|
||||
<!--
|
||||
### Allow all egress traffic
|
||||
-->
|
||||
### 允许所有出站流量 {#allow-all-egress-traffic}
|
||||
|
||||
<!--
|
||||
If you want to allow all connections from all pods in a namespace, you can create a policy that explicitly allows all outgoing connections from pods in that namespace.
|
||||
-->
|
||||
如果要允许来自命名空间中所有 Pod 的所有连接,
|
||||
则可以创建一个明确允许来自该命名空间中 Pod 的所有出站连接的策略。
|
||||
|
||||
{{< codenew file="service/networking/network-policy-allow-all-egress.yaml" >}}
|
||||
|
||||
<!--
|
||||
With this policy in place, no additional policy or policies can cause any outgoing connection from those pods to be denied. This policy has no effect on isolation for ingress to any pod.
|
||||
-->
|
||||
有了这个策略,任何额外的策略都不会导致来自这些 Pod 的任何出站连接被拒绝。
|
||||
此策略对进入任何 Pod 的隔离没有影响。
|
||||
|
||||
<!--
|
||||
### Default deny all ingress and all egress traffic
|
||||
|
||||
You can create a "default" policy for a namespace which prevents all ingress AND egress traffic by creating the following NetworkPolicy in that namespace.
|
||||
-->
|
||||
### 默认拒绝所有入站和所有出站流量 {#default-deny-all-ingress-and-all-egress-traffic}
|
||||
|
||||
你可以为名字空间创建“默认”策略,以通过在该名字空间中创建以下 NetworkPolicy
|
||||
来阻止所有入站和出站流量。
|
||||
|
||||
{{< codenew file="service/networking/network-policy-default-deny-all.yaml" >}}
|
||||
|
||||
<!--
|
||||
This ensures that even pods that aren't selected by any other NetworkPolicy will not be allowed ingress or egress traffic.
|
||||
-->
|
||||
此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被
|
||||
允许入站或出站流量。
|
||||
|
||||
<!--
|
||||
## SCTP support
|
||||
-->
|
||||
## SCTP 支持 {#sctp-support}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.20" state="stable" >}}
|
||||
|
||||
<!--
|
||||
As a stable feature, this is enabled by default. To disable SCTP at a cluster level, you (or your cluster administrator) will need to disable the `SCTPSupport` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) for the API server with `--feature-gates=SCTPSupport=false,…`.
|
||||
When the feature gate is enabled, you can set the `protocol` field of a NetworkPolicy to `SCTP`.
|
||||
-->
|
||||
作为一个稳定特性,SCTP 支持默认是被启用的。
|
||||
要在集群层面禁用 SCTP,你(或你的集群管理员)需要为 API 服务器指定
|
||||
`--feature-gates=SCTPSupport=false,...`
|
||||
来禁用 `SCTPSupport` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)。
|
||||
启用该特性门控后,用户可以将 NetworkPolicy 的 `protocol` 字段设置为 `SCTP`。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
You must be using a {{< glossary_tooltip text="CNI" term_id="cni" >}} plugin that supports SCTP protocol NetworkPolicies.
|
||||
-->
|
||||
你必须使用支持 SCTP 协议网络策略的 {{< glossary_tooltip text="CNI" term_id="cni" >}} 插件。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
## Targeting a range of Ports
|
||||
-->
|
||||
## 针对某个端口范围 {#targeting-a-range-of-ports}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
|
||||
|
||||
<!--
|
||||
When writing a NetworkPolicy, you can target a range of ports instead of a single port.
|
||||
|
||||
This is achievable with the usage of the `endPort` field, as the following example:
|
||||
-->
|
||||
在编写 NetworkPolicy 时,你可以针对一个端口范围而不是某个固定端口。
|
||||
|
||||
这一目的可以通过使用 `endPort` 字段来实现,如下例所示:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: multi-port-egress
|
||||
namespace: default
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
role: db
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.0.0.0/24
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 32000
|
||||
endPort: 32768
|
||||
```
|
||||
|
||||
<!--
|
||||
The above rule allows any Pod with label `role=db` on the namespace `default` to communicate
|
||||
with any IP within the range `10.0.0.0/24` over TCP, provided that the target
|
||||
port is between the range 32000 and 32768.
|
||||
-->
|
||||
上面的规则允许名字空间 `default` 中所有带有标签 `role=db` 的 Pod 使用 TCP 协议
|
||||
与 `10.0.0.0/24` 范围内的 IP 通信,只要目标端口介于 32000 和 32768 之间就可以。
|
||||
|
||||
<!--
|
||||
The following restrictions apply when using this field:
|
||||
* As a beta feature, this is enabled by default. To disable the `endPort` field
|
||||
at a cluster level, you (or your cluster administrator) need to disable the
|
||||
`NetworkPolicyEndPort` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
|
||||
for the API server with `--feature-gates=NetworkPolicyEndPort=false,…`.
|
||||
* The `endPort` field must be equal to or greater than the `port` field.
|
||||
* `endPort` can only be defined if `port` is also defined.
|
||||
* Both ports must be numeric.
|
||||
-->
|
||||
使用此字段时存在以下限制:
|
||||
|
||||
* 作为一种 Beta 阶段的特性,端口范围设定默认是被启用的。要在整个集群
|
||||
范围内禁止使用 `endPort` 字段,你(或者你的集群管理员)需要为 API
|
||||
服务器设置 `--feature-gates=NetworkPolicyEndPort=false,...` 以禁用
|
||||
`NetworkPolicyEndPort`
|
||||
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)。
|
||||
* `endPort` 字段必须等于或者大于 `port` 字段的值。
|
||||
* 两个字段的设置值都只能是数字。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
Your cluster must be using a {{< glossary_tooltip text="CNI" term_id="cni" >}} plugin that
|
||||
supports the `endPort` field in NetworkPolicy specifications.
|
||||
If your [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
|
||||
does not support the `endPort` field and you specify a NetworkPolicy with that,
|
||||
the policy will be applied only for the single `port` field.
|
||||
-->
|
||||
你的集群所使用的 {{< glossary_tooltip text="CNI" term_id="cni" >}} 插件
|
||||
必须支持在 NetworkPolicy 规约中使用 `endPort` 字段。
|
||||
如果你的[网络插件](/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
|
||||
不支持 `endPort` 字段,而你指定了一个包含 `endPort` 字段的 NetworkPolicy,
|
||||
策略只对单个 `port` 字段生效。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
## Targeting a Namespace by its name
|
||||
-->
|
||||
## 基于名字指向某名字空间 {#targeting-a-namespace-by-its-name}
|
||||
|
||||
{{< feature-state for_k8s_version="1.22" state="stable" >}}
|
||||
|
||||
<!--
|
||||
The Kubernetes control plane sets an immutable label `kubernetes.io/metadata.name` on all
|
||||
namespaces, provided that the `NamespaceDefaultLabelName`
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) is enabled.
|
||||
The value of the label is the namespace name.
|
||||
|
||||
While NetworkPolicy cannot target a namespace by its name with some object field, you can use the
|
||||
standardized label to target a specific namespace.
|
||||
-->
|
||||
只要 `NamespaceDefaultLabelName`
|
||||
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)
|
||||
被启用,Kubernetes 控制面会在所有名字空间上设置一个不可变更的标签
|
||||
`kubernetes.io/metadata.name`。该标签的值是名字空间的名称。
|
||||
|
||||
如果 NetworkPolicy 无法在某些对象字段中指向某名字空间,你可以使用标准的
|
||||
标签方式来指向特定名字空间。
|
||||
|
||||
<!--
|
||||
## What you can't do with network policies (at least, not yet)
|
||||
|
||||
As of Kubernetes {{< skew latestVersion >}}, the following functionality does not exist in the NetworkPolicy API, but you might be able to implement workarounds using Operating System components (such as SELinux, OpenVSwitch, IPTables, and so on) or Layer 7 technologies (Ingress controllers, Service Mesh implementations) or admission controllers. In case you are new to network security in Kubernetes, its worth noting that the following User Stories cannot (yet) be implemented using the NetworkPolicy API.
|
||||
-->
|
||||
## 通过网络策略(至少目前还)无法完成的工作 {#what-you-can-t-do-with-network-policies-at-least-not-yet}
|
||||
|
||||
到 Kubernetes {{< skew latestVersion >}} 为止,NetworkPolicy API 还不支持以下功能,不过
|
||||
你可能可以使用操作系统组件(如 SELinux、OpenVSwitch、IPTables 等等)
|
||||
或者第七层技术(Ingress 控制器、服务网格实现)或准入控制器来实现一些
|
||||
替代方案。
|
||||
如果你对 Kubernetes 中的网络安全性还不太了解,了解使用 NetworkPolicy API
|
||||
还无法实现下面的用户场景是很值得的。
|
||||
|
||||
<!--
|
||||
- Forcing internal cluster traffic to go through a common gateway (this might be best served with a service mesh or other proxy).
|
||||
- Anything TLS related (use a service mesh or ingress controller for this).
|
||||
- Node specific policies (you can use CIDR notation for these, but you cannot target nodes by their Kubernetes identities specifically).
|
||||
- Targeting of services by name (you can, however, target pods or namespaces by their {{< glossary_tooltip text="labels" term_id="label" >}}, which is often a viable workaround).
|
||||
- Creation or management of "Policy requests" that are fulfilled by a third party.
|
||||
-->
|
||||
- 强制集群内部流量经过某公用网关(这种场景最好通过服务网格或其他代理来实现);
|
||||
- 与 TLS 相关的场景(考虑使用服务网格或者 Ingress 控制器);
|
||||
- 特定于节点的策略(你可以使用 CIDR 来表达这一需求不过你无法使用节点在
|
||||
Kubernetes 中的其他标识信息来辩识目标节点);
|
||||
- 基于名字来选择服务(不过,你可以使用 {{< glossary_tooltip text="标签" term_id="label" >}}
|
||||
来选择目标 Pod 或名字空间,这也通常是一种可靠的替代方案);
|
||||
- 创建或管理由第三方来实际完成的“策略请求”;
|
||||
<!--
|
||||
- Default policies which are applied to all namespaces or pods (there are some third party Kubernetes distributions and projects which can do this).
|
||||
- Advanced policy querying and reachability tooling.
|
||||
- The ability to log network security events (for example connections that are blocked or accepted).
|
||||
- The ability to explicitly deny policies (currently the model for NetworkPolicies are deny by default, with only the ability to add allow rules).
|
||||
- The ability to prevent loopback or incoming host traffic (Pods cannot currently block localhost access, nor do they have the ability to block access from their resident node).
|
||||
-->
|
||||
- 实现适用于所有名字空间或 Pods 的默认策略(某些第三方 Kubernetes 发行版本
|
||||
或项目可以做到这点);
|
||||
- 高级的策略查询或者可达性相关工具;
|
||||
- 生成网络安全事件日志的能力(例如,被阻塞或接收的连接请求);
|
||||
- 显式地拒绝策略的能力(目前,NetworkPolicy 的模型默认采用拒绝操作,
|
||||
其唯一的能力是添加允许策略);
|
||||
- 禁止本地回路或指向宿主的网络流量(Pod 目前无法阻塞 localhost 访问,
|
||||
它们也无法禁止来自所在节点的访问请求)。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
- See the [Declare Network Policy](/docs/tasks/administer-cluster/declare-network-policy/)
|
||||
walkthrough for further examples.
|
||||
- See more [recipes](https://github.com/ahmetb/kubernetes-network-policy-recipes) for common scenarios enabled by the NetworkPolicy resource.
|
||||
-->
|
||||
- 参阅[声明网络策略](/zh/docs/tasks/administer-cluster/declare-network-policy/)
|
||||
演练了解更多示例;
|
||||
- 有关 NetworkPolicy 资源所支持的常见场景的更多信息,请参见
|
||||
[此指南](https://github.com/ahmetb/kubernetes-network-policy-recipes)。
|
||||
@@ -0,0 +1,305 @@
|
||||
---
|
||||
title: 使用拓扑键实现拓扑感知的流量路由
|
||||
content_type: concept
|
||||
weight: 10
|
||||
---
|
||||
<!--
|
||||
reviewers:
|
||||
- johnbelamaric
|
||||
- imroc
|
||||
title: Topology-aware traffic routing with topology keys
|
||||
content_type: concept
|
||||
weight: 10
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
This feature, specifically the alpha `topologyKeys` API, is deprecated since
|
||||
Kubernetes v1.21.
|
||||
[Topology Aware Hints](/docs/concepts/services-networking/topology-aware-hints/),
|
||||
introduced in Kubernetes v1.21, provide similar functionality.
|
||||
-->
|
||||
此功能特性,尤其是 Alpha 阶段的 `topologyKeys` API,在 Kubernetes v1.21
|
||||
版本中已被废弃。Kubernetes v1.21 版本中引入的
|
||||
[拓扑感知的提示](/zh/docs/concepts/services-networking/topology-aware-hints/),
|
||||
提供类似的功能。
|
||||
{{</ note >}}
|
||||
|
||||
<!--
|
||||
_Service Topology_ enables a service to route traffic based upon the Node
|
||||
topology of the cluster. For example, a service can specify that traffic be
|
||||
preferentially routed to endpoints that are on the same Node as the client, or
|
||||
in the same availability zone.
|
||||
-->
|
||||
服务拓扑(Service Topology)可以让一个服务基于集群的 Node 拓扑进行流量路由。
|
||||
例如,一个服务可以指定流量是被优先路由到一个和客户端在同一个 Node 或者在同一可用区域的端点。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Topology-aware traffic routing
|
||||
|
||||
By default, traffic sent to a `ClusterIP` or `NodePort` Service may be routed to
|
||||
any backend address for the Service. Kubernetes 1.7 made it possible to
|
||||
route "external" traffic to the Pods running on the same Node that received the
|
||||
traffic. For `ClusterIP` Services, the equivalent same-node preference for
|
||||
routing wasn't possible; nor could you configure your cluster to favor routing
|
||||
to endpoints within the same zone.
|
||||
By setting `topologyKeys` on a Service, you're able to define a policy for routing
|
||||
traffic based upon the Node labels for the originating and destination Nodes.
|
||||
-->
|
||||
## 拓扑感知的流量路由
|
||||
|
||||
默认情况下,发往 `ClusterIP` 或者 `NodePort` 服务的流量可能会被路由到
|
||||
服务的任一后端的地址。Kubernetes 1.7 允许将“外部”流量路由到接收到流量的
|
||||
节点上的 Pod。对于 `ClusterIP` 服务,无法完成同节点优先的路由,你也无法
|
||||
配置集群优选路由到同一可用区中的端点。
|
||||
通过在 Service 上配置 `topologyKeys`,你可以基于来源节点和目标节点的
|
||||
标签来定义流量路由策略。
|
||||
|
||||
<!--
|
||||
The label matching between the source and destination lets you, as a cluster
|
||||
operator, designate sets of Nodes that are "closer" and "farther" from one another.
|
||||
You can define labels to represent whatever metric makes sense for your own
|
||||
requirements.
|
||||
In public clouds, for example, you might prefer to keep network traffic within the
|
||||
same zone, because interzonal traffic has a cost associated with it (and intrazonal
|
||||
traffic typically does not). Other common needs include being able to route traffic
|
||||
to a local Pod managed by a DaemonSet, or directing traffic to Nodes connected to the
|
||||
same top-of-rack switch for the lowest latency.
|
||||
-->
|
||||
通过对源和目的之间的标签匹配,作为集群操作者的你可以根据节点间彼此“较近”和“较远”
|
||||
来定义节点集合。你可以基于符合自身需求的任何度量值来定义标签。
|
||||
例如,在公有云上,你可能更偏向于把流量控制在同一区内,因为区间流量是有费用成本的,
|
||||
而区内流量则没有。
|
||||
其它常见需求还包括把流量路由到由 `DaemonSet` 管理的本地 Pod 上,或者
|
||||
把将流量转发到连接在同一机架交换机的节点上,以获得低延时。
|
||||
|
||||
<!--
|
||||
## Using Service Topology
|
||||
|
||||
If your cluster has the `ServiceTopology`
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
|
||||
enabled, you can control Service traffic
|
||||
routing by specifying the `topologyKeys` field on the Service spec. This field
|
||||
is a preference-order list of Node labels which will be used to sort endpoints
|
||||
when accessing this Service. Traffic will be directed to a Node whose value for
|
||||
the first label matches the originating Node's value for that label. If there is
|
||||
no backend for the Service on a matching Node, then the second label will be
|
||||
considered, and so forth, until no labels remain.
|
||||
|
||||
If no match is found, the traffic will be rejected, as if there were no
|
||||
backends for the Service at all. That is, endpoints are chosen based on the first
|
||||
topology key with available backends. If this field is specified and all entries
|
||||
have no backends that match the topology of the client, the service has no
|
||||
backends for that client and connections should fail. The special value `"*"` may
|
||||
be used to mean "any topology". This catch-all value, if used, only makes sense
|
||||
as the last value in the list.
|
||||
-->
|
||||
|
||||
## 使用服务拓扑 {#using-service-topology}
|
||||
|
||||
如果集群启用了 `ServiceTopology`
|
||||
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/),
|
||||
你就可以在 Service 规约中设定 `topologyKeys` 字段,从而控制其流量路由。
|
||||
此字段是 `Node` 标签的优先顺序字段,将用于在访问这个 `Service` 时对端点进行排序。
|
||||
流量会被定向到第一个标签值和源 `Node` 标签值相匹配的 `Node`。
|
||||
如果这个 `Service` 没有匹配的后端 `Node`,那么第二个标签会被使用做匹配,
|
||||
以此类推,直到没有标签。
|
||||
|
||||
如果没有匹配到,流量会被拒绝,就如同这个 `Service` 根本没有后端。
|
||||
换言之,系统根据可用后端的第一个拓扑键来选择端点。
|
||||
如果这个字段被配置了而没有后端可以匹配客户端拓扑,那么这个 `Service`
|
||||
对那个客户端是没有后端的,链接应该是失败的。
|
||||
这个字段配置为 `"*"` 意味着任意拓扑。
|
||||
这个通配符值如果使用了,那么只有作为配置值列表中的最后一个才有用。
|
||||
|
||||
<!--
|
||||
If `topologyKeys` is not specified or empty, no topology constraints will be applied.
|
||||
|
||||
Consider a cluster with Nodes that are labeled with their hostname, zone name,
|
||||
and region name. Then you can set the `topologyKeys` values of a service to direct
|
||||
traffic as follows.
|
||||
|
||||
* Only to endpoints on the same node, failing if no endpoint exists on the node:
|
||||
`["kubernetes.io/hostname"]`.
|
||||
* Preferentially to endpoints on the same node, falling back to endpoints in the
|
||||
same zone, followed by the same region, and failing otherwise: `["kubernetes.io/hostname",
|
||||
"topology.kubernetes.io/zone", "topology.kubernetes.io/region"]`.
|
||||
This may be useful, for example, in cases where data locality is critical.
|
||||
* Preferentially to the same zone, but fallback on any available endpoint if
|
||||
none are available within this zone:
|
||||
`["topology.kubernetes.io/zone", "*"]`.
|
||||
-->
|
||||
如果 `topologyKeys` 没有指定或者为空,就没有启用这个拓扑约束。
|
||||
|
||||
一个集群中,其 `Node` 的标签被打为其主机名,区域名和地区名。
|
||||
那么就可以设置 `Service` 的 `topologyKeys` 的值,像下面的做法一样定向流量了。
|
||||
|
||||
* 只定向到同一个 `Node` 上的端点,`Node` 上没有端点存在时就失败:
|
||||
配置 `["kubernetes.io/hostname"]`。
|
||||
* 偏向定向到同一个 `Node` 上的端点,回退同一区域的端点上,然后是同一地区,
|
||||
其它情况下就失败:配置 `["kubernetes.io/hostname", "topology.kubernetes.io/zone", "topology.kubernetes.io/region"]`。
|
||||
这或许很有用,例如,数据局部性很重要的情况下。
|
||||
* 偏向于同一区域,但如果此区域中没有可用的终结点,则回退到任何可用的终结点:
|
||||
配置 `["topology.kubernetes.io/zone", "*"]`。
|
||||
|
||||
<!--
|
||||
## Constraints
|
||||
|
||||
* Service topology is not compatible with `externalTrafficPolicy=Local`, and
|
||||
therefore a Service cannot use both of these features. It is possible to use
|
||||
both features in the same cluster on different Services, only not on the same
|
||||
Service.
|
||||
|
||||
* Valid topology keys are currently limited to `kubernetes.io/hostname`,
|
||||
`topology.kubernetes.io/zone`, and `topology.kubernetes.io/region`, but will
|
||||
be generalized to other node labels in the future.
|
||||
|
||||
* Topology keys must be valid label keys and at most 16 keys may be specified.
|
||||
|
||||
* The catch-all value, `"*"`, must be the last value in the topology keys, if
|
||||
it is used.
|
||||
-->
|
||||
## 约束条件 {#constraints}
|
||||
|
||||
* 服务拓扑和 `externalTrafficPolicy=Local` 是不兼容的,所以 `Service` 不能同时使用这两种特性。
|
||||
但是在同一个集群的不同 `Service` 上是可以分别使用这两种特性的,只要不在同一个
|
||||
`Service` 上就可以。
|
||||
|
||||
* 有效的拓扑键目前只有:`kubernetes.io/hostname`、`topology.kubernetes.io/zone` 和
|
||||
`topology.kubernetes.io/region`,但是未来会推广到其它的 `Node` 标签。
|
||||
|
||||
* 拓扑键必须是有效的标签,并且最多指定16个。
|
||||
|
||||
* 通配符:`"*"`,如果要用,则必须是拓扑键值的最后一个值。
|
||||
|
||||
<!--
|
||||
## Examples
|
||||
|
||||
The following are common examples of using the Service Topology feature.
|
||||
-->
|
||||
## 示例
|
||||
|
||||
以下是使用服务拓扑功能的常见示例。
|
||||
|
||||
<!--
|
||||
### Only Node Local Endpoints
|
||||
|
||||
A Service that only routes to node local endpoints. If no endpoints exist on the node, traffic is dropped:
|
||||
-->
|
||||
### 仅节点本地端点
|
||||
|
||||
仅路由到节点本地端点的一种服务。如果节点上不存在端点,流量则被丢弃:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: my-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
topologyKeys:
|
||||
- "kubernetes.io/hostname"
|
||||
```
|
||||
|
||||
<!--
|
||||
### Prefer Node Local Endpoints
|
||||
|
||||
A Service that prefers node local Endpoints but falls back to cluster wide endpoints if node local endpoints do not exist:
|
||||
-->
|
||||
### 首选节点本地端点
|
||||
|
||||
首选节点本地端点,如果节点本地端点不存在,则回退到集群范围端点的一种服务:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: my-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
topologyKeys:
|
||||
- "kubernetes.io/hostname"
|
||||
- "*"
|
||||
```
|
||||
|
||||
<!--
|
||||
### Only Zonal or Regional Endpoints
|
||||
|
||||
A Service that prefers zonal then regional endpoints. If no endpoints exist in either, traffic is dropped.
|
||||
-->
|
||||
### 仅地域或区域端点
|
||||
|
||||
首选地域端点而不是区域端点的一种服务。 如果以上两种范围内均不存在端点,
|
||||
流量则被丢弃。
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: my-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
topologyKeys:
|
||||
- "topology.kubernetes.io/zone"
|
||||
- "topology.kubernetes.io/region"
|
||||
```
|
||||
|
||||
<!--
|
||||
### Prefer Node Local, Zonal, then Regional Endpoints
|
||||
|
||||
A Service that prefers node local, zonal, then regional endpoints but falls back to cluster wide endpoints.
|
||||
-->
|
||||
### 优先选择节点本地端点、地域端点,然后是区域端点
|
||||
|
||||
优先选择节点本地端点,地域端点,然后是区域端点,最后才是集群范围端点的
|
||||
一种服务。
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: my-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
topologyKeys:
|
||||
- "kubernetes.io/hostname"
|
||||
- "topology.kubernetes.io/zone"
|
||||
- "topology.kubernetes.io/region"
|
||||
- "*"
|
||||
```
|
||||
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
<!--
|
||||
* Read about [enabling Service Topology](/docs/tasks/administer-cluster/enabling-service-topology)
|
||||
* Read [Connecting Applications with Services](/docs/concepts/services-networking/connect-applications-service/)
|
||||
-->
|
||||
* 阅读关于[启用服务拓扑](/zh/docs/tasks/administer-cluster/enabling-service-topology/)
|
||||
* 阅读[用服务连接应用程序](/zh/docs/concepts/services-networking/connect-applications-service/)
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: 服务内部流量策略
|
||||
content_type: concept
|
||||
weight: 45
|
||||
---
|
||||
<!--
|
||||
---
|
||||
reviewers:
|
||||
- maplain
|
||||
title: Service Internal Traffic Policy
|
||||
content_type: concept
|
||||
weight: 45
|
||||
---
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.23" state="beta" >}}
|
||||
|
||||
<!--
|
||||
_Service Internal Traffic Policy_ enables internal traffic restrictions to only route
|
||||
internal traffic to endpoints within the node the traffic originated from. The
|
||||
"internal" traffic here refers to traffic originated from Pods in the current
|
||||
cluster. This can help to reduce costs and improve performance.
|
||||
-->
|
||||
_服务内部流量策略_ 开启了内部流量限制,只路由内部流量到和发起方处于相同节点的服务端点。
|
||||
这里的”内部“流量指当前集群中的 Pod 所发起的流量。
|
||||
这种机制有助于节省开销,提升效率。
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Using Service Internal Traffic Policy
|
||||
-->
|
||||
## 使用服务内部流量策略 {#using-service-internal-traffic-policy}
|
||||
|
||||
<!--
|
||||
The `ServiceInternalTrafficPolicy` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
|
||||
is a Beta feature and enabled by default.
|
||||
When the feature is enabled, you can enable the internal-only traffic policy for a
|
||||
{{< glossary_tooltip text="Services" term_id="service" >}}, by setting its
|
||||
`.spec.internalTrafficPolicy` to `Local`.
|
||||
This tells kube-proxy to only use node local endpoints for cluster internal traffic.
|
||||
-->
|
||||
`ServiceInternalTrafficPolicy`
|
||||
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/) 是 Beta 功能,默认启用。
|
||||
启用该功能后,你就可以通过将 {{< glossary_tooltip text="Services" term_id="service" >}} 的
|
||||
`.spec.internalTrafficPolicy` 项设置为 `Local`,
|
||||
来为它指定一个内部专用的流量策略。
|
||||
此设置就相当于告诉 kube-proxy 对于集群内部流量只能使用本地的服务端口。
|
||||
|
||||
<!--
|
||||
For pods on nodes with no endpoints for a given Service, the Service
|
||||
behaves as if it has zero endpoints (for Pods on this node) even if the service
|
||||
does have endpoints on other nodes.
|
||||
-->
|
||||
{{< note >}}
|
||||
如果某节点上的 Pod 均不提供指定 Service 的服务端点,
|
||||
即使该 Service 在其他节点上有可用的服务端点,
|
||||
Service 的行为看起来也像是它只有 0 个服务端点(只针对此节点上的 Pod)。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
The following example shows what a Service looks like when you set
|
||||
`.spec.internalTrafficPolicy` to `Local`:
|
||||
-->
|
||||
以下示例展示了把 Service 的 `.spec.internalTrafficPolicy` 项设为 `Local` 时,
|
||||
Service 的样子:
|
||||
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: MyApp
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
internalTrafficPolicy: Local
|
||||
```
|
||||
|
||||
<!--
|
||||
## How it works
|
||||
-->
|
||||
## 工作原理 {#how-it-works}
|
||||
|
||||
<!--
|
||||
The kube-proxy filters the endpoints it routes to based on the
|
||||
`spec.internalTrafficPolicy` setting. When it's set to `Local`, only node local
|
||||
endpoints are considered. When it's `Cluster` or missing, all endpoints are
|
||||
considered.
|
||||
When the [feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
|
||||
`ServiceInternalTrafficPolicy` is enabled, `spec.internalTrafficPolicy` defaults to "Cluster".
|
||||
-->
|
||||
kube-proxy 基于 `spec.internalTrafficPolicy` 的设置来过滤路由的目标服务端点。
|
||||
当它的值设为 `Local` 时,只选择节点本地的服务端点。
|
||||
当它的值设为 `Cluster` 或缺省时,则选择所有的服务端点。
|
||||
启用[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)
|
||||
`ServiceInternalTrafficPolicy` 后,
|
||||
`spec.internalTrafficPolicy` 的值默认设为 `Cluster`。
|
||||
|
||||
<!--
|
||||
## Constraints
|
||||
-->
|
||||
## 限制 {#constraints}
|
||||
|
||||
<!--
|
||||
* Service Internal Traffic Policy is not used when `externalTrafficPolicy` is set
|
||||
to `Local` on a Service. It is possible to use both features in the same cluster
|
||||
on different Services, just not on the same Service.
|
||||
-->
|
||||
* 在一个Service上,当 `externalTrafficPolicy` 已设置为 `Local`时,服务内部流量策略无法使用。
|
||||
换句话说,在一个集群的不同 Service 上可以同时使用这两个特性,但在一个 Service 上不行。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
* Read about [Topology Aware Hints](/docs/concepts/services-networking/topology-aware-hints)
|
||||
* Read about [Service External Traffic Policy](/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip)
|
||||
* Read [Connecting Applications with Services](/docs/concepts/services-networking/connect-applications-service/)
|
||||
-->
|
||||
* 请阅读[拓扑感知提示](/zh/docs/concepts/services-networking/topology-aware-hints)
|
||||
* 请阅读[Service 的外部流量策略](/zh/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip)
|
||||
* 请阅读[用 Service 连接应用](/zh/docs/concepts/services-networking/connect-applications-service/)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,295 @@
|
||||
---
|
||||
title: 拓扑感知提示
|
||||
content_type: concept
|
||||
weight: 45
|
||||
---
|
||||
<!--
|
||||
---
|
||||
reviewers:
|
||||
- robscott
|
||||
title: Topology Aware Hints
|
||||
content_type: concept
|
||||
weight: 45
|
||||
---
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.23" state="beta" >}}
|
||||
|
||||
<!--
|
||||
_Topology Aware Hints_ enable topology aware routing by including suggestions
|
||||
for how clients should consume endpoints. This approach adds metadata to enable
|
||||
consumers of EndpointSlice and / or Endpoints objects, so that traffic to
|
||||
those network endpoints can be routed closer to where it originated.
|
||||
|
||||
For example, you can route traffic within a locality to reduce
|
||||
costs, or to improve network performance.
|
||||
-->
|
||||
_拓扑感知提示_ 包含客户怎么使用服务端点的建议,从而实现了拓扑感知的路由功能。
|
||||
这种方法添加了元数据,以启用 EndpointSlice 和/或 Endpoints 对象的调用者,
|
||||
这样,访问这些网络端点的请求流量就可以在它的发起点附近就近路由。
|
||||
|
||||
例如,你可以在一个地域内路由流量,以降低通信成本,或提高网络性能。
|
||||
|
||||
<!--
|
||||
The "topology-aware hints" feature is at Beta stage and it is **NOT** enabled
|
||||
by default. To try out this feature, you have to enable the `TopologyAwareHints`
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/).
|
||||
-->
|
||||
|
||||
{{< note >}}
|
||||
“拓扑感知提示”特性处于 Beta 阶段,并且默认情况下**未**启用。
|
||||
要试用此特性,你必须启用 `TopologyAwareHints`
|
||||
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)。
|
||||
{{< /note >}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
<!--
|
||||
## Motivation
|
||||
-->
|
||||
## 动机 {#motivation}
|
||||
|
||||
<!--
|
||||
Kubernetes clusters are increasingly deployed in multi-zone environments.
|
||||
_Topology Aware Hints_ provides a mechanism to help keep traffic within the zone
|
||||
it originated from. This concept is commonly referred to as "Topology Aware
|
||||
Routing". When calculating the endpoints for a {{< glossary_tooltip term_id="Service" >}},
|
||||
the EndpointSlice controller considers the topology (region and zone) of each endpoint
|
||||
and populates the hints field to allocate it to a zone.
|
||||
Cluster components such as the {{< glossary_tooltip term_id="kube-proxy" text="kube-proxy" >}}
|
||||
can then consume those hints, and use them to influence how the traffic to is routed
|
||||
(favoring topologically closer endpoints).
|
||||
-->
|
||||
Kubernetes 集群越来越多的部署到多区域环境中。
|
||||
_拓扑感知提示_ 提供了一种把流量限制在它的发起区域之内的机制。
|
||||
这个概念一般被称之为 “拓扑感知路由”。
|
||||
在计算 {{< glossary_tooltip term_id="Service" >}} 的端点时,
|
||||
EndpointSlice 控制器会评估每一个端点的拓扑(地域和区域),填充提示字段,并将其分配到某个区域。
|
||||
集群组件,例如{{< glossary_tooltip term_id="kube-proxy" text="kube-proxy" >}}
|
||||
就可以使用这些提示信息,并用他们来影响流量的路由(倾向于拓扑上相邻的端点)。
|
||||
|
||||
<!--
|
||||
## Using Topology Aware Hints
|
||||
-->
|
||||
## 使用拓扑感知提示 {#using-topology-aware-hints}
|
||||
|
||||
<!--
|
||||
You can activate Topology Aware Hints for a Service by setting the
|
||||
`service.kubernetes.io/topology-aware-hints` annotation to `auto`. This tells
|
||||
the EndpointSlice controller to set topology hints if it is deemed safe.
|
||||
Importantly, this does not guarantee that hints will always be set.
|
||||
-->
|
||||
|
||||
你可以通过把注解 `service.kubernetes.io/topology-aware-hints` 的值设置为 `auto`,
|
||||
来激活服务的拓扑感知提示功能。
|
||||
这告诉 EndpointSlice 控制器在它认为安全的时候来设置拓扑提示。
|
||||
重要的是,这并不能保证总会设置提示(hints)。
|
||||
|
||||
<!--
|
||||
## How it works {#implementation}
|
||||
-->
|
||||
## 工作原理 {#implementation}
|
||||
|
||||
<!--
|
||||
The functionality enabling this feature is split into two components: The
|
||||
EndpointSlice controller and the kube-proxy. This section provides a high level overview
|
||||
of how each component implements this feature.
|
||||
-->
|
||||
此特性启用的功能分为两个组件:EndpointSlice 控制器和 kube-proxy。
|
||||
本节概述每个组件如何实现此特性。
|
||||
|
||||
<!--
|
||||
### EndpointSlice controller {#implementation-control-plane}
|
||||
-->
|
||||
### EndpointSlice 控制器 {#implementation-control-plane}
|
||||
|
||||
<!--
|
||||
The EndpointSlice controller is responsible for setting hints on EndpointSlices
|
||||
when this feature is enabled. The controller allocates a proportional amount of
|
||||
endpoints to each zone. This proportion is based on the
|
||||
[allocatable](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)
|
||||
CPU cores for nodes running in that zone. For example, if one zone had 2 CPU
|
||||
cores and another zone only had 1 CPU core, the controller would allocated twice
|
||||
as many endpoints to the zone with 2 CPU cores.
|
||||
-->
|
||||
此特性开启后,EndpointSlice 控制器负责在 EndpointSlice 上设置提示信息。
|
||||
控制器按比例给每个区域分配一定比例数量的端点。
|
||||
这个比例来源于此区域中运行节点的
|
||||
[可分配](/zh/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)
|
||||
CPU 核心数。
|
||||
例如,如果一个区域拥有 2 CPU 核心,而另一个区域只有 1 CPU 核心,
|
||||
那控制器将给那个有 2 CPU 的区域分配两倍数量的端点。
|
||||
|
||||
<!--
|
||||
The following example shows what an EndpointSlice looks like when hints have
|
||||
been populated:
|
||||
-->
|
||||
以下示例展示了提供提示信息后 EndpointSlice 的样子:
|
||||
|
||||
```yaml
|
||||
apiVersion: discovery.k8s.io/v1
|
||||
kind: EndpointSlice
|
||||
metadata:
|
||||
name: example-hints
|
||||
labels:
|
||||
kubernetes.io/service-name: example-svc
|
||||
addressType: IPv4
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
endpoints:
|
||||
- addresses:
|
||||
- "10.1.2.3"
|
||||
conditions:
|
||||
ready: true
|
||||
hostname: pod-1
|
||||
zone: zone-a
|
||||
hints:
|
||||
forZones:
|
||||
- name: "zone-a"
|
||||
```
|
||||
|
||||
### kube-proxy {#implementation-kube-proxy}
|
||||
|
||||
<!--
|
||||
The kube-proxy component filters the endpoints it routes to based on the hints set by
|
||||
the EndpointSlice controller. In most cases, this means that the kube-proxy is able
|
||||
to route traffic to endpoints in the same zone. Sometimes the controller allocates endpoints
|
||||
from a different zone to ensure more even distribution of endpoints between zones.
|
||||
This would result in some traffic being routed to other zones.
|
||||
-->
|
||||
kube-proxy 组件依据 EndpointSlice 控制器设置的提示,过滤由它负责路由的端点。
|
||||
在大多数场合,这意味着 kube-proxy 可以把流量路由到同一个区域的端点。
|
||||
有时,控制器从某个不同的区域分配端点,以确保在多个区域之间更平均的分配端点。
|
||||
这会导致部分流量被路由到其他区域。
|
||||
|
||||
<!--
|
||||
## Safeguards
|
||||
-->
|
||||
## 保护措施 {#safeguards}
|
||||
|
||||
<!--
|
||||
The Kubernetes control plane and the kube-proxy on each node apply some
|
||||
safeguard rules before using Topology Aware Hints. If these don't check out,
|
||||
the kube-proxy selects endpoints from anywhere in your cluster, regardless of the
|
||||
zone.
|
||||
-->
|
||||
Kubernetes 控制平面和每个节点上的 kube-proxy,在使用拓扑感知提示功能前,会应用一些保护措施规则。
|
||||
如果没有检出,kube-proxy 将无视区域限制,从集群中的任意节点上选择端点。
|
||||
|
||||
<!--
|
||||
1. **Insufficient number of endpoints:** If there are less endpoints than zones
|
||||
in a cluster, the controller will not assign any hints.
|
||||
-->
|
||||
1. **端点数量不足:** 如果一个集群中,端点数量少于区域数量,控制器不创建任何提示。
|
||||
|
||||
<!--
|
||||
2. **Impossible to achieve balanced allocation:** In some cases, it will be
|
||||
impossible to achieve a balanced allocation of endpoints among zones. For
|
||||
example, if zone-a is twice as large as zone-b, but there are only 2
|
||||
endpoints, an endpoint allocated to zone-a may receive twice as much traffic
|
||||
as zone-b. The controller does not assign hints if it can't get this "expected
|
||||
overload" value below an acceptable threshold for each zone. Importantly this
|
||||
is not based on real-time feedback. It is still possible for individual
|
||||
endpoints to become overloaded.
|
||||
-->
|
||||
2. **不可能实现均衡分配:** 在一些场合中,不可能实现端点在区域中的平衡分配。
|
||||
例如,假设 zone-a 比 zone-b 大两倍,但只有 2 个端点,
|
||||
那分配到 zone-a 的端点可能收到比 zone-b多两倍的流量。
|
||||
如果控制器不能确定此“期望的过载”值低于每一个区域可接受的阈值,控制器将不指派提示信息。
|
||||
重要的是,这不是基于实时反馈。所以对于单独的端点仍有可能超载。
|
||||
|
||||
<!--
|
||||
3. **One or more Nodes has insufficient information:** If any node does not have
|
||||
a `topology.kubernetes.io/zone` label or is not reporting a value for
|
||||
allocatable CPU, the control plane does not set any topology-aware endpoint
|
||||
hints and so kube-proxy does not filter endpoints by zone.
|
||||
-->
|
||||
3. **一个或多个节点信息不足:** 如果任一节点没有设置标签 `topology.kubernetes.io/zone`,
|
||||
或没有上报可分配的 CPU 数据,控制平面将不会设置任何拓扑感知提示,
|
||||
继而 kube-proxy 也就不能通过区域过滤端点。
|
||||
|
||||
<!--
|
||||
4. **One or more endpoints does not have a zone hint:** When this happens,
|
||||
the kube-proxy assumes that a transition from or to Topology Aware Hints is
|
||||
underway. Filtering endpoints for a Service in this state would be dangerous
|
||||
so the kube-proxy falls back to using all endpoints.
|
||||
-->
|
||||
4. **一个或多个端点没有设置区域提示:** 当这类事情发生时,
|
||||
kube-proxy 会假设这是正在执行一个从/到拓扑感知提示的转移。
|
||||
在这种场合下过滤Service 的端点是有风险的,所以 kube-proxy 回撤为使用所有的端点。
|
||||
|
||||
<!--
|
||||
5. **A zone is not represented in hints:** If the kube-proxy is unable to find
|
||||
at least one endpoint with a hint targeting the zone it is running in, it falls
|
||||
to using endpoints from all zones. This is most likely to happen as you add
|
||||
a new zone into your existing cluster.
|
||||
-->
|
||||
5. **不在提示中的区域:** 如果 kube-proxy 不能根据一个指示在它所在的区域中发现一个端点,
|
||||
它回撤为使用所有节点的端点。当你的集群新增一个新的区域时,这种情况发生概率很高。
|
||||
|
||||
<!--
|
||||
## Constraints
|
||||
-->
|
||||
## 限制 {#constraints}
|
||||
|
||||
<!--
|
||||
* Topology Aware Hints are not used when either `externalTrafficPolicy` or
|
||||
`internalTrafficPolicy` is set to `Local` on a Service. It is possible to use
|
||||
both features in the same cluster on different Services, just not on the same
|
||||
Service.
|
||||
-->
|
||||
* 当 Service 的 `externalTrafficPolicy` 或 `internalTrafficPolicy` 设置值为 `Local` 时,
|
||||
拓扑感知提示功能不可用。
|
||||
你可以在一个集群的不同服务中使用这两个特性,但不能在同一个服务中这么做。
|
||||
|
||||
<!--
|
||||
* This approach will not work well for Services that have a large proportion of
|
||||
traffic originating from a subset of zones. Instead this assumes that incoming
|
||||
traffic will be roughly proportional to the capacity of the Nodes in each
|
||||
zone.
|
||||
-->
|
||||
* 这种方法不适用于大部分流量来自于一部分区域的服务。
|
||||
相反的,这里假设入站流量将根据每个区域中节点的服务能力按比例的分配。
|
||||
|
||||
<!--
|
||||
* The EndpointSlice controller ignores unready nodes as it calculates the
|
||||
proportions of each zone. This could have unintended consequences if a large
|
||||
portion of nodes are unready.
|
||||
-->
|
||||
* EndpointSlice 控制器在计算每一个区域的容量比例时,会忽略未就绪的节点。
|
||||
在大量节点未就绪的场景下,这样做会带来非预期的结果。
|
||||
|
||||
<!--
|
||||
* The EndpointSlice controller does not take into account {{< glossary_tooltip
|
||||
text="tolerations" term_id="toleration" >}} when deploying calculating the
|
||||
proportions of each zone. If the Pods backing a Service are limited to a
|
||||
subset of Nodes in the cluster, this will not be taken into account.
|
||||
-->
|
||||
* EndpointSlice 控制器在计算每一个区域的部署比例时,并不会考虑
|
||||
{{< glossary_tooltip text="容忍度" term_id="toleration" >}}。
|
||||
如果服务后台的 Pod 被限制只能运行在集群节点的一个子集上,这些信息并不会被使用。
|
||||
|
||||
<!--
|
||||
* This may not work well with autoscaling. For example, if a lot of traffic is
|
||||
originating from a single zone, only the endpoints allocated to that zone will
|
||||
be handling that traffic. That could result in {{< glossary_tooltip
|
||||
text="Horizontal Pod Autoscaler" term_id="horizontal-pod-autoscaler" >}}
|
||||
either not picking up on this event, or newly added pods starting in a
|
||||
different zone.
|
||||
-->
|
||||
* 这种方法和自动扩展机制之间不能很好的协同工作。例如,如果大量流量来源于一个区域,
|
||||
那只有分配到该区域的端点才可用来处理流量。这会导致
|
||||
{{< glossary_tooltip text="Pod 自动水平扩展" term_id="horizontal-pod-autoscaler" >}}
|
||||
要么不能拾取此事件,要么新增 Pod 被启动到其他区域。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
* Read [Connecting Applications with Services](/docs/concepts/services-networking/connect-applications-service/)
|
||||
-->
|
||||
|
||||
* 参阅[通过服务连通应用](/zh/docs/concepts/services-networking/connect-applications-service/)
|
||||
@@ -0,0 +1,310 @@
|
||||
---
|
||||
title: Windows 网络
|
||||
content_type: concept
|
||||
weight: 75
|
||||
---
|
||||
<!--
|
||||
reviewers:
|
||||
- aravindhp
|
||||
- jayunit100
|
||||
- jsturtevant
|
||||
- marosset
|
||||
title: Networking on Windows
|
||||
content_type: concept
|
||||
weight: 75
|
||||
-->
|
||||
<!-- overview -->
|
||||
<!--
|
||||
Kubernetes supports running nodes on either Linux or Windows. You can mix both kinds of node within a single cluster.
|
||||
This page provides an overview to networking specific to the Windows operating system.
|
||||
-->
|
||||
Kubernetes 支持运行 Linux 或 Windows 节点。
|
||||
你可以在统一集群内混布这两种节点。
|
||||
本页提供了特定于 Windows 操作系统的网络概述。
|
||||
|
||||
<!-- body -->
|
||||
<!--
|
||||
## Container networking on Windows {#networking}
|
||||
|
||||
Networking for Windows containers is exposed through
|
||||
[CNI plugins](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/).
|
||||
Windows containers function similarly to virtual machines in regards to
|
||||
networking. Each container has a virtual network adapter (vNIC) which is connected
|
||||
to a Hyper-V virtual switch (vSwitch). The Host Networking Service (HNS) and the
|
||||
Host Compute Service (HCS) work together to create containers and attach container
|
||||
vNICs to networks. HCS is responsible for the management of containers whereas HNS
|
||||
is responsible for the management of networking resources such as:
|
||||
|
||||
* Virtual networks (including creation of vSwitches)
|
||||
* Endpoints / vNICs
|
||||
* Namespaces
|
||||
* Policies including packet encapsulations, load-balancing rules, ACLs, and NAT rules.
|
||||
-->
|
||||
## Windows 容器网络 {#networking}
|
||||
|
||||
Windows 容器网络通过 [CNI 插件](/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)暴露。
|
||||
Windows 容器网络的工作方式与虚拟机类似。
|
||||
每个容器都有一个连接到 Hyper-V 虚拟交换机(vSwitch)的虚拟网络适配器(vNIC)。
|
||||
主机网络服务(Host Networking Service,HNS)和主机计算服务(Host Comute Service,HCS)
|
||||
协同创建容器并将容器 vNIC 挂接到网络。
|
||||
HCS 负责管理容器,而 HNS 负责管理以下网络资源:
|
||||
|
||||
* 虚拟网络(包括创建 vSwitch)
|
||||
* Endpoint / vNIC
|
||||
* 命名空间
|
||||
* 包括数据包封装、负载均衡规则、ACL 和 NAT 规则在内的策略。
|
||||
|
||||
<!--
|
||||
The Windows HNS and vSwitch implement namespacing and can
|
||||
create virtual NICs as needed for a pod or container. However, many configurations such
|
||||
as DNS, routes, and metrics are stored in the Windows registry database rather than as
|
||||
files inside `/etc`, which is how Linux stores those configurations. The Windows registry for the container
|
||||
is separate from that of the host, so concepts like mapping `/etc/resolv.conf` from
|
||||
the host into a container don't have the same effect they would on Linux. These must
|
||||
be configured using Windows APIs run in the context of that container. Therefore
|
||||
CNI implementations need to call the HNS instead of relying on file mappings to pass
|
||||
network details into the pod or container.
|
||||
-->
|
||||
Windows HNS 和 vSwitch 实现命名空间划分,且可以按需为 Pod 或容器创建虚拟 NIC。
|
||||
然而,诸如 DNS、路由和指标等许多配置将存放在 Windows 注册表数据库中,
|
||||
而不是像 Linux 将这些配置作为文件存放在 `/etc` 内。
|
||||
针对容器的 Windows 注册表与主机的注册表是分开的,因此将 `/etc/resolv.conf`
|
||||
从主机映射到一个容器的类似概念与 Linux 上的效果不同。
|
||||
这些必须使用容器环境中运行的 Windows API 进行配置。
|
||||
因此,实现 CNI 时需要调用 HNS,而不是依赖文件映射将网络详情传递到 Pod 或容器中。
|
||||
|
||||
<!--
|
||||
## Network modes
|
||||
|
||||
Windows supports five different networking drivers/modes: L2bridge, L2tunnel,
|
||||
Overlay (Beta), Transparent, and NAT. In a heterogeneous cluster with Windows and Linux
|
||||
worker nodes, you need to select a networking solution that is compatible on both
|
||||
Windows and Linux. The following table lists the out-of-tree plugins are supported on Windows,
|
||||
with recommendations on when to use each CNI:
|
||||
-->
|
||||
## 网络模式 {#network-mode}
|
||||
|
||||
Windows 支持五种不同的网络驱动/模式:L2bridge、L2tunnel、Overlay (Beta)、Transparent 和 NAT。
|
||||
在 Windows 和 Linux 工作节点组成的异构集群中,你需要选择一个同时兼容 Windows 和 Linux 的网络方案。
|
||||
下表列出了 Windows 支持的树外插件,并给出了何时使用每种 CNI 的建议:
|
||||
|
||||
<!--
|
||||
| Network Driver | Description | Container Packet Modifications | Network Plugins | Network Plugin Characteristics |
|
||||
| -------------- | ----------- | ------------------------------ | --------------- | ------------------------------ |
|
||||
| L2bridge | Containers are attached to an external vSwitch. Containers are attached to the underlay network, although the physical network doesn't need to learn the container MACs because they are rewritten on ingress/egress. | MAC is rewritten to host MAC, IP may be rewritten to host IP using HNS OutboundNAT policy. | [win-bridge](https://github.com/containernetworking/plugins/tree/master/plugins/main/windows/win-bridge), [Azure-CNI](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md), Flannel host-gateway uses win-bridge | win-bridge uses L2bridge network mode, connects containers to the underlay of hosts, offering best performance. Requires user-defined routes (UDR) for inter-node connectivity. |
|
||||
| L2Tunnel | This is a special case of l2bridge, but only used on Azure. All packets are sent to the virtualization host where SDN policy is applied. | MAC rewritten, IP visible on the underlay network | [Azure-CNI](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md) | Azure-CNI allows integration of containers with Azure vNET, and allows them to leverage the set of capabilities that [Azure Virtual Network provides](https://azure.microsoft.com/en-us/services/virtual-network/). For example, securely connect to Azure services or use Azure NSGs. See [azure-cni for some examples](https://docs.microsoft.com/azure/aks/concepts-network#azure-cni-advanced-networking) |
|
||||
| Overlay | Containers are given a vNIC connected to an external vSwitch. Each overlay network gets its own IP subnet, defined by a custom IP prefix.The overlay network driver uses VXLAN encapsulation. | Encapsulated with an outer header. | [win-overlay](https://github.com/containernetworking/plugins/tree/master/plugins/main/windows/win-overlay), Flannel VXLAN (uses win-overlay) | win-overlay should be used when virtual container networks are desired to be isolated from underlay of hosts (e.g. for security reasons). Allows for IPs to be re-used for different overlay networks (which have different VNID tags) if you are restricted on IPs in your datacenter. This option requires [KB4489899](https://support.microsoft.com/help/4489899) on Windows Server 2019. |
|
||||
| Transparent (special use case for [ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes)) | Requires an external vSwitch. Containers are attached to an external vSwitch which enables intra-pod communication via logical networks (logical switches and routers). | Packet is encapsulated either via [GENEVE](https://datatracker.ietf.org/doc/draft-gross-geneve/) or [STT](https://datatracker.ietf.org/doc/draft-davie-stt/) tunneling to reach pods which are not on the same host. <br/> Packets are forwarded or dropped via the tunnel metadata information supplied by the ovn network controller. <br/> NAT is done for north-south communication. | [ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes) | [Deploy via ansible](https://github.com/openvswitch/ovn-kubernetes/tree/master/contrib). Distributed ACLs can be applied via Kubernetes policies. IPAM support. Load-balancing can be achieved without kube-proxy. NATing is done without using iptables/netsh. |
|
||||
| NAT (*not used in Kubernetes*) | Containers are given a vNIC connected to an internal vSwitch. DNS/DHCP is provided using an internal component called [WinNAT](https://techcommunity.microsoft.com/t5/virtualization/windows-nat-winnat-capabilities-and-limitations/ba-p/382303) | MAC and IP is rewritten to host MAC/IP. | [nat](https://github.com/Microsoft/windows-container-networking/tree/master/plugins/nat) | Included here for completeness |
|
||||
-->
|
||||
| 网络驱动 | 描述 | 容器数据包修改 | 网络插件 | 网络插件特点 |
|
||||
| -------------- | ----------- | ------------------------------ | --------------- | ------------------------------ |
|
||||
| L2bridge | 容器挂接到一个外部 vSwitch。容器挂接到下层网络,但物理网络不需要了解容器的 MAC,因为这些 MAC 在入站/出站时被重写。 | MAC 被重写为主机 MAC,可使用 HNS OutboundNAT 策略将 IP 重写为主机 IP。 | [win-bridge](https://github.com/containernetworking/plugins/tree/master/plugins/main/windows/win-bridge)、[Azure-CNI](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md)、Flannel host-gateway 使用 win-bridge| win-bridge 使用 L2bridge 网络模式,将容器连接到主机的下层,提供最佳性能。节点间连接需要用户定义的路由(UDR)。 |
|
||||
| L2Tunnel | 这是 L2bridge 的一种特例,但仅用在 Azure 上。所有数据包都会被发送到应用了 SDN 策略的虚拟化主机。 | MAC 被重写,IP 在下层网络上可见。| [Azure-CNI](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md) | Azure-CNI 允许将容器集成到 Azure vNET,允许容器充分利用 [Azure 虚拟网络](https://azure.microsoft.com/zh-cn/services/virtual-network/)所提供的能力集合。例如,安全地连接到 Azure 服务或使用 Azure NSG。参考 [azure-cni 了解有关示例](https://docs.microsoft.com/zh-cn/azure/aks/concepts-network#azure-cni-advanced-networking)。 |
|
||||
| Overlay | 容器被赋予一个 vNIC,连接到外部 vSwitch。每个上层网络都有自己的 IP 子网,由自定义 IP 前缀进行定义。该上层网络驱动使用 VXLAN 封装。 | 用外部头进行封装。 | [win-overlay](https://github.com/containernetworking/plugins/tree/master/plugins/main/windows/win-overlay)、Flannel VXLAN(使用 win-overlay) | 当需要将虚拟容器网络与主机的下层隔离时(例如出于安全原因),应使用 win-overlay。如果你的数据中心的 IP 个数有限,可以将 IP 在不同的上层网络中重用(带有不同的 VNID 标记)。在 Windows Server 2019 上这个选项需要 [KB4489899](https://support.microsoft.com/zh-cn/help/4489899)。 |
|
||||
| Transparent([ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes) 的特殊用例) | 需要一个外部 vSwitch。容器挂接到一个外部 vSwitch,由后者通过逻辑网络(逻辑交换机和路由器)实现 Pod 内通信。 | 数据包通过 [GENEVE](https://datatracker.ietf.org/doc/draft-gross-geneve/) 或 [STT](https://datatracker.ietf.org/doc/draft-davie-stt/) 隧道进行封装,以到达其它主机上的 Pod。 <br/> 数据包基于 OVN 网络控制器提供的隧道元数据信息被转发或丢弃。<br/>南北向通信使用 NAT。 | [ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes) | [通过 ansible 部署](https://github.com/openvswitch/ovn-kubernetes/tree/master/contrib)。通过 Kubernetes 策略可以实施分布式 ACL。支持 IPAM。无需 kube-proxy 即可实现负载均衡。无需 iptables/netsh 即可进行 NAT。 |
|
||||
| NAT(**Kubernetes 中未使用**) | 容器被赋予一个 vNIC,连接到内部 vSwitch。DNS/DHCP 是使用一个名为 [WinNAT 的内部组件](https://techcommunity.microsoft.com/t5/virtualization/windows-nat-winnat-capabilities-and-limitations/ba-p/382303)实现的 | MAC 和 IP 重写为主机 MAC/IP。 | [nat](https://github.com/Microsoft/windows-container-networking/tree/master/plugins/nat) | 放在此处保持完整性。 |
|
||||
|
||||
<!--
|
||||
As outlined above, the [Flannel](https://github.com/coreos/flannel)
|
||||
[CNI plugin](https://github.com/flannel-io/cni-plugin)
|
||||
is also [supported](https://github.com/flannel-io/cni-plugin#windows-support-experimental) on Windows via the
|
||||
[VXLAN network backend](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan) (**Beta support** ; delegates to win-overlay)
|
||||
and [host-gateway network backend](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#host-gw) (stable support; delegates to win-bridge).
|
||||
-->
|
||||
如上所述,Windows 通过 [VXLAN 网络后端](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan)(**Beta 支持**;委派给 win-overlay)
|
||||
和 [host-gateway 网络后端](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#host-gw)(稳定支持;委派给 win-bridge)
|
||||
也[支持](https://github.com/flannel-io/cni-plugin#windows-support-experimental) [Flannel](https://github.com/coreos/flannel) 的 [CNI 插件](https://github.com/flannel-io/cni-plugin)。
|
||||
|
||||
<!--
|
||||
This plugin supports delegating to one of the reference CNI plugins (win-overlay,
|
||||
win-bridge), to work in conjunction with Flannel daemon on Windows (Flanneld) for
|
||||
automatic node subnet lease assignment and HNS network creation. This plugin reads
|
||||
in its own configuration file (cni.conf), and aggregates it with the environment
|
||||
variables from the FlannelD generated subnet.env file. It then delegates to one of
|
||||
the reference CNI plugins for network plumbing, and sends the correct configuration
|
||||
containing the node-assigned subnet to the IPAM plugin (for example: `host-local`).
|
||||
-->
|
||||
此插件支持委派给参考 CNI 插件(win-overlay、win-bridge)之一,配合使用 Windows
|
||||
上的 Flannel 守护程序(Flanneld),以便自动分配节点子网租赁并创建 HNS 网络。
|
||||
该插件读取自己的配置文件(cni.conf),并聚合 FlannelD 生成的 subnet.env 文件中的环境变量。
|
||||
然后,委派给网络管道的参考 CNI 插件之一,并将包含节点分配子网的正确配置发送给 IPAM 插件(例如:`host-local`)。
|
||||
|
||||
<!--
|
||||
For Node, Pod, and Service objects, the following network flows are supported for
|
||||
TCP/UDP traffic:
|
||||
|
||||
* Pod → Pod (IP)
|
||||
* Pod → Pod (Name)
|
||||
* Pod → Service (Cluster IP)
|
||||
* Pod → Service (PQDN, but only if there are no ".")
|
||||
* Pod → Service (FQDN)
|
||||
* Pod → external (IP)
|
||||
* Pod → external (DNS)
|
||||
* Node → Pod
|
||||
* Pod → Node
|
||||
-->
|
||||
对于 Node、Pod 和 Service 对象,TCP/UDP 流量支持以下网络流:
|
||||
|
||||
* Pod → Pod(IP)
|
||||
* Pod → Pod(名称)
|
||||
* Pod → Service(集群 IP)
|
||||
* Pod → Service(PQDN,但前提是没有 ".")
|
||||
* Pod → Service(FQDN)
|
||||
* Pod → 外部(IP)
|
||||
* Pod → 外部(DNS)
|
||||
* Node → Pod
|
||||
* Pod → Node
|
||||
|
||||
<!--
|
||||
## IP address management (IPAM) {#ipam}
|
||||
|
||||
The following IPAM options are supported on Windows:
|
||||
|
||||
* [host-local](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local)
|
||||
* [azure-vnet-ipam](https://github.com/Azure/azure-container-networking/blob/master/docs/ipam.md) (for azure-cni only)
|
||||
* [Windows Server IPAM](https://docs.microsoft.com/windows-server/networking/technologies/ipam/ipam-top) (fallback option if no IPAM is set)
|
||||
-->
|
||||
## IP 地址管理(IPAM) {#ipam}
|
||||
|
||||
Windows 支持以下 IPAM 选项:
|
||||
|
||||
* [host-local](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local)
|
||||
* [azure-vnet-ipam](https://github.com/Azure/azure-container-networking/blob/master/docs/ipam.md)(仅适用于 azure-cni)
|
||||
* [Windows Server IPAM](https://docs.microsoft.com/zh-cn/windows-server/networking/technologies/ipam/ipam-top)(未设置 IPAM 时的回滚选项)
|
||||
|
||||
<!--
|
||||
## Load balancing and Services
|
||||
|
||||
A Kubernetes {{< glossary_tooltip text="Service" term_id="service" >}} is an abstraction
|
||||
that defines a logical set of Pods and a means to access them over a network.
|
||||
In a cluster that includes Windows nodes, you can use the following types of Service:
|
||||
-->
|
||||
## 负载均衡和 Service {#load-balancing-and-services}
|
||||
|
||||
Kubernetes {{< glossary_tooltip text="Service" term_id="service" >}} 是一种抽象:定义了逻辑上的一组 Pod 和一种通过网络访问这些 Pod 的方式。
|
||||
在包含 Windows 节点的集群中,你可以使用以下类别的 Service:
|
||||
|
||||
* `NodePort`
|
||||
* `ClusterIP`
|
||||
* `LoadBalancer`
|
||||
* `ExternalName`
|
||||
|
||||
<!--
|
||||
Windows container networking differs in some important ways from Linux networking.
|
||||
The [Microsoft documentation for Windows Container Networking](https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/architecture)
|
||||
provides additional details and background.
|
||||
|
||||
On Windows, you can use the following settings to configure Services and load
|
||||
balancing behavior:
|
||||
-->
|
||||
Windows 容器网络与 Linux 网络有着很重要的差异。
|
||||
更多细节和背景信息,参考 [Microsoft Windows 容器网络文档](https://docs.microsoft.com/zh-cn/virtualization/windowscontainers/container-networking/architecture)。
|
||||
|
||||
在 Windows 上,你可以使用以下设置来配置 Service 和负载均衡行为:
|
||||
|
||||
<!--
|
||||
{{< table caption="Windows Service Settings" >}}
|
||||
| Feature | Description | Minimum Supported Windows OS build | How to enable |
|
||||
| ------- | ----------- | -------------------------- | ------------- |
|
||||
| Session affinity | Ensures that connections from a particular client are passed to the same Pod each time. | Windows Server 2022 | Set `service.spec.sessionAffinity` to "ClientIP" |
|
||||
| Direct Server Return (DSR) | Load balancing mode where the IP address fixups and the LBNAT occurs at the container vSwitch port directly; service traffic arrives with the source IP set as the originating pod IP. | Windows Server 2019 | Set the following flags in kube-proxy: `--feature-gates="WinDSR=true" --enable-dsr=true` |
|
||||
| Preserve-Destination | Skips DNAT of service traffic, thereby preserving the virtual IP of the target service in packets reaching the backend Pod. Also disables node-node forwarding. | Windows Server, version 1903 | Set `"preserve-destination": "true"` in service annotations and enable DSR in kube-proxy. |
|
||||
| IPv4/IPv6 dual-stack networking | Native IPv4-to-IPv4 in parallel with IPv6-to-IPv6 communications to, from, and within a cluster | Windows Server 2019 | See [IPv4/IPv6 dual-stack](#ipv4ipv6-dual-stack) |
|
||||
| Client IP preservation | Ensures that source IP of incoming ingress traffic gets preserved. Also disables node-node forwarding. | Windows Server 2019 | Set `service.spec.externalTrafficPolicy` to "Local" and enable DSR in kube-proxy |
|
||||
{{< /table >}}
|
||||
-->
|
||||
{{< table caption="Windows Service 设置" >}}
|
||||
| 功能特性 | 描述 | 支持的 Windows 操作系统最低版本 | 启用方式 |
|
||||
| ------- | ----------- | -------------------------- | ------------- |
|
||||
| 会话亲和性 | 确保每次都将来自特定客户端的连接传递到同一个 Pod。 | Windows Server 2022 | 将 `service.spec.sessionAffinity` 设为 “ClientIP” |
|
||||
| Direct Server Return (DSR) | 在负载均衡模式中 IP 地址修正和 LBNAT 直接发生在容器 vSwitch 端口;服务流量到达时源 IP 设置为原始 Pod IP。 | Windows Server 2019 | 在 kube-proxy 中设置以下标志:`--feature-gates="WinDSR=true" --enable-dsr=true` |
|
||||
| 保留目标(Preserve-Destination) | 跳过服务流量的 DNAT,从而在到达后端 Pod 的数据包中保留目标服务的虚拟 IP。也会禁用节点间的转发。 | Windows Server,version 1903 | 在服务注解中设置 `"preserve-destination": "true"` 并在 kube-proxy 中启用 DSR。 |
|
||||
| IPv4/IPv6 双栈网络 | 进出集群和集群内通信都支持原生的 IPv4 间与 IPv6 间流量 | Windows Server 2019 | 参考 [IPv4/IPv6 双栈](#ipv4ipv6-dual-stack)。 |
|
||||
| 客户端 IP 保留 | 确保入站流量的源 IP 得到保留。也会禁用节点间转发。 | Windows Server 2019 | 将 `service.spec.externalTrafficPolicy` 设置为 “Local” 并在 kube-proxy 中启用 DSR。 |
|
||||
{{< /table >}}
|
||||
|
||||
<!--
|
||||
There are known issue with NodePort Services on overlay networking, if the destination node is running Windows Server 2022.
|
||||
To avoid the issue entirely, you can configure the service with `externalTrafficPolicy: Local`.
|
||||
|
||||
There are known issues with Pod to Pod connectivity on l2bridge network on Windows Server 2022 with KB5005619 or higher installed.
|
||||
To workaround the issue and restore Pod to Pod connectivity, you can disable the WinDSR feature in kube-proxy.
|
||||
|
||||
These issues require OS fixes.
|
||||
Please follow https://github.com/microsoft/Windows-Containers/issues/204 for updates.
|
||||
-->
|
||||
{{< warning >}}
|
||||
如果目的地节点在运行 Windows Server 2022,则上层网络的 NodePort Service 存在已知问题。
|
||||
要完全避免此问题,可以使用 `externalTrafficPolicy: Local` 配置服务。
|
||||
|
||||
在安装了 KB5005619 的 Windows Server 2022 或更高版本上,采用 L2bridge 网络时
|
||||
Pod 间连接存在已知问题。
|
||||
要解决此问题并恢复 Pod 间连接,你可以在 kube-proxy 中禁用 WinDSR 功能。
|
||||
|
||||
这些问题需要操作系统修复。
|
||||
有关更新,请参考 https://github.com/microsoft/Windows-Containers/issues/204。
|
||||
{{< /warning >}}
|
||||
|
||||
<!--
|
||||
## Limitations
|
||||
|
||||
The following networking functionality is _not_ supported on Windows nodes:
|
||||
|
||||
* Host networking mode
|
||||
* Local NodePort access from the node itself (works for other nodes or external clients)
|
||||
* More than 64 backend pods (or unique destination addresses) for a single Service
|
||||
* IPv6 communication between Windows pods connected to overlay networks
|
||||
* Local Traffic Policy in non-DSR mode
|
||||
-->
|
||||
## 限制 {#limitations}
|
||||
|
||||
Windows 节点**不支持**以下网络功能:
|
||||
|
||||
* 主机网络模式
|
||||
* 从节点本身访问本地 NodePort(可以从其他节点或外部客户端进行访问)
|
||||
* 为同一 Service 提供 64 个以上后端 Pod(或不同目的地址)
|
||||
* 在连接到上层网络的 Windows Pod 之间使用 IPv6 通信
|
||||
* 非 DSR 模式中的本地流量策略(Local Traffic Policy)
|
||||
|
||||
<!--
|
||||
* Outbound communication using the ICMP protocol via the `win-overlay`, `win-bridge`, or using the Azure-CNI plugin.\
|
||||
Specifically, the Windows data plane ([VFP](https://www.microsoft.com/research/project/azure-virtual-filtering-platform/))
|
||||
doesn't support ICMP packet transpositions, and this means:
|
||||
* ICMP packets directed to destinations within the same network (such as pod to pod communication via ping)
|
||||
work as expected;
|
||||
* TCP/UDP packets work as expected;
|
||||
* ICMP packets directed to pass through a remote network (e.g. pod to external internet communication via ping)
|
||||
cannot be transposed and thus will not be routed back to their source;
|
||||
* Since TCP/UDP packets can still be transposed, you can substitute `ping <destination>` with
|
||||
`curl <destination>` when debugging connectivity with the outside world.
|
||||
-->
|
||||
* 通过 `win-overlay`、`win-bridge` 使用 ICMP 协议,或使用 Azure-CNI 插件进行出站通信。
|
||||
具体而言,Windows 数据平面([VFP](https://www.microsoft.com/research/project/azure-virtual-filtering-platform/))不支持 ICMP 数据包转换,这意味着:
|
||||
* 指向同一网络内目的地址的 ICMP 数据包(例如 Pod 间的 ping 通信)可正常工作;
|
||||
* TCP/UDP 数据包可正常工作;
|
||||
* 通过远程网络指向其它地址的 ICMP 数据包(例如通过 ping 从 Pod 到外部公网的通信)无法被转换,
|
||||
因此无法被路由回到这些数据包的源点;
|
||||
* 由于 TCP/UDP 数据包仍可被转换,所以在调试与外界的连接时,
|
||||
你可以将 `ping <destination>` 替换为 `curl <destination>`。
|
||||
|
||||
<!--
|
||||
Other limitations:
|
||||
|
||||
* Windows reference network plugins win-bridge and win-overlay do not implement
|
||||
[CNI spec](https://github.com/containernetworking/cni/blob/master/SPEC.md) v0.4.0,
|
||||
due to a missing `CHECK` implementation.
|
||||
* The Flannel VXLAN CNI plugin has the following limitations on Windows:
|
||||
* Node-pod connectivity is only possible for local pods with Flannel v0.12.0 (or higher).
|
||||
* Flannel is restricted to using VNI 4096 and UDP port 4789. See the official
|
||||
[Flannel VXLAN](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan)
|
||||
backend docs for more details on these parameters.
|
||||
-->
|
||||
其他限制:
|
||||
|
||||
* 由于缺少 `CHECK` 实现,Windows 参考网络插件 win-bridge 和 win-overlay 未实现
|
||||
[CNI 规约](https://github.com/containernetworking/cni/blob/master/SPEC.md) 的 v0.4.0 版本。
|
||||
* Flannel VXLAN CNI 插件在 Windows 上有以下限制:
|
||||
* 使用 Flannel v0.12.0(或更高版本)时,节点到 Pod 的连接仅适用于本地 Pod。
|
||||
* Flannel 仅限于使用 VNI 4096 和 UDP 端口 4789。
|
||||
有关这些参数的更多详细信息,请参考官方的 [Flannel VXLAN](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan) 后端文档。
|
||||
Reference in New Issue
Block a user