前言:Deployment的发展
虽然ReplicaSet可以确保在任何给定时间运行的Pod副本达到指定的数量,但是Deployment(部署)是一个更高级的概念,它管理ReplicaSet并为Pod和ReplicaSet提供声明性更新以及许多其他有用的功能,所以建议在实际使用中,采用Deployment代替ReplicaSet。
如果在Deployment对象中描述了所需的状态,Deployment控制器就会以可控制的速率将实际状态更改为期望状态。也可以在Deployment中创建新的ReplicaSet,或者删除现有的Deployment并使用新的Deployment部署所用的资源。
一、无状态应用管理器Deployment
deployment用于部署无状态的服务,是k8s中最常用的控制器。管理对象为pod。
一般用于管理维护企业内部无状态的微服务,比如configserver、zuul、springboot。
deployment可以管理多个副本的Pod实现无缝迁移、自动扩容缩容、自动灾难恢复、一键回滚等功能。
Deployment管理器基础操作
创建Deployment
方式1:手动创建
kubectl create deployment {deployment-name} --image=nginx
方式2:以yaml格式或json格式创建Deployment
kubectl create -f test-nginx.yaml
查询deployment状态
查看指定deployment的详细信息
kubectl describe deployment {deployment-name} -n {namespace-name}
kubectl get deployments -o wide
解析:-o wide 查看全部详情
导出deployment配置
导出已创建的deployment配置文件至指定路径:
kubectl get deployments test-nginx -o yaml >/data1/k8s-app/deploy/test-nginx.yaml
查看指定某一pod下的日志
kubectl logs {pod-name} -n {namespace-name}
修改deployment配置
修改某个指定deployment配置
kubectl edit deployment {deployment-name} -n {namespace-name}
kubectl apply -f xxx.yaml -n {namespace-name}
kubectl replace -f xxx.yaml -n {namespace-name}
版本升级操作:
手动改镜像并记录:
kubectl set image deploy {deployment-name} -n {namespace-name} XXX=xx(版本信息) --record
解析:
--record 表示记录本次修改
查看部署历史:
kubectl rollout history deploy {deployment-name} -n {namespace-name}
更新多次,需要查看某次更新的详细信息:
kubectl rollout history deploy {deployment-name} -n {namespace-name} --revision=3
解析:
--revision 指定版本号
回滚到上一个版本:
kubectl rollout undo deploy {deployment-name} -n {namespace-name}
回滚到指定版本:
kubectl rollout undo deploy {deployment-name} -n {namespace-name} --to-revision=2
解析:
--to-revision=2 表示回滚到更新的第2个版本
扩容与缩容
动态调整Pod的副本数:
kubectl scale deploy {deployment-name} -n {namespace-name} --replicas=5
解析:
--replicas=5 将原有副本数修改为5,若原有为2个,将扩容3个副本;若原有为10个,将缩容
注意:这里的扩容缩容,不会修改原有rs
Deployment更新的暂停与恢复(用set 修改多处更新)
暂停Deployment更新
kubectl rollout pause deploy {deployment-name} -n {namespace-name}
set修改deployment资源
kubectl set image ......
kubectl set resources deploy {deployment-name} -c {container-name}(指定容器) --limits=cpu=200m,memory=128Mi --requests=cpu=10m,memory=16Mi
恢复Deployment更新:
kubectl rollout resume {deployment-name} -n {namespace-name}
注意:恢复更新的Deployment创建了一个新的RS(复制集)
注意事项:
可修改yaml格式来更新Deployment,其中在spec下的几个参数配置解析为:
- replicas: 4 表示副本数,4为4个副本
- revisionHistoryLimit:设置保留RS旧的revision的个数,设置为0的话,不保留历史数据;
- minReadySeconds:可选参数,指定新创建的Pod在没有任何容器崩溃的情况下视为Ready最小的秒数,默认为0,即一旦被创建就视为可用。
关于滚动更新的策略参数解析:
strategy.type:更新deployment的方式,默认是RollingUpdate;
- RollingUpdate表示滚动更新,可以指定maxSurge和maxUnavailable
- maxUnavailable:指定在回滚或更新时最大不可用的Pod的数量,可选字段,默认25%,可以设置成数字或百分比,如果该值为0,那么maxSurge就不能0
- maxSurge:可以超过期望值的最大Pod数,可选字段,默认为25%,可以设置成数字或百分比,如果该值为0,那么maxUnavailable不能为0
- Recreate:重建,先删除旧的Pod,在创建新的Pod
示例:
# kubectl get deploy nginx -oyaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "12"
kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.3
--record=true
creationTimestamp: "2020-09-19T02:41:11Z"
generation: 19
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.3
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 10m
memory: 16Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
二、有状态应用管理StatefulSet
StatefulSet(有状态集,缩写为sts)主要用于管理有状态应用程序的工作负载API对象。常用于部署有状态的且需要有序启动的应用程序。
和Deployment类似,一个StatefulSet也同样管理着基于相同容器规范的Pod。不同的是,StatefulSet为每个Pod维护了一个粘性标识。这些Pod是根据相同的规范创建的,但是不可互换,每个Pod都有一个持久的标识符,在重新调度时也会保留,一般格式为StatefulSetName-Number。比如定义一个名字是Redis-Sentinel的StatefulSet,指定创建三个Pod,那么创建出来的Pod名字就为Redis-Sentinel-0、Redis-Sentinel-1、Redis-Sentinel-2。
StatefulSet创建的Pod一般使用Headless Service(无头服务)负责Pod的网络身份和通信,需要提前创建此服务。和普通的Service的区别在于Headless Service没有ClusterIP,它使用的是Endpoint进行互相通信。在删除一个StatefulSet时,不保证对Pod的终止,要在StatefulSet中实现Pod的有序和正常终止,可以在删除之前将StatefulSet的副本缩减为0。
Headless一般格式为:
statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
解析:
- statefulSetName 为StatefulSet的名字;
- 0..N-1 为Pod所在的序号,从0开始到N-1;
- serviceName 为Headless Service的名字,创建StatefulSet时,必须指定Headless Service名称;
- namespace 为服务所在的命名空间;
- .cluster.local 为Cluster Domain(集群域)。
StatefulSet注意事项:
一般StatefulSet用于有以下一个或者多个需求的应用程序:
- 需要稳定的独一无二的网络标识符。
- 需要持久化数据。
- 需要有序的、优雅的部署和扩展。
- 需要有序的自动滚动更新。
- 如果应用程序不需要任何稳定的标识符或者有序的部署、删除或者扩展,应该使用无状态的控制器部署应用程序,比如Deployment或者ReplicaSet。
StatefulSet是Kubernetes 1.9版本之前的beta资源,在1.5版本之前的任何Kubernetes版本都没有。
Pod所用的存储必须由PersistentVolume Provisioner(持久化卷配置器)根据请求配置StorageClass,或者由管理员预先配置,当然也可以不配置存储。
为了确保数据安全,删除和缩放StatefulSet不会删除与StatefulSet关联的卷,可以手动选择性地删除PVC和PV(参考PV和PVC节)。
Deployment管理器基础操作
定义一个StatefulSet资源yaml文件
定义一个简单的StatefulSet的示例如下:
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:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
注意:
此示例没有添加存储配置
其中:
- kind: Service 定义了一个名字为Nginx的Headless Service,创建的Service格式为nginx-0.nginx.default.svc.cluster.local,其他的类似,因为没有指定Namespace(命名空间),所以默认部署在default。
- kind: StatefulSet 定义了一个名字为web的StatefulSet,replicas表示部署Pod的副本数。
- 在StatefulSet中必须设置Pod选择器(.spec.selector)用来匹配其标签(.spec.template.metadata.labels)。在1.8版本之前,如果未配置该字段(.spec.selector),将被设置为默认值,在1.8版本之后,如果未指定匹配Pod Selector,则会导致StatefulSet创建错误。
- 当StatefulSet控制器创建Pod时,它会添加一个标签statefulset.kubernetes.io/pod-name,该标签的值为Pod的名称,用于匹配Service。
查看更新过程
kubuctl rollout status sts {statefulset-name} -n {namespace-name}
过滤查看pod配置中某一信息
kubectl get pod {pod-name} -n {namespace-name} -oyaml | grep image
kubectl get po -l app=nginx -w
-w 参数表示动态查看pod的更新过程
在pod的配置中,updateStrategy 表示更新策略,其中若type: RollingUpdate 表示滚动更新,修改pod配置后会根据创建顺序更新,配置为:
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
解析:
partition: 0 表示分段更新,0表示小于0的pod不更新(即更新所有pod);其中数字表示更新的分段(pod)数;举例:若StatefulSet的pod数有5个,现在partition: 2;那么pod2前面的pod不会更新(pod0、pod1),更新的pod为pod2、pod3、pod4。多用于灰度发布(先让指定pod更新,在更新其它pod)
若type: OnDelete 表示只有删除pod时,才会更新修改的配置,且配置应为:
updateStrategy:
type: RollingUpdate
StatefulSet的删除
一般情况,删除sts时,pod会被重建
涉及概念:级联删除与非级联删除
- 级联删除:删除StatefulSet时同时删除pod,若不指定,默认为级联删除
- 非级联删除:删除StatefulSet时不删除pod,但删除sts后,pod变成“孤儿”,此时删除pod不会被重建
设置级联删除或非级联删除
非级联删除:
kubectl delete sts {statefulset-name} -n {namespace-name} --cascade=false
三、守护进程服务DaemonSet
DaemonSet 是守护进程集,缩写为ds,在所有节点或者是匹配条件的节点(通过打标签形式)上都部署一个Pod。
使用DaemonSet的场景
- 运行集群存储的daemon,比如ceph或者glusterd
- 节点的CNI网络插件,calico
- 节点日志的收集:fluentd或者是filebeat
- 节点的监控:node exporter
- 服务暴露:部署一个ingress-nginx
创建DaemonSet
kubectl create -f nginx-ds.yaml
示例:
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: nginx
name: nginx
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
updateStrategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
设置匹配条件的node部署pod
方法1命令部署:
kubectl label nodeXX(节点名称) nodeXX(节点名称-多个节点) ... ds=true
查看标签
kubectl get node --show-labels
方法2修改yaml文件:(注意,若replace YAML文件,会更新配置)
在spec下,添加
......
nodeSelector:
ds: "ture"
......
另外,若需要添加或删除ds节点,需进行label添加或删除即可
DaemonSet更新配置
......
updateStrategy:
rollingUpdate:
maxUnavailable: 1 ###最大不可用范围,建议设为1
......
注意:在DaemonSet的生产环境中,建议更新策略采用OnDelete,避免影响所有节点上的pod,可用几个不重要的pod做测试用
......
updateStrategy:
type: RollingUpdate
......
四、Label与Selector
Label:对k8s中各种资源进行分类、分组,添加一个具有特别属性的一个标签。
Selector:通过一个过滤的语法进行查找到对应标签的资源
删除label
kubectl label node {node-name} app- -n {namespace-name}
修改label
kubectl label pod {pod-name} app=xx(新名称) -n {namespace-name} --overwrite
查看所有ns下符合条件的标签
kubectl get svc -A --show-labels
kubectl get pod -A --show-labels
kubectl get node -A --show-labels
根据需求查看匹配条件的多种标签表达示例:
所有ns下,标签包含metrics-server和kubernetes-dashboad的pod
kubectl get po -A -l 'k8s-app in (metrics-server, kubernetes-dashboad)'
标签为nginx,但不包含v1版本的pod
kubectl get po -l version!=v1,app=nginx
所有ns下,标签为nginx,但不包含v1版本的pod
kubectl get po -A -l version!=v1,'app02 in (nginx,busybox)'
未完待续。。。。