[zh] Resync setup section (2)

This commit is contained in:
Qiming Teng
2021-04-26 16:14:23 +08:00
parent 1869573927
commit 544d3c2fb7
7 changed files with 595 additions and 744 deletions
@@ -1,5 +1,5 @@
---
title: 运行于多区环境
title: 运行于多可用区环境
weight: 10
content_type: concept
---
@@ -16,591 +16,267 @@ content_type: concept
<!-- overview -->
<!--
This page describes how to run a cluster in multiple zones.
This page describes running a cluster across multiple zones.
-->
本页描述如何多个区(Zone)中运行集群。
本页描述如何多个区(Zone)中运行集群。
<!-- body -->
<!--
## Introduction
## Background
Kubernetes 1.2 adds support for running a single cluster in multiple failure zones
(GCE calls them simply "zones", AWS calls them "availability zones", here we'll refer to them as "zones").
This is a lightweight version of a broader Cluster Federation feature (previously referred to by the affectionate
nickname ["Ubernetes"](https://github.com/kubernetes/community/blob/{{< param "githubbranch" >}}/contributors/design-proposals/multicluster/federation.md)).
Full Cluster Federation allows combining separate
Kubernetes clusters running in different regions or cloud providers
(or on-premises data centers). However, many
users simply want to run a more available Kubernetes cluster in multiple zones
of their single cloud provider, and this is what the multizone support in 1.2 allows
(this previously went by the nickname "Ubernetes Lite").
Kubernetes is designed so that a single Kubernetes cluster can run
across multiple failure zones, typically where these zones fit within
a logical grouping called a _region_. Major cloud providers define a region
as a set of failure zones (also called _availability zones_) that provide
a consistent set of features: within a region, each zone offers the same
APIs and services.
Typical cloud architectures aim to minimize the chance that a failure in
one zone also impairs services in another zone.
-->
## 介绍
## 背景
Kubernetes 1.2 添加了跨多个失效区(Failure Zone)运行同一集群的能力
(GCE 把它们称作“区(Zones)”,AWS 把它们称作“可用区(Availability Zones)”,
这里我们用“区(Zones)”指代它们)。
此能力是更广泛的集群联邦(Cluster Federation)特性的一个轻量级版本
集群联邦之前有一个昵称
["Ubernetes"](https://github.com/kubernetes/community/blob/{{< param "githubbranch" >}}/contributors/design-proposals/multicluster/federation.md))
完全的集群联邦可以将运行在多个区域(Region)或云供应商(或本地数据中心)的多个
Kubernetes 集群组合起来。
不过,很多用户仅仅是希望在同一云厂商平台的多个区域运行一个可用性更好的集群,
而这恰恰是 1.2 引入的多区支持所带来的特性
(此特性之前有一个昵称 “Ubernetes Lite”)。
Kubernetes 从设计上允许同一个 Kubernetes 集群跨多个失效区来运行,
通常这些去位于某个称作 _区域(region_ 逻辑分组中。
主要的云提供商都将区域定义为一组失效区的集合(也称作 _可用区(Availability Zones_),
能够提供一组一致的功能特性:每个区域内,各个可用区提供相同的 API 和服务
典型的云体系结构都会尝试降低某个区中的失效影响到其他区中服务的概率
<!--
Multizone support is deliberately limited: a single Kubernetes cluster can run
in multiple zones, but only within the same region (and cloud provider). Only
GCE and AWS are currently supported automatically (though it is easy to
add similar support for other clouds or even bare metal, by simply arranging
for the appropriate labels to be added to nodes and volumes).
## Control plane behavior
All [control plane components](/docs/concepts/overview/components/#control-plane-components)
support running as a pool of interchangeable resources, replicated per
component.
-->
多区支持有意实现的有局限性:可以在跨多个区域运行同一 Kubernetes 集群,但只能
在同一区域(Region)和云厂商平台。目前仅自动支持 GCE 和 AWS,尽管为其他云平台
或裸金属平台添加支持页相对容易,只需要确保节点和卷上添加合适的标签即可。
## 控制面行为 {#control-plane-behavior}
所有的[控制面组件](/zh/docs/concepts/overview/components/#control-plane-components)
都支持以一组可相互替换的资源池的形式来运行,每个组件都有多个副本。
<!--
## Functionality
When nodes are started, the kubelet automatically adds labels to them with
zone information.
When you deploy a cluster control plane, place replicas of
control plane components across multiple failure zones. If availability is
an important concern, select at least three failure zones and replicate
each individual control plane component (API server, scheduler, etcd,
cluster controller manager) across at least three failure zones.
If you are running a cloud controller manager then you should
also replicate this across all the failure zones you selected.
-->
## 功能
当你部署集群控制面时,应将控制面组件的副本跨多个失效区来部署。
如果可用性是一个很重要的指标,应该选择至少三个失效区,并将每个
控制面组件(API 服务器、调度器、etcd、控制器管理器)复制多个副本,
跨至少三个失效区来部署。如果你在运行云控制器管理器,则也应该将
该组件跨所选的三个失效区来部署。
节点启动时,`kubelet` 自动向其上添加区信息标签。
<!--
Kubernetes will automatically spread the pods in a replication controller
or service across nodes in a single-zone cluster (to reduce the impact of
failures.) With multiple-zone clusters, this spreading behavior is
extended across zones (to reduce the impact of zone failures.) (This is
achieved via `SelectorSpreadPriority`). This is a best-effort
placement, and so if the zones in your cluster are heterogeneous
(e.g. different numbers of nodes, different types of nodes, or
different pod resource requirements), this might prevent perfectly
even spreading of your pods across zones. If desired, you can use
homogeneous zones (same number and types of nodes) to reduce the
probability of unequal spreading.
-->
在单区(Single-Zone)集群中, Kubernetes 会自动将副本控制器或服务中的 Pod
分布到不同节点,以降低节点失效的影响。
在多区集群中,这一分布负载的行为被扩展到跨区分布,以降低区失效的影响,
跨区分布的能力是通过 `SelectorSpreadPriority` 实现的。此放置策略亦仅仅是
尽力而为,所以如果你的集群所跨区是异质的(例如,节点个数不同、节点类型
不同或者 Pod 资源需求不同),放置策略都可能无法完美地跨区完成 Pod 的
均衡分布。如果需要,你可以使用同质区(节点个数和类型相同)以降低不均衡
分布的可能性。
<!--
When persistent volumes are created, the `PersistentVolumeLabel`
admission controller automatically adds zone labels to them. The scheduler (via the
`VolumeZonePredicate` predicate) will then ensure that pods that claim a
given volume are only placed into the same zone as that volume, as volumes
cannot be attached across zones.
-->
持久卷被创建时,`PersistentVolumeLabel` 准入控制器会自动为其添加区标签。
调度器使用 `VolumeZonePredicate` 断言确保申领某给定卷的 Pod 只会被放到
该卷所在的区。这是因为卷不可以跨区挂载。
<!--
## Limitations
There are some important limitations of the multizone support:
* We assume that the different zones are located close to each other in the
network, so we don't perform any zone-aware routing. In particular, traffic
that goes via services might cross zones (even if some pods backing that service
exist in the same zone as the client), and this may incur additional latency and cost.
-->
## 局限性
多区支持有一些很重要的局限性:
* 我们假定不同的区之间在网络上彼此距离很近,所以我们不执行可感知区的路由。
尤其是,即使某些负责提供该服务的 Pod 与客户端位于同一区,通过服务末端
进入的流量可能会跨区,因而会导致一些额外的延迟和开销。
<!--
* Volume zone-affinity will only work with a `PersistentVolume`, and will not
work if you directly specify an EBS volume in the pod spec (for example).
* Clusters cannot span clouds or regions (this functionality will require full
federation support).
-->
* 卷与区之间的亲和性仅适用于 PV 持久卷。例如,如果你直接在 Pod 规约中指定某 EBS
卷,这种亲和性支持就无法工作。
* 集群无法跨多个云平台或者地理区域运行。这类功能需要完整的联邦特性支持。
<!--
* Although your nodes are in multiple zones, kube-up currently builds
a single master node by default. While services are highly
available and can tolerate the loss of a zone, the control plane is
located in a single zone. Users that want a highly available control
plane should follow the [high availability](/docs/setup/production-environment/tools/kubeadm/high-availability/) instructions.
-->
* 尽管你的节点位于多个区中,`kube-up` 脚本目前默认只能构造一个主控节点。
尽管服务是高可用的,能够忍受失去某个区的问题,控制面位于某一个区中。
希望运行高可用控制面的用户应该遵照
[高可用性](/zh/docs/setup/production-environment/tools/kubeadm/high-availability/)
中的指令构建。
<!--
### Volume limitations
The following limitations are addressed with
[topology-aware volume binding](/docs/concepts/storage/storage-classes/#volume-binding-mode).
* StatefulSet volume zone spreading when using dynamic provisioning is currently not compatible with
pod affinity or anti-affinity policies.
-->
### 卷局限性
以下局限性通过
[拓扑感知的卷绑定](/zh/docs/concepts/storage/storage-classes/#volume-binding-mode)解决:
* 使用动态卷供应时,StatefulSet 卷的跨区分布目前与 Pod
亲和性和反亲和性策略不兼容。
<!--
* If the name of the StatefulSet contains dashes ("-"), volume zone spreading
may not provide a uniform distribution of storage across zones.
* When specifying multiple PVCs in a Deployment or Pod spec, the StorageClass
needs to be configured for a specific single zone, or the PVs need to be
statically provisioned in a specific zone. Another workaround is to use a
StatefulSet, which will ensure that all the volumes for a replica are
provisioned in the same zone.
-->
* 如果 StatefulSet 的名字中包含连字符("-"),卷的跨区分布可能无法实现存储的
跨区同一分布。
* 当在一个 Deployment 或 Pod 规约中指定多个 PVC 申领时,则需要为某特定区域
配置 StorageClass,或者在某一特定区域中需要静态供应 PV 卷。
另一种解决方案是使用 StatefulSet,确保给定副本的所有卷都从同一区中供应。
<!--
## Walkthrough
We're now going to walk through setting up and using a multi-zone
cluster on both GCE & AWS. To do so, you bring up a full cluster
(specifying `MULTIZONE=true`), and then you add nodes in additional zones
by running `kube-up` again (specifying `KUBE_USE_EXISTING_MASTER=true`).
-->
## 演练
我们现在准备对在 GCE 和 AWS 上配置和使用多区集群进行演练。为了完成此演练,
你需要设置 `MULTIZONE=true` 来启动一个完整的集群,之后指定
`KUBE_USE_EXISTING_MASTER=true` 并再次运行 `kube-up` 添加其他区中的节点。
<!--
### Bringing up your cluster
Create the cluster as normal, but pass MULTIZONE to tell the cluster to manage multiple zones; creating nodes in us-central1-a.
-->
### 建立集群
和往常一样创建集群,不过需要设置 MULTIZONE,以便告诉集群需要管理多个区。
这里我们在 `us-central1-a` 创建节点。
GCE:
```shell
curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a NUM_NODES=3 bash
```
AWS:
```shell
curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a NUM_NODES=3 bash
```
<!--
This step brings up a cluster as normal, still running in a single zone
(but `MULTIZONE=true` has enabled multi-zone capabilities).
-->
这一步骤和往常一样启动一个集群,不过尽管 `MULTIZONE=true`
标志已经启用了多区功能特性支持,集群仍然运行在一个区内。
<!--
### Nodes are labeled
View the nodes; you can see that they are labeled with zone information.
They are all in `us-central1-a` (GCE) or `us-west-2a` (AWS) so far. The
labels are `topology.kubernetes.io/region` for the region,
and `topology.kubernetes.io/zone` for the zone:
-->
### 节点已被打标签
查看节点,你会看到节点上已经有了区信息标签。
目前这些节点都在 `us-central1-a` (GCE) 或 `us-west-2a` (AWS)。
对于区域(Region),标签为 `topology.kubernetes.io/region`
对于区(Zone),标签为 `topology.kubernetes.io/zone`
```shell
kubectl get nodes --show-labels
```
<!--
The output is similar to this:
-->
输出类似于:
```
NAME STATUS ROLES AGE VERSION LABELS
kubernetes-master Ready,SchedulingDisabled <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-1,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-87j9 Ready <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
```
<!--
### Add more nodes in a second zone
Let's add another set of nodes to the existing cluster, reusing the
existing master, running in a different zone (us-central1-b or us-west-2b).
We run kube-up again, but by specifying `KUBE_USE_EXISTING_MASTER=true`
kube-up will not create a new master, but will reuse one that was previously
created instead.
-->
### 添加第二个区中的节点
让我们向现有集群中添加另外一组节点,复用现有的主控节点,但运行在不同的区
`us-central1-b``us-west-2b`)。
我们再次运行 `kube-up`,不过设置 `KUBE_USE_EXISTING_MASTER=true`
`kube-up` 不会创建新的主控节点,而会复用之前创建的主控节点。
GCE:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-b NUM_NODES=3 kubernetes/cluster/kube-up.sh
```
<!--
On AWS we also need to specify the network CIDR for the additional
subnet, along with the master internal IP address:
-->
在 AWS 上,我们还需要为额外的子网指定网络 CIDR,以及主控节点的内部 IP 地址:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2b NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.1.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
```
<!--
View the nodes again; 3 more nodes should have launched and be tagged
in us-central1-b:
-->
再次查看节点,你会看到新启动了三个节点并且其标签表明运行在 `us-central1-b` 区:
```shell
kubectl get nodes --show-labels
```
<!--
The output is similar to this:
-->
输出类似于:
```
NAME STATUS ROLES AGE VERSION LABELS
kubernetes-master Ready,SchedulingDisabled <none> 16m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-1,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-281d Ready <none> 2m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-87j9 Ready <none> 16m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready <none> 16m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready <none> 17m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
kubernetes-minion-pp2f Ready <none> 2m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-pp2f
kubernetes-minion-wf8i Ready <none> 2m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-wf8i
```
<!--
### Volume affinity
Create a volume using the dynamic volume creation (only PersistentVolumes are supported for zone affinity):
-->
### 卷亲和性
通过动态卷供应创建一个卷(只有 PV 持久卷支持区亲和性):
```bash
kubectl apply -f - <<EOF
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "claim1",
"annotations": {
"volume.alpha.kubernetes.io/storage-class": "foo"
}
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "5Gi"
}
}
}
}
EOF
```
<!--
For version 1.3+ Kubernetes will distribute dynamic PV claims across
the configured zones. For version 1.2, dynamic persistent volumes were
always created in the zone of the cluster master
(here us-central1-a / us-west-2a); that issue
([#23330](https://github.com/kubernetes/kubernetes/issues/23330))
was addressed in 1.3+.
-->
{{< note >}}
Kubernetes 1.3 及以上版本会将动态 PV 申领散布到所配置的各个区。
在 1.2 版本中,动态持久卷总是在集群主控节点所在的区
(这里的 `us-central1-a``us-west-2a`),
对应的 Issue ([#23330](https://github.com/kubernetes/kubernetes/issues/23330))
在 1.3 及以上版本中已经解决。
<!--
Kubernetes does not provide cross-zone resilience for the API server
endpoints. You can use various techniques to improve availability for
the cluster API server, including DNS round-robin, SRV records, or
a third-party load balancing solution with health checking.
-->
Kubernetes 并不会为 API 服务器端点提供跨失效区的弹性。
你可以为集群 API 服务器使用多种技术来提升其可用性,包括使用
DNS 轮转、SRV 记录或者带健康检查的第三方负载均衡解决方案等等。
{{< /note >}}
<!--
Now let's validate that Kubernetes automatically labeled the zone & region the PV was created in.
-->
现在我们来验证 Kubernetes 自动为 PV 打上了所在区或区域的标签:
## Node behavior
```shell
kubectl get pv --show-labels
```
Kubernetes automatically spreads the Pods for
workload resources (such as {{< glossary_tooltip text="Deployment" term_id="deployment" >}}
or {{< glossary_tooltip text="StatefulSet" term_id="statefulset" >}})
across different nodes in a cluster. This spreading helps
reduce the impact of failures.
-->
## 节点行为 {#node-behavior}
Kubernetes 自动为负载资源(如{{< glossary_tooltip text="Deployment" term_id="deployment" >}}
或 {{< glossary_tooltip text="StatefulSet" term_id="statefulset" >}})
跨集群中不同节点来部署其 Pods。
这种分布逻辑有助于降低失效带来的影响。
<!--
The output is similar to this:
When nodes start up, the kubelet on each node automatically adds
{{< glossary_tooltip text="labels" term_id="label" >}} to the Node object
that represents that specific kubelet in the Kubernetes API.
These labels can include
[zone information](/docs/reference/labels-annotations-taints/#topologykubernetesiozone).
-->
输出类似于:
```
NAME CAPACITY ACCESSMODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE LABELS
pv-gce-mj4gm 5Gi RWO Retain Bound default/claim1 manual 46s topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a
```
节点启动时,每个节点上的 kubelet 会向 Kubernetes API 中代表该 kubelet 的 Node 对象
添加 {{< glossary_tooltip text="标签" term_id="label" >}}。
这些标签可能包含[区信息](/zh/docs/reference/labels-annotations-taints/#topologykubernetesiozone)。
<!--
So now we will create a pod that uses the persistent volume claim.
Because GCE PDs / AWS EBS volumes cannot be attached across zones,
this means that this pod can only be created in the same zone as the volume:
If your cluster spans multiple zones or regions, you can use node labels
in conjunction with
[Pod topology spread constraints](/docs/concepts/workloads/pods/pod-topology-spread-constraints/)
to control how Pods are spread across your cluster among fault domains:
regions, zones, and even specific nodes.
These hints enable the
{{< glossary_tooltip text="scheduler" term_id="kube-scheduler" >}} to place
Pods for better expected availability, reducing the risk that a correlated
failure affects your whole workload.
-->
现在我们将创建一个使用 PVC 申领的 Pod。
由于 GCE PD 或 AWS EBS 卷都不能跨区挂载,这意味着 Pod 只能创建在卷所在的区:
```yaml
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: claim1
EOF
```
如果你的集群跨了多个可用区或者地理区域,你可以使用节点标签,结合
[Pod 拓扑分布约束](/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints/)
来控制如何在你的集群中多个失效域之间分布 Pods。这里的失效域可以是
地理区域、可用区甚至是特定节点。
这些提示信息使得{{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}}
能够更好地分布 Pods,以实现更好的可用性,降低因为某种失效给整个工作负载
带来的风险。
<!--
Note that the pod was automatically created in the same zone as the volume, as
cross-zone attachments are not generally permitted by cloud providers:
For example, you can set a constraint to make sure that the
3 replicas of a StatefulSet are all running in different zones to each
other, whenever that is feasible. You can define this declaratively
without explicitly defining which availability zones are in use for
each workload.
-->
注意 Pod 自动创建在卷所在的区,因为云平台提供商一般不允许跨区挂接存储卷。
```shell
kubectl describe pod mypod | grep Node
```
```
Node: kubernetes-minion-9vlv/10.240.0.5
```
例如,你可以设置一种约束,确保某个 StatefulSet 中的三个副本都运行在
不同的可用区中,只要其他条件允许。你可以通过声明的方式来定义这种约束,
而不需要显式指定每个工作负载使用哪些可用区。
<!--
And check node labels:
### Distributing nodes across zones
Kubernetes' core does not create nodes for you; you need to do that yourself,
or use a tool such as the [Cluster API](https://cluster-api.sigs.k8s.io/) to
manage nodes on your behalf.
Using tools such as the Cluster API you can define sets of machines to run as
worker nodes for your cluster across multiple failure domains, and rules to
automatically heal the cluster in case of whole-zone service disruption.
-->
检查节点标签:
### 跨多个区分布节点 {#distributing-nodes-across-zones}
```shell
kubectl get node kubernetes-minion-9vlv --show-labels
```
```
NAME STATUS AGE VERSION LABELS
kubernetes-minion-9vlv Ready 22m v1.6.0+fff5156 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
```
Kubernetes 的核心逻辑并不会帮你创建节点,你需要自行完成此操作,或者使用
类似 [Cluster API](https://cluster-api.sigs.k8s.io/) 这类工具来替你管理节点。
<!--
### Pods are spread across zones
Pods in a replication controller or service are automatically spread
across zones. First, let's launch more nodes in a third zone:
Using tools such as the Cluster API you can define sets of machines to run as
worker nodes for your cluster across multiple failure domains, and rules to
automatically heal the cluster in case of whole-zone service disruption.
-->
### Pod 跨区分布
同一副本控制器或服务的多个 Pod 会自动完成跨区分布。
首先,我们现在第三个区启动一些节点:
GCE:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-f NUM_NODES=3 kubernetes/cluster/kube-up.sh
```
AWS:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2c NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.2.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
```
使用类似 Cluster API 这类工具,你可以跨多个失效域来定义一组用做你的集群
工作节点的机器,以及当整个区的服务出现中断时如何自动治愈集群的策略。
<!--
Verify that you now have nodes in 3 zones:
-->
验证你现在有来自三个区的节点:
## Manual zone assignment for Pods
```shell
kubectl get nodes --show-labels
```
You can apply [node selector constraints](/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector)
to Pods that you create, as well as to Pod templates in workload resources
such as Deployment, StatefulSet, or Job.
-->
## 为 Pods 手动指定区
<!--
Create the guestbook-go example, which includes an RC of size 3, running a simple web app:
You can apply [node selector constraints](/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector)
to Pods that you create, as well as to Pod templates in workload resources
such as Deployment, StatefulSet, or Job.
-->
创建 `guestbook-go` 示例,其中包含副本个数为 3 的 RC,运行一个简单的 Web 应用:
```shell
find kubernetes/examples/guestbook-go/ -name '*.json' | xargs -I {} kubectl apply -f {}
```
你可以应用[节点选择算符约束](/zh/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector)
到你所创建的 Pods 上,或者为 Deployment、StatefulSet 或 Job 这类工作负载资源
中的 Pod 模板设置此类约束。
<!--
The pods should be spread across all 3 zones:
## Storage access for zones
When persistent volumes are created, the `PersistentVolumeLabel`
[admission controller](/docs/reference/access-authn-authz/admission-controllers/)
automatically adds zone labels to any PersistentVolumes that are linked to a specific
zone. The {{< glossary_tooltip text="scheduler" term_id="kube-scheduler" >}} then ensures,
through its `NoVolumeZoneConflict` predicate, that pods which claim a given PersistentVolume
are only placed into the same zone as that volume.
-->
Pod 应该跨三个区分布:
## 跨区的存储访问
```shell
kubectl describe pod -l app=guestbook | grep Node
```
```
Node: kubernetes-minion-9vlv/10.240.0.5
Node: kubernetes-minion-281d/10.240.0.8
Node: kubernetes-minion-olsh/10.240.0.11
```
```shell
kubectl get node kubernetes-minion-9vlv kubernetes-minion-281d kubernetes-minion-olsh --show-labels
```
```
NAME STATUS ROLES AGE VERSION LABELS
kubernetes-minion-9vlv Ready <none> 34m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-281d Ready <none> 20m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-olsh Ready <none> 3m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-f,kubernetes.io/hostname=kubernetes-minion-olsh
```
当创建持久卷时,`PersistentVolumeLabel`
[准入控制器](/zh/docs/reference/access-authn-authz/admission-controllers/)
会自动向那些链接到特定区的 PersistentVolume 添加区标签。
{{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}}通过其
`NoVolumeZoneConflict` 断言确保申领给定 PersistentVolume 的 Pods 只会
被调度到该卷所在的可用区。
<!--
Load-balancers span all zones in a cluster; the guestbook-go example
includes an example load-balanced service:
You can specify a {{< glossary_tooltip text="StorageClass" term_id="storage-class" >}}
for PersistentVolumeClaims that specifies the failure domains (zones) that the
storage in that class may use.
To learn about configuring a StorageClass that is aware of failure domains or zones,
see [Allowed topologies](/docs/concepts/storage/storage-classes/#allowed-topologies).
-->
负载均衡器也会跨集群中的所有区;`guestbook-go` 示例中包含了一个负载均衡
服务的例子:
```shell
kubectl describe service guestbook | grep LoadBalancer.Ingress
```
你可以为 PersistentVolumeClaim 指定{{< glossary_tooltip text="StorageClass" term_id="storage-class" >}}
以设置该类中的存储可以使用的失效域(区)。
要了解如何配置能够感知失效域或区的 StorageClass,请参阅
[可用的拓扑逻辑](/zh/docs/concepts/storage/storage-classes/#allowed-topologies)。
<!--
The output is similar to this:
-->
输出类似于:
## Networking
```
LoadBalancer Ingress: 130.211.126.21
```
By itself, Kubernetes does not include zone-aware networking. You can use a
[network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
to configure cluster networking, and that network solution might have zone-specific
elements. For example, if your cloud provider supports Services with
`type=LoadBalancer`, the load balancer might only send traffic to Pods running in the
same zone as the load balancer element processing a given connection.
Check your cloud provider's documentation for details.
-->
## 网络 {#networking}
Kubernetes 自身不提供与可用区相关的联网配置。
你可以使用[网络插件](/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
来配置集群的联网,该网络解决方案可能拥有一些与可用区相关的元素。
例如,如果你的云提供商支持 `type=LoadBalancer` 的 Service,则负载均衡器
可能仅会将请求流量发送到运行在负责处理给定连接的负载均衡器组件所在的区。
请查阅云提供商的文档了解详细信息。
<!--
Set the above IP:
For custom or on-premises deployments, similar considerations apply.
{{< glossary_tooltip text="Service" term_id="service" >}} and
{{< glossary_tooltip text="Ingress" term_id="ingress" >}} behavior, including handling
of different failure zones, does vary depending on exactly how your cluster is set up.
-->
设置上面的 IP 地址:
```shell
export IP=130.211.126.21
```
对于自定义的或本地集群部署,也可以考虑这些因素
{{< glossary_tooltip text="Service" term_id="service" >}}
{{< glossary_tooltip text="Ingress" term_id="ingress" >}} 的行为,
包括处理不同失效区的方法,在很大程度上取决于你的集群是如何搭建的。
<!--
Explore with curl via IP:
## Fault recovery
When you set up your cluster, you might also need to consider whether and how
your setup can restore service if all the failure zones in a region go
off-line at the same time. For example, do you rely on there being at least
one node able to run Pods in a zone?
Make sure that any cluster-critical repair work does not rely
on there being at least one healthy node in your cluster. For example: if all nodes
are unhealthy, you might need to run a repair Job with a special
{{< glossary_tooltip text="toleration" term_id="toleration" >}} so that the repair
can complete enough to bring at least one node into service.
Kubernetes doesn't come with an answer for this challenge; however, it's
something to consider.
-->
使用 curl 访问该 IP
## 失效恢复 {#fault-recovery}
在搭建集群时,你可能需要考虑当某区域中的所有失效区都同时掉线时,是否以及如何
恢复服务。例如,你是否要求在某个区中至少有一个节点能够运行 Pod?
请确保任何对集群很关键的修复工作都不要指望集群中至少有一个健康节点。
例如:当所有节点都不健康时,你可能需要运行某个修复性的 Job,
该 Job 要设置特定的{{< glossary_tooltip text="容忍度" term_id="toleration" >}}
以便修复操作能够至少将一个节点恢复为可用状态。
```shell
curl -s http://${IP}:3000/env | grep HOSTNAME
```
Kubernetes 对这类问题没有现成的解决方案;不过这也是要考虑的因素之一。
## {{% heading "whatsnext" %}}
<!--
The output is similar to this:
To learn how the scheduler places Pods in a cluster, honoring the configured constraints,
visit [Scheduling and Eviction](/docs/concepts/scheduling-eviction/).
-->
输出类似于:
```
"HOSTNAME": "guestbook-44sep",
```
<!--
Again, explore multiple times:
-->
如果多次尝试该命令:
```shell
(for i in `seq 20`; do curl -s http://${IP}:3000/env | grep HOSTNAME; done) | sort | uniq
```
<!--
The output is similar to this:
-->
输出类似于:
```shell
"HOSTNAME": "guestbook-44sep",
"HOSTNAME": "guestbook-hum5n",
"HOSTNAME": "guestbook-ppm40",
```
<!--
The load balancer correctly targets all the pods, even though they are in multiple zones.
-->
负载均衡器正确地选择不同的 Pod,即使它们跨了多个区。
<!--
### Shutting down the cluster
When you're done, clean up:
-->
### 停止集群
当完成以上工作之后,清理任务现场:
GCE:
```shell
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-f kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a kubernetes/cluster/kube-down.sh
```
AWS:
```shell
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2c kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a kubernetes/cluster/kube-down.sh
```
要了解调度器如何在集群中放置 Pods 并遵从所配置的约束,可参阅
[调度与驱逐](/zh/docs/concepts/scheduling-eviction/)。