K8s学习笔记 (4)
@ wgjak47 | 星期四,七月 25 日,2019 年 | 5 分钟阅读 | 更新于 星期四,七月 25 日,2019 年

k8s学习笔记

控制器

Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为。

Deployment

Deployment为Pod和Replica Set(下一代Replication Controller)提供声明式更新。

  • 定义Deployment来创建Pod和ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 暂停和继续Deployment

创建

例子: yaml定义

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
# 资源限制
resources:
# 最大资源
limits:
memory: "180Mi"
# 一般情况下的资源请求
requests:
memory: "100Mi"
image: nginx:1.7.9
ports:
- containerPort: 80

创建:

kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
deployment "nginx-deployment" created

注意在指定deployment的selector时不要和K8s中的其他Controller重复,防止无法预期的行为。

更新Deployment

通过更改Deployment的定义来更新deployment对象:

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

deployment更新是先尝试创建一个新的ReplicaSet并扩容,并在将旧的replica缩容到0,默认情况下,会保证至少有期望pod数-1个pod是up状态,至多有期望Pod数+1个pod是down状态。(未来幅度可能会变成25%上下) 。如果在更新过程中又遇到另一个更新或者创建,Deployment的Controller会立即放弃上一个更新,杀死已经启动的容器,开始创建新的容器。

更新label selector要注意的东西

  • 增添 selector 需要同时在 Deployment 的 spec 中更新新的 label,否则将返回校验错误。此更改是不可覆盖的,这意味着新的 selector 不会选择使用旧 selector 创建的 ReplicaSet 和 Pod,从而导致所有旧版本的 ReplicaSet 都被丢弃,并创建新的 ReplicaSet。
  • 更新 selector,即更改 selector key 的当前值,将导致跟增添 selector 同样的后果。
  • 删除 selector,即删除 Deployment selector 中的已有的 key,不需要对 Pod template label 做任何更改,现有的 ReplicaSet 也不会成为孤儿,但是请注意,删除的 label 仍然存在于现有的 Pod 和 ReplicaSet 中。

回滚Deployment

默认情况下,kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录。每当Deployment Pod template的内容被修改,就会创建一个新的revision

检查Deployment的revision

例如:

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment":
REVISION    CHANGE-CAUSE
1           kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml--record
2           kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.91

回退到历史版本

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back

P.S. 通过设置.spec.revisionHistoryLimit来指定deployment最多保留多少revision历史记录

扩容

例子:

# 手动指定
$ kubectl scale deployment nginx-deployment --replicas 10
deployment "nginx-deployment" scaled
# 根据CPU使用情况自动扩容
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment "nginx-deployment" autoscaled

比例扩容

RollingUpdate Deployment 支持同时运行一个应用的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout(进行中或者已经暂停的),为了降低风险,Deployment controller 将会平衡已存在的活动中的 ReplicaSet(有 Pod 的 ReplicaSet)和新加入的 replica。这被称为比例扩容。最终所有的replica都会移动到新的replicaSet里面。

暂停和恢复Deployment

在发出一次或多次更新前暂停一个 Deployment,然后再恢复它。这样就能在暂停 Deployment,期间进行一些修复工作,而不会发出不必要的 rollout。

例子:

# 暂停更新
$ kubectl rollout pause deployment/nginx-deployment
deployment "nginx-deployment" paused

# 修改声明
$ kubectl set image deploy/nginx nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

# 恢复
$ kubectl rollout resume deploy nginx
deployment "nginx" resumed

注意: 在恢复 Deployment 之前无法回退一个已经暂停的 Deployment。

Deployment状态

进行中(progressing)

  • Deployment 正在创建新的ReplicaSet过程中。
  • Deployment 正在扩容一个已有的 ReplicaSet。
  • Deployment 正在缩容一个已有的 ReplicaSet。
  • 有新的可用的 pod 出现。

完成(complete)

  • Deployment 最小可用。最小可用意味着 Deployment 的可用 replica 个数等于或者超过 Deployment 策略中的期望个数。
    
  • 所有与该 Deployment 相关的replica都被更新到了您指定版本,也就说更新完成。
  • 该 Deployment 中没有旧的 Pod 存在。

失败(fail to progressing)

  • 无效的引用
  • 不可读的 probe failure
  • 镜像拉取错误
  • 权限不够
  • 范围限制
  • 程序运行时配置错误

可以设置spec.progressDeadlineSeconds来让deployment的controller判断本次人物是否失败。 例如:

$ kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
"nginx-deployment" patched

当超过截止时间后,Deployment controller 会在 Deployment 的 status.conditions中增加一条DeploymentCondition,它包括如下属性:

Type=Progressing
Status=False
Reason=ProgressDeadlineExceeded

PS1: Deployment的controller只是报告Reason信息,其余的行动由更高层的协调器决定。 PS2: 如果您暂停了一个 Deployment,在暂停的这段时间内kubernetnes不会检查您指定的 deadline。

编写 Deployment Spec

例子:

# k8s object共有
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
# 声明Pod数量,默认都是1
replicas: 3
# 可选字段,指定Deployment管理的pod范围
# 默认是.spec.template.metadata.labels
# 必须匹配.spec.template.metadata.labels
selector:
matchLabels:
app: nginx
# stragey可以是Recreate/RollingUpdate(default), 前者是直接重新创建
# Recreate: https://github.com/ContainerSolutions/k8s-deployment-strategies/tree/master/recreate
# RollingUpdate:https://github.com/ContainerSolutions/k8s-deployment-strategies/tree/master/ramped
stragey:
type: RollingUpdate
rollingUpdate:
# 指定在升级过程中不可用Pod的最大数量。数字或者百分比(5%)
maxUnavailable:1
# 指定在升级过程中超过Pod的最大数量。数字或者百分比(5%)
maxSurge: 1
# 指定没有任何容器crash的Pod并被认为是可用状态的最小秒数。默认是0
minReadySeconds: 100
# 用来配置Deployment回退的配置。设置该参数将触发回退操作,每次回退完成后,该值就会被清除。
rollbackTo:
# 用来指定回退到的revision。默认是0,即上一个revision
revision: 0
# 用来指定可以保留的旧的ReplicaSet数量
revisionHistoryLimit: 34
# 用来指定暂停和恢复Deployment
pasued: false
# template为spec必须字段
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

ReplicaSet

虽然ReplicaSet可以独立使用,但一般还是建议使用 Deployment 来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment支持)。