1 为什么有这样的设计
- 假设你需要固定数量的pod 运行,如果某个 Pod 失效或被删除,你想要自动创建新的 Pod 来替代,从而保持应用程序的高可用性
- 假如你想要滚动更新, 想平滑地更新应用程序的副本. 需要它可以控制旧 Pod 和新 Pod 的并行运行数量,以及更新的速率,从而避免应用程序的中断或过载
- …
2 ReplicationController
Warning
已经不推荐用, 推荐使用 ReplicaSet
3 ReplicaSet(RS)
Tip
- RS确保任何时间都有指定数量的 Pod 副本在运行
- 一般不会单独去用的
3.1 创建
kubectl explain rs # ReplicaSet可以简写为rs
# 我们发现 rs 内部有个模板属性,看下里面的,其实就是pod的属性
# pod 模板对象
kubectl explain rs.spec.template
kubectl api-resources |grep ReplicaSetrs-nginx.yaml
- 1
- 创建几个pod资源,2个都是按照下面设置的模板template来创建的,如果没有设置,默认就是1
- 2
- 使用什么样的标签 来选择 pod呢,符合这样的标签的pod 都会被rs所管理
- 3
- 定义pod的模板
- 4
- 这里定义的标签一定要和 上面selector定义的matchlabels一样
- 5
- Always 唯一允许的取值,也是默认值
3.2 脱离模板的pod
Tip
如果我们创建了符合rs 标签选择器的pod ,会如何呢?
- 先创建rs ,后创建脱离模板的pod
pod-nginx-single-match-rs.yaml
Note
由于这些 Pod 没有控制器作为其属主引用(ownerReferences 属性),并且 其标签与 ReplicaSet 的选择算符匹配,它们会立即被该 ReplicaSet 获取, 但是该pod 会立即被 ReplicaSet 终止,因为 它们的存在会使得 ReplicaSet 中 Pod 个数超出其期望值
- 先创建符合rs的pod, 再创建rs
会被rs 管理, rs根据你符合条件的pod数量,再看是否需要创建rs中模板的pod.
3.3 删除
4 Deployment (deploy)
Tip
- 一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力
- 你负责描述 Deployment 中的 目标状态,而 Deployment 控制器(Controller)以受控速率更改实际状态, 使其变为期望状态
- 无状态资源管理,最常用的控制器, 继承了rs,通过控制 replicaSet来控制管理pod
- 什么叫无状态? 无状态指的是对于请求方的每个请求,接收方都当这次请求是第一次请求
4.1 创建
k get deploy
# 这样可以导出 配置文件, 做些修改
k create deploy deploy-nginx \
--image=nginx:1.14.2 \
--dry-run=client -o yaml > deploy-nginx.yaml deploy-nginx.yaml
4.2 更新
如何更新
- 假设我们deploy 管理着3个pod ,3个nginx pod 让用户访问, 负载均衡
- 现在我们要更新里面nginx 的版本
- 问题
- 因为只有好像只能有3个, 不能超过, 所以更新的时候先删除一个pod?
- 但是如果这个时候因为删除一个pod导致用户访问满载… 就有问题了
- 解决
- deploy 支持临时添加pod, 支持在滚动更新前,设置最多多几个(比如原来是3个,现在可以是4个),和最多少几个(比如原先3个,现在至少需要2个pod运行)
看一下创建的deploy的更新策略
| 属性 | 值/子属性 | 描述 |
|---|---|---|
| type | Recreate |
|
| RollingUpdate |
|
|
| RollingUpdate | maxSurge |
|
| maxUnavailable |
|
# 直接修改 deploy 中pod使用的image
# --record 记录 会在 kubectl rollout history deployment demo-nginx 命令中显示,
# 会在 CHANGE-CAUSE 里显示 你的命令,否则显示none
# --record will be removed in the future ,未来会被移除
# pod-deploy-nginx 是模板中pod的名字 , nginx:1.9.1 是新的镜像名
kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.9.1 --record=truek get rs -w
# 为了 方便看,我将新的rs 名字下面显示为 deploy-nginx-new
NAME DESIRED CURRENT READY AGE
deploy-nginx-77d87b4b6c 3 3 3 7m38s
deploy-nginx--------new 1 0 0 0s
deploy-nginx--------new 1 1 0 0s
deploy-nginx--------new 1 1 1 85s
deploy-nginx-77d87b4b6c 2 3 3 9m52s
deploy-nginx--------new 2 1 1 85s
deploy-nginx-77d87b4b6c 2 2 2 9m52s
deploy-nginx--------new 2 2 1 85s
deploy-nginx--------new 2 2 2 2m47s
deploy-nginx-77d87b4b6c 1 2 2 11m
deploy-nginx--------new 3 2 2 2m47s
deploy-nginx-77d87b4b6c 1 1 1 11m
deploy-nginx--------new 3 3 2 2m47s
deploy-nginx--------new 3 3 3 2m48s
deploy-nginx-77d87b4b6c 0 1 1 11m
deploy-nginx-77d87b4b6c 0 0 0 11m- 创建了一个新的rs, 新rs创建一个pod, 旧的rs 缩容,减少一个pod
- 继续以上操作, 最终新的rs 创建了3个, 旧的缩容为0
k get deploy -w
NAME READY UP-TO-DATE AVAILABLE AGE
deploy-nginx 3/3 3 3 20m
deploy-nginx 3/3 0 3 20m
deploy-nginx 3/3 1 3 20m
deploy-nginx 4/3 1 4 20m
deploy-nginx 3/3 1 3 20m
deploy-nginx 3/3 2 3 20m
deploy-nginx 4/3 2 4 20m
deploy-nginx 3/3 2 3 20m
deploy-nginx 3/3 3 3 20m
deploy-nginx 4/3 3 4 20m
deploy-nginx 3/3 3 3 20m
# 也可以看到相关的信息, 通过控制rs的replicas的数量
# 新rs先创建一个pod,是因为 一开始replicas=1
k describe deploy deploy-nginx
# 上线的状态如何,是否更新成功
k rollout status deploy deploy-nginx| 状态 | 描述 |
|---|---|
| DESIRED | 用户期望的 Pod 副本个数 (spec.replicas 的值) |
| CURRENT | 当前处于 Running 状态的 Pod 的个数, pull image时期就属于running状态 |
| READY | pod已经启动可以提供服务的状态 |
| UP-TO-DATE |
|
| AVAILABLE |
|
4.3 回滚
Tip
前面更新那里我们会看到,更新成功后, 旧的rs 不会被删除. 有什么用呢?
# 我们再看看
k describe deployments.apps deploy-nginx | grep annotation -iA 3
Annotations: deployment.kubernetes.io/revision: 9
kubernetes.io/change-cause: kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.9.1 --record=true
# 查看deploy-nginx 的上线历史, 显示的相关信息对应上面的版本号和 change-cause
k rollout history deployment deploy-nginx
1 kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.9.1 --record=true
2 kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.14.1 --record=true
# 表示默认保留10个历史记录 可以用于回滚, 可以在创建deploy时指定
# 0 的话,表示不保留
k get deployments.apps deploy-nginx -o yaml | grep revisionHistoryLimit
revisionHistoryLimit: 10
#我们再做一次更新, 没有record,
kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:latest
k rollout history deployment deploy-nginx
REVISION CHANGE-CAUSE
1 kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.9.1 --record=true
2 kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.14.2 --record=true
3 kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:1.14.2 --record=true # 这里还是用的旧的.
# 前面说到 --record 会废弃, 那么实际上就是给deploy 添加一个annotation
# 我们可以手动添加你这个更新的原因. 仅作为注释.
k annotate deploy deploy-nginx kubernetes.io/change-cause='kubectl set image deploy deploy-nginx pod-deploy-nginx=nginx:latest'
# 会先是3个rs. 都保留着 用来回滚用的.
# rs 的配置里面image用的之前的nginx 版本.
k get rs
# 查看某个版本的详情
k rollout history deployment deploy-nginx --revision=1
# 回滚到上一个版本
k rollout undo deploy deploy-nginx
k get rs # 对应的rs就会创建pod了.
# 回滚到指定版本
k rollout undo deploy deploy-nginx --to-revision=2
4.4 扩容
4.5 暂停和恢复
Tip
- 如果你是用命令修改, 需要多次操作,比如一次修改了image,一次修改了cpu什么的. 你不希望修改后就马上重建pod,则可以先暂停, 当然你直接edit 一次全部修改就得了
- 这个就是你自动化操作的时候可能就有用了. 我们一般会在cicd里使用诸如 kubectl set …
5 statefulset(sts)
Tip
- 前面我们说到的pod控制器都是无状态的,关注的是群体(群体里的个体都是一样的,所以把整个群体当成一个个体)
- statefulset 关注个体
- StatefulSet(有状态集)常用于部署有状态的且需要有序启动的应用程序
StatefulSet 的核心功能,就是通过某种方式记录这些状态,然后在 Pod 被重新创 建时,能够为新 Pod 恢复这些状态.