statefulset
This commit is contained in:
@ -220,7 +220,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
title: '服务发现、负载均衡、网络',
|
||||
collapsable: true,
|
||||
collapsable: false,
|
||||
children: [
|
||||
// 'k8s-intermediate/service/service',
|
||||
// 'k8s-intermediate/service/dns',
|
||||
@ -231,7 +231,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
title: '存储',
|
||||
collapsable: true,
|
||||
collapsable: false,
|
||||
children: [
|
||||
'k8s-intermediate/persistent/volume',
|
||||
'k8s-intermediate/persistent/pv',
|
||||
@ -241,7 +241,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
title: '配置',
|
||||
collapsable: true,
|
||||
collapsable: false,
|
||||
children: [
|
||||
'k8s-intermediate/config/config-map',
|
||||
'k8s-intermediate/config/computing-resource',
|
||||
|
||||
@ -13,7 +13,8 @@ p img {
|
||||
}
|
||||
|
||||
p code {
|
||||
border: 1px solid #007af5;
|
||||
/*border: 1px solid #007af5;*/
|
||||
color: #007af5 !important;
|
||||
}
|
||||
|
||||
.noselect {
|
||||
|
||||
@ -7,7 +7,117 @@ description: 本文描述了 Kubernetes StatefulSet 的基本信息:Components
|
||||
|
||||
[返回 StatefulSet](./)
|
||||
|
||||
正在撰写...
|
||||
## 创建 StatefulSet
|
||||
|
||||
下面是一个 StatefulSet 的例子,由如下内容组成:
|
||||
* 一个名为 nginx 的 [Headless Service](https://kubernetes.io/docs/concepts/services-networking/service/#headless-service),用于控制网络域
|
||||
* 一个名为 web 的StatefulSet,副本数为 3
|
||||
* volumeClaimTemplates 提供稳定的存储(每一个 Pod ID 对应自己的存储卷,且 Pod 重建后,仍然能找到对应的存储卷)
|
||||
|
||||
``` yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
name: web
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: nginx
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: web
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx # has to match .spec.template.metadata.labels
|
||||
serviceName: "nginx"
|
||||
replicas: 3 # by default is 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx # has to match .spec.selector.matchLabels
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: nginx
|
||||
image: k8s.gcr.io/nginx-slim:0.8
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: web
|
||||
volumeMounts:
|
||||
- name: www
|
||||
mountPath: /usr/share/nginx/html
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: www
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "my-storage-class"
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
```
|
||||
|
||||
## Pod 的标识
|
||||
|
||||
StatefulSet 中的 Pod 具备一个唯一标识,该标识由以下几部分组成:
|
||||
* 序号
|
||||
* 稳定的网络标识
|
||||
* 稳定的存储
|
||||
|
||||
该标识始终与 Pod 绑定,无论该 Pod 被调度(重新调度)到哪一个节点上。
|
||||
|
||||
### 序号
|
||||
|
||||
假设一个 StatefulSet 的副本数为 N,其中的每一个 Pod 都会被分配一个序号,序号的取值范围从 0 到 N - 1,并且该序号在 StatefulSet 内部是唯一的。
|
||||
|
||||
### 稳定的网络 ID
|
||||
|
||||
* StatefulSet 中 Pod 的 hostname 格式为 $(StatefulSet name)-$(Pod 序号)。上面的例子将要创建三个 Pod,其名称分别为: web-0,web-1,web-2。
|
||||
* StatefulSet 可以使用 Headless Service 来控制其 Pod 所在的域。该域(domain)的格式为 $(service name).$(namespace).svc.cluster.local,其中 “cluster.local” 是集群的域。
|
||||
* StatefulSet 中每一个 Pod 将被分配一个 dnsName,格式为: $(podName).$(所在域名)
|
||||
|
||||
::: tip
|
||||
您需要自行为 StatefulSet 创建 Headless Service。
|
||||
:::
|
||||
|
||||
下表列出了不同的 集群域、Service name、StatefulSet name 的情况下,对应的 StatefulSet 中 Pod 的 DNS 名字:
|
||||
|
||||
|
||||
|
||||
| 字段名 | 组合一 | 组合二 | 组合三 |
|
||||
| --------------------- | -------------------------------------------- | ---------------------------------------- | ------------------------------------- |
|
||||
| **集群域 Cluster Domain** | cluster.local | cluster.local | cluster.local |
|
||||
| **Service name** | default/nginx | foo/nginx | foo/nginx |
|
||||
| **StatefulSet name** | default/web | foo/web | foo/web |
|
||||
| **StatefulSet Domain** | nginx.default.svc.cluster.local | nginx.foo.svc.cluster.local | nginx.foo.svc.kube.local |
|
||||
| **Pod DNS** | web-{0..N-1}.nginx.default.svc.cluster.local | web-{0..N-1}.nginx.foo.svc.cluster.local | web-{0..N-1}.nginx.foo.svc.kube.local |
|
||||
| **Pod name** | web-{0..N-1} | web-{0..N-1} | web-{0..N-1} |
|
||||
|
||||
### 稳定的存储
|
||||
|
||||
Kubernetes 为每一个 VolumeClaimTemplate 创建一份 PersistentVolume(存储卷)。在上面的例子中,每一个 Pod 都将由 StorageClass(存储类)`my-storage-class` 为其创建一个 1Gib 大小的 PersistentVolume(存储卷)。当 Pod 被调度(或重新调度)到一个节点上,其挂载点将挂载该存储卷声明(关联到该 PersistentVolume)。
|
||||
|
||||
::: tip
|
||||
* 当 Pod 或 StatefulSet 被删除时,其关联的 PersistentVolumeClaim(存储卷声明)以及其背后的 PersistentVolume(存储卷)仍然存在。
|
||||
* 如果相同的 Pod 或 StatefulSet 被再次创建,则,新建的名为 web-0 的 Pod 仍将挂载到原来名为 web-0 的 Pod 所挂载的存储卷声明及存储卷。
|
||||
* 这确保了 web-0、web-1、web-2 等,不管被删除重建多少次,都将 “稳定” 的使用各自所对应的存储内容
|
||||
:::
|
||||
|
||||
### Pod name 标签
|
||||
|
||||
当 StatefulSet 控制器创建一个 Pod 时,会为 Pod 添加一个标签(label) `statefulset.kubernetes.io/pod-name` 且该标签的值为 Pod 的名字。您可以利用此名字,StatefulSet 中的某一个特定的 Pod 关联一个 Service。
|
||||
|
||||
::: tip
|
||||
实际操作中,您无需为 StatefulSet 中的一个特定 Pod 关联 Service,因为您可以直接通过该 Pod 的 DNS Name 访问到 Pod。
|
||||
:::
|
||||
|
||||
|
||||
[返回 StatefulSet](./)
|
||||
|
||||
@ -5,4 +5,30 @@ description: 本文描述了 Kubernetes StatefulSet 的概念、行为及用法
|
||||
|
||||
# StatefulSet 的使用场景
|
||||
|
||||
正在撰写...
|
||||
## StatefulSet 概述
|
||||
|
||||
StatefulSet 顾名思义,用于管理 Stateful(有状态)的应用程序。
|
||||
|
||||
StatefulSet 管理 Pod 时,确保其 Pod 有一个按顺序增长的 ID。
|
||||
|
||||
与 [Deployment](../wl-deployment/) 相似,StatefulSet 基于一个 Pod 模板管理其 Pod。与 Deployment 最大的不同在于 StatefulSet 始终将一系列不变的名字分配给其 Pod。这些 Pod 从同一个模板创建,但是并不能相互替换:每个 Pod 都对应一个特有的持久化存储标识。
|
||||
|
||||
同其他所有控制器一样,StatefulSet 也使用相同的模式运作:用户在 StatefulSet 中定义自己期望的结果,StatefulSet 控制器执行需要的操作,以使得该结果被达成。
|
||||
|
||||
## StatefulSet 使用场景
|
||||
|
||||
对于有如下要求的应用程序,StatefulSet 非常适用:
|
||||
|
||||
* 稳定、唯一的网络标识(dnsname)
|
||||
* 稳定、不变的持久化路径(或存储卷)
|
||||
* 按顺序地增加副本、减少副本,并在减少副本时执行清理
|
||||
* 按顺序自动地执行滚动更新
|
||||
|
||||
如果一个应用程序不需要稳定的网络标识,或者不需要按顺序部署、删除、增加副本,您应该考虑使用 Deployment 这类无状态(stateless)的控制器。
|
||||
|
||||
## StatefulSet 的限制
|
||||
|
||||
* Pod 的存储要么由 storage class 对应的 [PersistentVolume Provisioner](https://github.com/kubernetes/examples/blob/master/staging/persistent-volume-provisioning/README.md) 提供,要么由集群管理员事先创建
|
||||
* 删除或 scale down 一个 StatefulSet 将不会删除其对应的数据卷。这样做的考虑是数据安全
|
||||
* 删除 StatefulSet 时,将无法保证 Pod 的终止是正常的。如果要按顺序 gracefully 终止 StatefulSet 中的 Pod,可以在删除 StatefulSet 前将其 scale down 到 0
|
||||
* 当使用默认的 [Pod Management Policy](./update.html) (OrderedReady) 进行滚动更新时,可能进入一个错误状态,并需要[人工介入](./update.html)才能修复
|
||||
|
||||
@ -7,7 +7,37 @@ description: 本文描述了 Kubernetes StatefulSet 的部署和伸缩
|
||||
|
||||
[返回 StatefulSet](./)
|
||||
|
||||
正在撰写...
|
||||
## 部署和伸缩 StatefulSet 时的执行顺序
|
||||
|
||||
* 在创建一个副本数为 N 的 StatefulSet 时,其 Pod 将被按 {0 ... N-1} 的顺序逐个创建
|
||||
* 在删除一个副本数为 N 的 StatefulSet (或其中所有的 Pod)时,其 Pod 将按照相反的顺序(即 {N-1 ... 0})终止和删除
|
||||
* 在对 StatefulSet 执行扩容(scale up)操作时,新增 Pod 所有的前序 Pod 必须处于 Running(运行)和 Ready(就绪)的状态
|
||||
* 终止和删除 StatefulSet 中的某一个 Pod 时,该 Pod 所有的后序 Pod 必须全部已终止
|
||||
|
||||
StatefulSet 中 `pod.spec.terminationGracePeriodSeconds` 不能为 0。具体原因请参考 [force deleting StatefulSet Pods](https://kubernetes.io/docs/tasks/run-application/force-delete-stateful-set-pod/)
|
||||
|
||||
[创建 StatefulSet](./basics.html) 例子中的 nginx StatefulSet 被创建时:
|
||||
* Pod web-0、web-1、web-2 将被按顺序部署
|
||||
* web-0 处于 Running 和 Ready 状态之前,web-1 不会创建;web-1 处于 Running 和 Ready 状态之前,web-2 不会创建
|
||||
* 如果 web-1 已处于 Running 和 Ready 的状态,web-2 尚未创建,此时 web-0 发生了故障,则在 web-0 成功重启并达到 Running 和 Ready 的状态之前,web-2 不会创建
|
||||
* 如果用户对这个 StatefulSet 执行缩容(scale down)操作,将其副本数调整为 1,则:
|
||||
* web-2 将被首先终止;在 web-2 已终止并删除之后,才开始终止 web-1
|
||||
* 假设在 web-2 终止并删除之后,web-1 终止之前,此时 web-0 出现故障,则,在 web-0 重新回到 Running 和 Ready 的状态之前,kubernetes 将不会终止 web-1
|
||||
|
||||
## Pod 管理策略
|
||||
|
||||
在 Kubernetes 1.7 及其后续版本中,可以为 StatefulSet 设定 `.spec.podManagementPolicy` 字段<Badge text="Kuboard 暂不支持" type="warn"/>,以便您可以继续使用 StatefulSet 唯一 ID 的特性,但禁用其有序创建和销毁 Pod 的特性。该字段的取值如下:
|
||||
|
||||
* **OrderedReady**
|
||||
|
||||
OrderedReady 是 `.spec.podManagementPlicy` 的默认值。其对 Pod 的管理方式已经在 [部署和伸缩 StatefulSet 时的执行顺序](./scaling.html#部署和伸缩-statefulset-时的执行顺序) 详细描述
|
||||
|
||||
* **Parallel**
|
||||
|
||||
`.spec.podManagementPlicy` 的取值为 Parallel,则 StatefulSet Controller 将同时并行地创建或终止其所有的 Pod。此时 StatefulSet Controller 将不会逐个创建 Pod,等待 Pod 进入 Running 和 Ready 状态之后再创建下一个 Pod,也不会逐个终止 Pod。
|
||||
|
||||
::: tip
|
||||
此选项只影响到伸缩(scale up/scale down)操作。更新操作不受影响。
|
||||
:::
|
||||
|
||||
[返回 StatefulSet](./)
|
||||
|
||||
@ -7,7 +7,44 @@ description: 本文描述了 Kubernetes StatefulSet 的更新
|
||||
|
||||
[返回 StatefulSet](./)
|
||||
|
||||
正在撰写...
|
||||
## StatefulSet 的更新策略 <Badge text="Kuboard 暂不支持" type="warn"/>
|
||||
|
||||
在 Kubernetes 1.7 及之后的版本中,可以为 StatefulSet 设定 `.spec.updateStrategy` 字段,以便您可以在改变 StatefulSet 中 Pod 的某些字段时(container/labels/resource request/resource limit/annotation等)禁用滚动更新。
|
||||
|
||||
### On Delete
|
||||
|
||||
OnDelete 策略实现了 StatefulSet 的遗留版本(kuberentes 1.6及以前的版本)的行为。如果 StatefulSet 的 `.spec.updateStrategy.type` 字段被设置为 OnDelete,当您修改 `.spec.template` 的内容时,StatefulSet Controller 将不会自动更新其 Pod。您必须手工删除 Pod,此时 StatefulSet Controller 在重新创建 Pod 时,使用修改过的 `.spec.template` 的内容创建新 Pod。
|
||||
|
||||
### Rolling Updates
|
||||
|
||||
`.spec.updateStrategy.type` 字段的默认值是 RollingUpdate,该策略为 StatefulSet 实现了 Pod 的自动滚动更新。在用户更新 StatefulSet 的 `.spec.tempalte` 字段时,StatefulSet Controller 将自动地删除并重建 StatefulSet 中的每一个 Pod。处理顺序如下:
|
||||
* 从序号最大的 Pod 开始,逐个删除和更新每一个 Pod,直到序号最小的 Pod 被更新
|
||||
* 当正在更新的 Pod 达到了 Running 和 Ready 的状态之后,才继续更新其前序 Pod
|
||||
|
||||
|
||||
* **Partitions**
|
||||
|
||||
通过指定 `.spec.updateStrategy.rollingUpdate.partition` 字段,可以分片(partitioned)执行RollingUpdate 更新策略。当更新 StatefulSet 的 `.spec.template` 时:
|
||||
* 序号大于或等于 `.spec.updateStrategy.rollingUpdate.partition` 的 Pod 将被删除重建
|
||||
* 序号小于 `.spec.updateStrategy.rollingUpdate.partition` 的 Pod 将不会更新,及时手工删除该 Pod,kubernetes 也会使用前一个版本的 `.spec.template` 重建该 Pod
|
||||
* 如果 `.spec.updateStrategy.rollingUpdate.partition` 大于 `.spec.replicas`,更新 `.spec.tempalte` 将不会影响到任何 Pod
|
||||
|
||||
::: tip
|
||||
大部分情况下,您不需要使用 `.spec.updateStrategy.rollingUpdate.partition`,除非您碰到如下场景:
|
||||
* 执行预发布
|
||||
* 执行金丝雀更新
|
||||
* 执行按阶段的更新
|
||||
:::
|
||||
|
||||
* **Forced Rollback** <Badge text="Kuboard 已支持" type="success"/>
|
||||
|
||||
当使用默认的 Pod 管理策略时(OrderedReady),很有可能会进入到一种卡住的状态,需要人工干预才能修复。
|
||||
|
||||
如果您更新 Pod template 后,该 Pod 始终不能进入 Running 和 Ready 的状态(例如,镜像错误或应用程序配置错误),StatefulSet 将停止滚动更新并一直等待。
|
||||
|
||||
此时,如果您仅仅将 Pod template 回退到一个正确的配置仍然是不够的。由于一个已知的问题,StatefulSet 将继续等待出错的 Pod 进入就绪状态(该状态将永远无法出现),才尝试将该 Pod 回退到正确的配置。
|
||||
|
||||
在修复 Pod template 以后,您还必须删除掉所有已经尝试使用有问题的 Pod template 的 Pod。StatefulSet此时才会开始使用修复了的 Pod template 重建 Pod。
|
||||
|
||||
|
||||
[返回 StatefulSet](./)
|
||||
|
||||
Reference in New Issue
Block a user