1. 控制器介绍
ReplicaSet 是下一代的 Replication Controller。 ReplicaSet 和 Replication Controller 的唯一区别是选择器的支持。 ReplicaSet 支持新的基于集合的选择器(selector)需求
2. ReplicaSet
ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。 然而 Deployment 是一个更高级的概念,它管理 ReplicaSet, 并向 Pod 提供声明式的更新以及许多其他有用的功能。 因此,更建议使用 Deploymen。
示例:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# 3个副本数
replicas: 3
selector:
matchLabels:
tier: frontend
matchExpressions:
- { key: tier,operator: In, values:[frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
将资源清单保存到frontend.yaml
中,执行 kubectl create -f frontend.yaml
就可以看到对应的 pod已经创建
$ kubectl get rs --show-labels=true -l app=guestbook
NAME DESIRED CURRENT READY AGE LABELS
frontend 3 3 3 25m app=guestbook,tier=frontend
$ kubectl get pod --show-labels=true -l app=guestbook
NAME READY STATUS RESTARTS AGE LABELS
frontend-82tvl 1/1 Running 0 25m app=guestbook,tier=frontend
frontend-q878l 1/1 Running 0 25m app=guestbook,tier=frontend
frontend-wh7n4 1/1 Running 0 25m app=guestbook,tier=frontend
2.1. 编写 ReplicaSet Spec
与所有其他Kubernetes API 对象一样, ReplicaSet 也需要 apiVersion
kind
metadata
spec
字段
-
Pod 模板
.spec.template
是.spec
唯一需求的字段。.spec.template
是 Pod 模板,和 Pod 的语法完全一样,只需要将 Pod 的metadata
和spec
语法嵌套进去就可以了.重启策略:
spec.template.spec.restartPolicy
唯一允许Always
-
Pod 选择器
.spec.seletor
字段是标签选择器。ReplicaSet 管理所有与标签选择器匹配的Pod。 它不区分是否为自己创建的Pod。 这允许在不影响运行中的 Pod 的情况下替换副本集..spec.template.metadata.labels
必须匹配.spec.selector
, 否则它将被 API 拒绝。通常不应该创建标签与此选择器匹配的任何Pod,或者直接与另一个 ReplicaSet 或 另一个控制器(如 Deployment) 标签匹配的任何Pod , 如果这样做, ReplicaSet 会认为它创造了其他 Pod 。 kubernetes 并不会阻止你这样做。
示例:
$ cat pod.yaml apiVersion: v1 kind: Pod metadata: name: frontend-test labels: app: guestbook tier: frontend spec: containers: - name: frontend-test image: harbor.tansuotv.cn/library/nginx:v1 $ kubectl create -f pod.yaml pod/frontend-test created $ kubectl get pod --show-labels=true -l app=guestbook NAME READY STATUS RESTARTS AGE LABELS frontend-82tvl 1/1 Running 0 79m app=guestbook,tier=frontend frontend-q878l 1/1 Running 0 79m app=guestbook,tier=frontend frontend-test 0/1 Terminating 0 5s app=guestbook,tier=frontend frontend-wh7n4 1/1 Running 0 79m app=guestbook,tier=frontend
-
Replicas
通过设置
.spec.replicas
可以指定要同时运行多少个 Pod。 在任何时间运行 Pod 数量 可能高于或低于.spec.replicas
指定的数量,例如在副本刚刚被增加或减少后,或者 Pod 正在被关闭或者替换。
2.2. 使用 ReplicaSets 的具体方法
-
删除 ReplicaSet 和它的 Pod
要删除 ReplicaSet 和它的所有 Pod, 使用
kubectl delete
命令。 默认情况下,垃圾收集器自动删除所有依赖的 Pod。当使用 REST API 或
client-go
库时, 您必须在删除选项中将propagationPolicy
设置为Background
或Foreground
。 例如:``` kubectl proxy –port=8080 curl -X DELETE ‘localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend’ \
-d ‘{“kind”:”DeleteOptions”,”apiVersion”:”v1”,”propagationPolicy”:”Foreground”}’ \ -H “Content-Type: application/json” Z```
-
只删除ReplicaSet
可以只删除 ReplicaSet 而不影响它的 Pod, 方法是使用
kubectl delete
命令去设置--cascade=false
选项当使用 REST API 或
client-go
库时, 必须将propagationPolicy
设置为Orphan
。例如:kubectl proxy --port=8080 curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \ > -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \ > -H "Content-Type: application/json"
一旦删除了原来的ReplicaSet ,就可以创建一个新的来替换它。 由于新旧ReplicaSet的
.spec.selector
是相同的,新的 ReplicaSet 将接管老的 Pod。 但是,它不会努力使现有的Pod 与新的、不同的Pod 模板匹配。 若想要以可控的方式将Pod 更新到新的 spec,就要使用滚动更新的方式 -
将Pod 从 ReplicaSet 中隔离
可以通过改变标签来从 ReplicaSet 的目标集中移除 Pod。这种技术可以用来从服务中去除 Pod,以便进行排错、数据恢复等。 以这种方式移除的 Pod 将被自动替换(假设副本的数量没有改变)。
$ kubectl edit pod frontend-42x87 pod/frontend-42x87 edited
-
缩放 ReplicaSet
通过更新 .spec.replicas 字段,ReplicaSet 可以被轻松的进行缩放。ReplicaSet 控制器能确保匹配标签选择器的数量的 Pod 是可用的和可操作的。
$ kubectl edit rs frontend replicaset.extensions/frontend edited
-
ReplicaSet 作为水平的Pod 自动缩放器目标
ReplicaSet 也可以作为 水平的Pod缩放器(HPA)的目标,ReplicaSet 可以被 HPA自动缩放
示例:
apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: frontend-scaler spec: scaleTargetRef: kind: ReplicaSet name: frontend minReplicas: 3 maxReplicas: 10 targetCPUUtilizationPercentage: 50
将这个列表保存到 hpa-rs.yaml 并提交到 Kubernetes 集群,就能创建它所定义的 HPA,进而就能根据复制的 Pod 的 CPU 利用率对目标 ReplicaSet进行自动缩放。
kubectl create -f https://k8s.io/examples/controllers/hpa-rs.yaml
或者,可以使用 kubectl autoscale 命令完成相同的操作。 (而且它更简单!)
kubectl autoscale rs frontend
3. Reployment
Deployment 是个高级 API 对象,它以
kubectl rolling-update
的方式更新其底层副本集及其Pod。如果需要滚动更新功能,建议使用Deployment, 因为 Deployment 与
kubectl rolling-update
不同的是: 它是声明式的、服务端的、并且具有其他特性。
3.1. 创建 Deployment
示例:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.4
ports:
- containerPort: 80
该清单主要完成以下工作:
- 创建名为
nginx-deployment
的 Deployment,由.metadata.name
字段指示 - Deployment 创建三个复制的 Pods,由
replicas
字段指示 selector
字段定义 Deployment 如何查找要管理的 Pods。 在这种情况下,只要选择在 Pod 模板(app: nginx
) 中定义的标签, 更复杂的选择规则是可能的, 只要 Pod 模板本身满足规则
注意:
matchLabels
字段是 {key,value} 的映射。单个 {key,value}在matchLabels
映射中的值等效于matchExpressions
的元素,其键字段是“key”,运算符为“In”,值数组仅包含“value”。所有要求,从matchLabels
和matchExpressions
,必须满足才能匹配。
template
字段包含以下子字段- Pod 使用
label
字段 标记为app: nginx
- Pod 模板规范或
.template.spec
字段指示Pods运行一个容器,nginx
运行nginx
- 创建一个容器并使用
name
字段将其命名为nginx
注意:
可以指定
--record
标志来写入在资源注释kubernetes.io/change-cause
中执行的命令。它对以后的检查是有用的。
检查创建结果
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/3 3 2 8m
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-9b644dcd5-dj6nw 0/1 ContainerCreating 0 24s
nginx-deployment-9b644dcd5-lb8hm 1/1 Running 0 24s
nginx-deployment-9b644dcd5-tp674 1/1 Running 0 24s
**查看Deployment 状态 **
$ kubectl rollout status deployment.v1.apps/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
查看Deployment 创建的 ReplicaSet (rs)
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-9b644dcd5 3 3 3 38m
要查看每个 Pod 自动生成的标签
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-9b644dcd5-dj6nw 1/1 Running 0 39m app=nginx,pod-template-hash=9b644dcd5
nginx-deployment-9b644dcd5-lb8hm 1/1 Running 0 39m app=nginx,pod-template-hash=9b644dcd5
nginx-deployment-9b644dcd5-tp674 1/1 Running 0 39m app=nginx,pod-template-hash=9b644dcd5
3.2. 更新 Deployment
$ kubectl --record deployment/nginx-deployment set image nginx=nginx:1.9.1
deployment.extensions/nginx-deployment image updated
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-7448597cd5-q8p52 1/1 Running 0 23s
nginx-deployment-7448597cd5-xm98k 0/1 ContainerCreating 0 27s
nginx-deployment-7448597cd5-z9762 1/1 Running 0 27s
查看展开状态
$ kubectl rollout status deployment.v1.apps/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 2 of 3 updated replicas are available...
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/3 3 2 46m
查看 ReplicaSet 状态
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-7448597cd5 3 3 2 3m38s
nginx-deployment-7b45cc56cf 0 0 0 4m48s
3.3. 回滚
触发 Deployment 展开时,将创建 Deployment 修改版。这意味着仅当 Deployment Pod 模板 (.spec.template
) 发生更改时,才会创建新修改版本,例如,如果更新模板的标签或容器镜像 。其他更新,如扩展 Deployment 、不要创建 Deployment 修改版,以便方便同时手动或自动缩放。这意味着,当回滚到较早的修改版时,只有 Deployment Pod 模板部分回滚。
检查Deployment 展开历史
-
检查 Deployment 修改历史:
$ kubectl rollout history deployment.v1.apps/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 2 kubectl deployment/nginx-deployment set image nginx=nginx:1.91. --record=true 3 <none> 4 kubectl deployment/nginx-deployment set image nginx=nginx:1.9.1 --record=true
-
查看修改历史详细信息
$ kubectl rollout history deployment/nginx-deployment --revision=2 deployment.extensions/nginx-deployment with revision #2 Pod Template: Labels: app=nginx pod-template-hash=7b45cc56cf Annotations: kubernetes.io/change-cause: kubectl deployment/nginx-deployment set image nginx=nginx:1.91. --record=true Containers: nginx: Image: nginx:1.91. Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none>
-
回滚到上一次修改
$ kubectl rollout undo deployment.v1.apps/nginx-deployment deployment.apps/nginx-deployment rolled back $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-7448597cd5-q8p52 1/1 Running 0 71m 10.244.2.47 k8s-n2 <none> <none> nginx-deployment-7448597cd5-z9762 1/1 Running 0 71m 10.244.2.46 k8s-n2 <none> <none> nginx-deployment-7448597cd5-zhqb5 0/1 Terminating 0 53m <none> k8s-n1 <none> <none> nginx-deployment-9b644dcd5-58fxf 0/1 ContainerCreating 0 4s <none> k8s-n2 <none> <none> nginx-deployment-9b644dcd5-wgc6f 0/1 ContainerCreating 0 4s <none> k8s-n1 <none> <none> $ kubectl get deployment nginx-deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 114m
更多回滚命令参考
$ kubectl rollout undo -h
Rollback to a previous rollout.
Examples:
# Rollback to the previous deployment
kubectl rollout undo deployment/abc
# Rollback to daemonset revision 3
kubectl rollout undo daemonset/abc --to-revision=3
# Rollback to the previous deployment with dry-run
kubectl rollout undo --dry-run=true deployment/abc
....
3.4. 缩放
将 pod 副本集从3个 修改为10个
$ kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
deployment.apps/nginx-deployment scaled
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-9b644dcd5-58fxf 1/1 Running 0 3m26s
nginx-deployment-9b644dcd5-6ts8v 1/1 Running 0 18s
nginx-deployment-9b644dcd5-924j2 1/1 Running 0 18s
nginx-deployment-9b644dcd5-jnp2v 1/1 Running 0 18s
nginx-deployment-9b644dcd5-mbclq 1/1 Running 0 18s
nginx-deployment-9b644dcd5-pmkth 1/1 Running 0 18s
nginx-deployment-9b644dcd5-r2nx6 1/1 Running 0 18s
nginx-deployment-9b644dcd5-wgc6f 1/1 Running 0 3m26s
nginx-deployment-9b644dcd5-z6nlq 1/1 Running 0 3m21s
nginx-deployment-9b644dcd5-zhts4 1/1 Running 0 18s
水平缩放
基于现有 Pod 的 CPU 利用率缩放
kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80
3.5. 暂停、恢复
可以在触发一个或多个更新之前暂停 Deployment ,然后继续它。这允许在暂停和恢复之间应用多个修补程序,而不会触发不必要的 Deployment
示例:
# 新建 deployment
$ kubectl apply -f nginx-deployment.yaml
deployment.extensions/nginx-deployment created
# 查看deployment
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 5s
# 查看rs
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-9b644dcd5 3 3 3 9s
# 暂停 deployment
$ kubectl rollout pause deployment/nginx-deployment
deployment.extensions/nginx-deployment paused
# 更新镜像
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment.extensions/nginx-deployment image updated
# 查看rollout history
$ kubectl rollout history deployment/nginx-deployment
deployment.extensions/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
# 查看rs状态
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-9b644dcd5 3 3 3 2m5s
# 修改资源限制
$ kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
deployment.extensions/nginx-deployment resource requirements updated
# 恢复
$ kubectl rollout resume deployment/nginx-deployment
deployment.extensions/nginx-deployment resumed
# 查看rs状态
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-7576c67d77 3 3 2 10s
nginx-deployment-9b644dcd5 0 0 0 3m24s
$ kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 2 of 3 updated replicas are available...
所有deployment 在 pause 状态的更新、滚动操作都不会执行 ,等到 resume 后 会继续执行
3.6. Deployment 状态
使用 kubectl rollout status
监视 Deployment 的进度
$ kubectl rollout status deployment nginx-deployment
deployment "nginx-deployment" successfully rolled out
3.7. Deployment 失败
可能引起 Deployment 失败的因素有:
- 赔额不足
- 就绪探测失败
- 镜像拉取错误
- 权限不足
- 限制范围
- 应用程序运行时配置错误
检测此条件的一种方法是在 Deployment 规范中指定截止时间参数:([.spec.progressDeadlineSeconds
](#progress-deadline-seconds))。
.spec.progressDeadlineSeconds
进度截止时间秒表示 Deployment 控制器在指示(处于 Deployment 状态)之前等待的秒数 Deployment 进度已停止。
以下 kubectl 命令设置具有进度的规范,使控制器报告 10 分钟后 Deployment 进度不足:
$ kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
deployment.apps/nginx-deployment patched
超过截止时间后, Deployment 控制器将添加具有以下属性到 Deployment 的 .status.conditions
:
- Type=Progressing
- Status=False
- Reason=ProgressDeadlineExceeded
注意:
Kubernetes 对已停止的 Deployment 不执行任何操作,只需使用
Reason=ProgressDeadlineExceeded
。 更高级别的编排器可以利用它并相应地采取行动,例如,将 Deployment 回滚到其以前的版本。
注意: 如果暂停 Deployment ,Kubernetes 不会根据指定的截止时间检查进度。可以在展开栏中间安全地暂停 Deployment ,并在不触发超过最后期限时恢复。
Deployments 可能会出现短暂的错误,既不是因为设置的超时时间过短,也不是因为任何真正的暂时性错误。例如配额不足。如果描述 Deployment ,将注意到以下部分:
kubectl describe deployment nginx-deployment
...
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-b7556d645 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 46m deployment-controller Scaled up replica set nginx-deployment-9b644dcd5 to 3
Normal ScalingReplicaSet 42m deployment-controller Scaled up replica set nginx-deployment-7576c67d77 to 1
Normal ScalingReplicaSet 42m deployment-controller Scaled down replica set nginx-deployment-9b644dcd5 to 2
Normal ScalingReplicaSet 42m deployment-controller Scaled up replica set nginx-deployment-7576c67d77 to 2
...
如果运行 kubectl get deployment nginx-deployment -o yaml
, Deployment 状态输出:
$ kubectl get deployment nginx-deployment -o yaml
...
status:
availableReplicas: 3
conditions:
- lastTransitionTime: "2020-03-17T08:59:10Z"
lastUpdateTime: "2020-03-17T08:59:10Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2020-03-17T09:43:19Z"
lastUpdateTime: "2020-03-17T09:43:19Z"
message: ReplicaSet "nginx-deployment-b7556d645" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 7
readyReplicas: 3
replicas: 3
updatedReplicas: 3
...
最终,一旦超过 Deployment 进度截止时间,Kubernetes 将更新状态和进度状态:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
4. DaemonSet
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
- 在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。
- 在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。
- 在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、Flowmill、Sysdig 代理、collectd、Dynatrace OneAgent、AppDynamics 代理、Datadog 代理、New Relic 代理、Ganglia gmond 或者 Instana 代理。