kubernetes对长时间运行的容器要求:必须一直在前台执行。如果是后台执行的程序,例如
Nohup ./start.sh &
则会在执行完成之后销毁Pod,但是可以借助一些方式让后台程序在前台执行,例如supervisor
如果两个容器耦合性较强,可以放在一个Pod里面,此时他们可以共享网络和文件。例如:
1、前端应用容器直接通过localhost访问后台应用容器服务;
2、一个应用写日志到本地,一个应用从本地读日志;
https://kubernetes.io/zh/docs/tasks/configure-pod-container/static-pod/
静态Pod是指由kubelet管理仅存在于特定Node上的Pod,不能1、通过API Server管理 2、与RC、Deployment关联 3、kubelet无法进行健康检查
创建静态Pod有配置文件和HTTP方式。
设置kubelet的启动参数"–pod-manifest-path=/root/yaml/",对于该目录下的yaml或者json文件,kubelet服务会定期进行扫描和创建。
apiVersion: v1 kind: Pod metadata: name: static-web labels: role: myrole spec: containers: - name: web image: nginx ports: - name: web containerPort: 80 protocol: TCP
静态Pod无法通过kubectl delete删除,删除后状态会变成Pending,删除需要删除对应config目录下的json和yaml配置。
指定kubelet的启动参数"–manifest-url"。
Note: 卷的名称只能是xx-xx的形式,不能使用小驼峰.
一个Pod内存在多个容器时,容器可以共享挂载卷,实现同一个目录,一个容器应用读取,一个容器应用写入。
例如:
apiVersion: v1 kind: Pod metadata: name: share-volumes-pod spec: containers: - name: tomcat image: tomcat volumeMounts: - name: log-volumes mountPath: /usr/local/tomcat/logs ports: - containerPort: 8080 - name: ubuntu-curl image: nanda/ubuntu-curl:v1 volumeMounts: - name: log-volumes mountPath: /logs command: - sh - -c args: - while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8080)" != '200' ]]; do echo Waiting for tomcat;sleep 5; done; tail -f /logs/catalina*.log; volumes: - name: log-volumes emptyDir: {}
这里有点要注意:容器启动是异步的,启动顺序是安装配置文件来,但是第二个启动时第一个不一定启动OK了,所有加入linux脚本命令等待第一个执行完毕。
kubernetes1.2提供一种统一的应用配置管理方案:ConfigMap。注意是通过环境变量注入到容器,而且可以实现将node上的文件变为配置,配置然后挂载成容器中的文件。
apiVersion: v1 kind: ConfigMap # ConfigMap metadata: name: app-vars # ConfigMap的名称,全局唯一 data: apploglevel: info appdatadir: /var/data
可以将配置文件的内容作为data中的value
# 从目录中进行创建,文件名作为key,文件内容作为value kubectl create configmap ConfigMap名称 --from-file=目录
1、通过环境变量
apiVersion: v1 kind: Pod metadata: name: test-use-configmap spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - env | grep APP; env: - name: APPLOGLEVEL valueFrom: configMapKeyRef: name: app-vars # ConfiMap的名称 key: apploglevel # ConfigMap中Key的名称 restartPolicy: Never # 执行完毕后退出,不重启,默认时Always
2、1.6之后的新字段envFrom将ConfigMap中所有定义的key=value自动生成环境变量
apiVersion: v1 kind: Pod metadata: name: test-use-configmap spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - env; envFrom: - configMapRef: name: app-vars # ConfiMap的名称 restartPolicy: Never # 执行完毕后退出,不重启,默认时Always
通过将ConfigMap中的key作为文件名,value作为文件内容挂载到容器中。
1、指定挂载configmap中的某一些配置
apiVersion: v1 kind: Pod metadata: name: test-use-configmap spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - ls /configfiles && cat /configfiles/apploglevel.txt && cat /configfiles/appdatadir.log; volumeMounts: - name: testvolumes # 卷名称 mountPath: /configfiles # 挂载到容器中的目录 volumes: - name: testvolumes configMap: name: app-vars # 挂载的configmap名称 items: # configmap中的那些项将被挂载 - key: apploglevel # configmap中的key path: apploglevel.txt # 文件名 - key: appdatadir # configmap中的key path: appdatadir.log # 文件名 restartPolicy: Never # 执行完毕后退出,不重启,默认时Always
2、挂载configmap中的所有配置
此时无法指定文件名了,只能以key作为文件名。
apiVersion: v1 kind: Pod metadata: name: test-use-configmap spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - ls /configfiles && cat /configfiles/apploglevel.txt && cat /configfiles/appdatadir.log; volumeMounts: - name: testvolumes # 卷名称 mountPath: /configfiles # 挂载到容器中的目录 volumes: - name: testvolumes configMap: name: app-vars # 挂载的configmap名称 restartPolicy: Never # 执行完毕后退出,不重启,默认时Always
1、必须在Pod前创建
2、受namespace限制
3、静态Pod无法使用
4、文件挂载时,会覆盖容器内原本的文件
主要是通过Downward API进行注入,两种方式:1、环境变量 2、文件挂载
apiVersion: v1 kind: Pod metadata: name: test-get-pod-info labels: a: a b: b c: c annotations: build: two builder: jhn-doe spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - env | grep POD_NAME && ls /configfiles && cat /configfiles/labels && cat /configfiles/annotations env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name volumeMounts: - name: podinfo mountPath: /configfiles readOnly: false volumes: - name: podinfo downwardAPI: items: - path: "labels" fieldRef: fieldPath: metadata.labels - path: "annotations" fieldRef: fieldPath: metadata.annotations restartPolicy: Never # 执行完毕后退出,不重启,默认时Always
Downward API提供的变量有:
apiVersion: v1 kind: Pod metadata: name: test-get-pod-resource-info spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - env | grep MY_ resources: requests: memory: "32Mi" cpu: "125m" limits: memory: "64Mi" cpu: "250m" env: - name: MY_REQUEST_CPU valueFrom: resourceFieldRef: containerName: ubuntu-curl resource: requests.cpu - name: MY_LIMITS_CPU valueFrom: resourceFieldRef: containerName: ubuntu-curl resource: limits.cpu - name: MY_REQUEST_MEMORY valueFrom: resourceFieldRef: containerName: ubuntu-curl resource: requests.memory - name: MY_LIMITS_MEMORY valueFrom: resourceFieldRef: containerName: ubuntu-curl resource: limits.memory restartPolicy: Never # 执行完毕后退出,不重启,默认时Always
Downward API提供的变量有:
某些程序启动时,可能需要自身的某些信息(自身标示或者IP)然后注册到服务注册中心的地方,这时可以使用启动脚本将注入的POD信息写到配置文件中,然后启动程序。
状态 | 描述 |
---|---|
pending | API Server已经创建该Pod,但是Pod中还有容器没有创建,包括镜像下载的过程 |
Running | Pod内所有容器都已经创建,容器处于运行、正在启动、正在重启状态 |
Complete/Succeeded | Pod中所有容器都已经成功执行并且退出,且不会再重启 |
Failed | Pod中所有容器都已退出,但有容器的退出状态为失败(exitcode非0) |
Unknown | 网络不通,无法获取状态 |
yaml文件中restartPolicy的取值:
重启的时间:sync-frequency*2n,最长延迟5分钟,并且在成功重启后的10分钟后重置改时间。
总结:需要长时间运行的程序设置为Always,只需要执行一次的程序设置为Never或者OnFailure
Kubernetes提供三种方式进行Pod中容器的健康检查,健康检查不通过时会依据配置的重启策略进行重启。
1、在容器中执行命令
2、TCP连接测试
3、HTTP请求测试
TCP和HTTP方式即使失败,退出码也是0,所以配置为Never的情况下,失败会变成Complete
apiVersion: v1 kind: Pod metadata: name: test-liveness-cmd spec: containers: - name: ubuntu-curl image: nanda/ubuntu-curl:v1 command: - sh - -c args: - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 600; livenessProbe: # 执行cat /tmp/health命令,如果后面文件不存在时cat命令返回code是0,可以通过执行命令后执行echo $?查看 exec: command: - cat - /tmp/health initialDelaySeconds: 15 # 延迟15s后执行 timeoutSeconds: 1 # 响应超时时间 restartPolicy: Never
这里会一直重启该Pod,这个Pod执行会一直失败.
apiVersion: v1 kind: Pod metadata: name: test-liveness-tcp spec: containers: - name: nginx image: nginx ports: - containerPort: 80 livenessProbe: # 与本地的8080端口建立连接,没有开启这个端口,所以容器健康检查会失败,容器退出 tcpSocket: port: 8080 initialDelaySeconds: 30 # 延迟30s后执行 timeoutSeconds: 1 # 响应超时时间 restartPolicy: Never
apiVersion: v1 kind: Pod metadata: name: test-liveness-http spec: containers: - name: nginx image: nginx ports: - containerPort: 80 livenessProbe: # 访问localhost:80/_status/healthz,nginx没有,所以会404,健康检查失败容器退出 httpGet: path: /_status/healthz port: 80 initialDelaySeconds: 30 # 延迟30s后执行 timeoutSeconds: 1 # 响应超时时间 restartPolicy: Never
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/
我们的Pod可能根据不同的情况需要被调度到不同的Node上,可能存在以下几种情况:
1、web应用,不限定node
2、数据库类Pod部署到ssd的node上
3、某两个pod不能部署到同一个node上或者某 两个pod必须部署到同一个node上(共用网络和数据卷)
4、zk、es、mongo、kafka,必须部署到不同的node上,恢复后需要挂载原来的volume,复杂
5、日志采集、性能采集每个node上都需要有且部署一个
Deployment可以控制指定Pod的数量,且可以实现全自动调度。
Deployment也是依据ReplicaSet来进行管理Pod的,所以我们创建一个Deployment的时候也会创建一个ReplicaSet对象。
1、部署三个Nginx Pod
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx-deployment template: metadata: labels: app: nginx-deployment spec: containers: - name: nginx-deployment image: nginx resources: limits: memory: "128Mi" cpu: "250m" ports: - containerPort: 80
2、两个版本的nginx,共三个,TODO
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/
将Pod调度到指定的node上
有两种方式打标签,命令行和文件的方式,都是在master结点上进行。
1、命令行
kubectl label nodes <node-name> <label-key>=<label-value>
例如,给node1结点打上disk=ssd的标签
kubectl label nodes node1 disk=ssd
tips:
查看每个node上的labels
kubectl get nodes --show-labels
通过查看,我们可以知道每个node的一些基本信息:操作系统、系统架构、主机名等信息都已经默认作为label标记在node上了。
删除指定node上的label
kubectl label nodes node1 disk-
修改指定node上label值
没有就会新建,相当于save=create or update
kubectl label nodes node1 disk=ssd --overwrite
apiVersion: v1 kind: ReplicationController metadata: name: redis-master spec: replicas: 1 selector: app: redis-master template: metadata: name: redis-master labels: app: redis-master spec: containers: - name: redis-master image: redis ports: - containerPort: 6379 # 将该rc控制的pod调度到打了disk=ssd的node上,标签不存在或者没有可用的node时就会调度失败 nodeSelector: disk: ssd
然后查看pod的情况,即可看到pod已经调度到了指定的node上了
kubectl get pods -o wide
上面的定向调度nodeselector属于一种硬限制,而且只能将Pods调度到指定的Nodes上。
NodeAffinity调度属于升级版,既可以支持硬限制,也可以支持软限制:优先级、顺序、权重。
IgnoreDuringExecution:如果在Pod运行期间标签发生了变更,不再符合Pod的亲和性需求,系统将会忽略该变化,Pod能继续在该节点运行
分为:
1、RequiredDuringSchedulingIgnoreDuringExecution:硬限制
对于定向调度的,我们可以这样写,也是一样的效果
apiVersion: v1 kind: Pod metadata: name: scheduling-soft labels: name: scheduling-soft spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: disk operator: In values: - ssd1 containers: - name: scheduling-soft image: redis resources: limits: memory: "128Mi" cpu: "250m" ports: - containerPort: 6379
2、PreferredDuringSchedulingignoredDuringExecution:软限制
例如上面的例子,如果disk=ssd标签的node不存在或者不可用,定向调度就会失败,我们使用软限制就可以让其退而求其次在其他node上进行调度:
apiVersion: v1 kind: Pod metadata: name: scheduling-soft labels: name: scheduling-soft spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disk operator: In values: - ssd1 containers: - name: scheduling-soft image: redis resources: limits: memory: "128Mi" cpu: "250m" ports: - containerPort: 6379
此时,我们的node上都没有disk=ssd1这个标签,但是还是能正常调度到其它node上。
Note:operator操作包括:In、NotIn、Exists、DoesNotExist、Gt、Lt
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx nodeName: node1
该功能1.4引入,前面的定向调度和node亲和性调度是站在node的角度上来对pod进行调度,但是我们有些需求是做pod之间的亲和和互斥,例如前端工程pod和后端工程pod部署在同一node上,mysql不能和redis部署在同一node上。
这时我们就可以使用Pod亲和和互斥调度
1、首先创建一个参考模板Pod
apiVersion: v1 kind: Pod metadata: name: nginx labels: name: nginx spec: containers: - name: nginx image: nginx resources: limits: memory: "128Mi" cpu: "500m" ports: - containerPort: 80
2、创建一个带有亲和性规则的Pod
其实Pod的亲和性调度还是依赖Pod上的标签,从需要指定topologyKey属性就可以看出来,亲和性规则:
在具有标签X的Node上运行了一个或者多个符合条件Y的Pod,那么该Pod应该允许在这个Node上
这里有两个条件:1、标签X的node 2、符合条件Y的Pod
但是我们可以推广第一个条件为全部的node,此时我们可以设置这个标签为每个node都有的默认的标签,例如:kubernetes.io/hostname
apiVersion: v1 kind: Pod metadata: name: pod-affinity labels: name: pod-affinity spec: containers: - name: pod-affinity image: tomcat resources: limits: memory: "128Mi" cpu: "250m" ports: - containerPort: 8080 affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: name operator: In values: - nginx topologyKey: kubernetes.io/hostname
此时我们再查看node就会发现,两个pod就调度到同一个node节点上了。
一个Pod不能和另外一个Pod调度到同一台机器上,可以使用podAntAffinity,指定另外一个Pod的标签。
apiVersion: v1 kind: Pod metadata: name: pod-affinity-mutex labels: name: pod-affinity-mutex spec: containers: - name: pod-affinity-mutex image: tomcat resources: limits: memory: "128Mi" cpu: "250m" ports: - containerPort: 8080 affinity: # 互斥 podAntAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: name operator: In values: - nginx topologyKey: kubernetes.io/hostname
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/
前面的调度是让Pod调度到node节点上,而Taints是让node拒绝Pod的运行。
Taints是node的属性,Tolerations是Pod的属性,node有taints,除非Pod明确表明能够容忍node的Taints,否则无法Pod无法调度或者运行在指定的node上。
1、禁止再将Pod调度到该node
# 给node1添加一个键为key,值为value,效果为NoSchedule的taints。 kubectl taint nodes node1 key=value:NoSchedule # 删除,后面加个减号 kubectl taint nodes node1 key=value:NoSchedule- # 查看node的所有Taints kubectl describe node node2 | grep Taints
效果:
effect | 描述 |
---|---|
NoSchedule | 没有指定Tolerations的Pod不会被调度到该node,master节点配置了这个属性,key为node-role.kubernetes.io/master |
PreferNoSchedule | 没有指定Tolerations的Pod不会被优先调度到该node |
NoExecute | 没有指定Tolerations的Pod会被立即驱逐,指定tolerationSeconds后会在指定时间后被驱逐 |
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent tolerations: - key: "key" operator: "Exists" effect: "NoSchedule"
operator的取值:Equal、Exist
effect的取值:NoSchedule、PreferNoSchedule(尽量避免调度,非强制)、NoExecute
operator一些规则:
使用场景:
1、部分node只给指定应用用,在node添加NoSchedule的taints,然后只在指定Pod上设置tolerations
2、node故障时,通过给node添加taints驱逐node上的pods
3、kubernetes的node有问题或者网络有问题时,会自动给node添加内置的taint使之无法调度到该节点
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/pod-priority-preemption/
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority # 超过一亿被系统保留,给系统组件使用 value: 1000000 globalDefault: false description: "description priority"
scheduling.k8s.io/v1beta1 PriorityClass is deprecated in v1.14+, unavailable in v1.22+; use scheduling.k8s.io/v1 PriorityClass
1.22中PriorityClass就成了正式版了
集群情况:两个node,每个node一个CPU,2G内存
先部署两个redis,每个使用半个CPU,将所有资源占满,再部署一个高优先级的使用半个CPU的tomcat,此时tomcat调度时就会驱逐掉一个redis
apiVersion: v1 kind: ReplicationController metadata: name: redis-master spec: replicas: 2 selector: app: redis-master template: metadata: name: redis-master labels: app: redis-master spec: containers: - name: redis-master image: redis ports: - containerPort: 6379 resources: limits: memory: "128Mi" cpu: "500m"
apiVersion: v1 kind: ReplicationController metadata: name: tomcat spec: replicas: 1 selector: app: tomcat template: metadata: name: tomcat labels: app: tomcat spec: containers: - name: tomcat image: tomcat ports: - containerPort: 8080 resources: limits: memory: "128Mi" cpu: "500m" priorityClassName: high-priority
https://kubernetes.io/zh/docs/concepts/workloads/controllers/daemonset/
需求:
使用:
apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-elasticsearch namespace: kube-system labels: k8s-app: fluentd-logging spec: selector: matchLabels: name: fluentd-elasticsearch # 滚动升级 updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 template: metadata: labels: name: fluentd-elasticsearch spec: tolerations: # this toleration is to have the daemonset runnable on master nodes # remove it if your masters can't run pods - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd-elasticsearch image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers
此时,包括master也会部署一个node。
1.6版本后,DaemonSet也能进行滚动升级。
删除掉DaemonSet,默认不会删除每个node上的Pod,添加–cascade=false命令,将会一起删除每个node上的Pod。
通过使用nodeSelect进行过滤,参考Pod亲和性和互斥
https://kubernetes.io/zh/docs/tasks/manage-daemon/update-daemon-set/
1、yaml文件中进行配置更新策略为滚动升级
2、修改配置后进行apply操作
https://kubernetes.io/zh/docs/concepts/workloads/controllers/job/
基本格式:
apiVersion: batch/v1 kind: Job metadata: name: pi spec: completions: 8 # Pod的执行次数 parallelism: 2 # Pod的并行个数 template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never backoffLimit: 4 # 重试次数
三种使用方式:
1、一个任务创建一个Job,一个Job执行一个Pod
2、多个任务创建一个Job(使用Redis队列),一个Job执行多个Pod,N个任务N个Job
3、多个任务创建一个Job(使用Redis队列),一个Job执行多个Pod,N个任务M个Job
https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
apiVersion: batch/v1beta1 kind: CronJob metadata: name: hello spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: hello image: busybox imagePullPolicy: IfNotPresent command: - /bin/sh - -c - date; echo Hello from the Kubernetes cluster restartPolicy: OnFailure
CronJob类型apiVersion在1.18中是batch/v1beta1,书籍和官方最新文档是v1,没搞懂是什么情况。TODO
创建CronJob之后,每隔一分钟就会创建一个Pod执行一次。
# ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of the month (1 - 31) # │ │ │ ┌───────────── month (1 - 12) # │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; # │ │ │ │ │ 7 is also Sunday on some systems) # │ │ │ │ │ # │ │ │ │ │ # * * * * *
Entry | Description | Equivalent to |
---|---|---|
@yearly (or @annually) | Run once a year at midnight of 1 January | 0 0 1 1 * |
@monthly | Run once a month at midnight of the first day of the month | 0 0 1 * * |
@weekly | Run once a week at midnight on Sunday morning | 0 0 * * 0 |
@daily (or @midnight) | Run once a day at midnight | 0 0 * * * |
@hourly | Run once an hour at the beginning of the hour | 0 * * * * |
*和/的作用:
*:任意值
/:表示从起始时间开始,每隔固定时间触发一次;例如*/1 * * * *表示从现在开始每隔一分钟执行一次
计算网站:
https://crontab.guru/
TODO
https://kubernetes.io/zh/docs/concepts/workloads/pods/init-containers/
1.3版本引入,应用启动之前启动一个初始化容器,完成应用启动前的预置条件,例如
例子:初始化Nginx前,为Nginx创建一个Index.html(Nginx镜像没有index.html文件,访问localhost:80会404)
apiVersion: v1 kind: Pod metadata: name: nginx labels: name: nginx spec: initContainers: - name: init-nginx-index image: busybox # 将百度主页下载到/work-dir/下 command: - wget - "-O" - "/work-dir/index.html" - http://www.baidu.com volumeMounts: - name: workdir mountPath: /work-dir containers: - name: nginx image: nginx resources: limits: memory: "128Mi" cpu: "500m" ports: - containerPort: 80 volumeMounts: - name: workdir mountPath: /usr/share/nginx/html volumes: - name: workdir emptyDir: {}
查看init-container日志
kubectl logs nginx -c init-nginx-index
初始化容器与Pod的区别:
新建一个deployment
apiVersion: apps/v1 kind: Deployment # Deployment metadata: name: mynginx # Deployment的名称,全局唯一 spec: replicas: 3 # Pod副本的期待数量 selector: matchLabels: # 注意这里写法和RC的不一样,因为支持多个selector app: mynginx # 符合目标的pod拥有此标签,===1此处应当一致 template: # 根据此模板创建pod的副本 metadata: labels: app: mynginx # pod副本拥有的标签,===1此处应当一致 spec: containers: # pod中容器的定义部分 - name: mynginx # 容器名称 image: nginx:1.7.9 # 容器对应的docker镜像 ports: - containerPort: 80 # 容器应用监听的端口号
# 查看滚动升级过程,完成后就只有成功的日志了 kubectl rollout status deployment/deployment名称
# 格式 kubectl set image deployment/deployment名称 容器名称=镜像名称:镜像版本 # 例如 kubectl set image deployment/mynginx mynginx=nginx:1.9.1
此时为滚动升级,先运行一个新的,新的运行起来后,再停止一个旧的;主要通过新建一个RS,然后调整两个RS的数量
# 格式 kubectl edit deployment/deployment名称 # 例如 kubectl edit deployment/mynginx
Deployment的更新由对应yaml文件中的配置指定,下面是默认值
spec: strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate
type有两种取值:recreate(停止所有旧的,再启动新的)和RollingUpdate(默认)
maxSurge:滚动升级过程中,Pod总数超过Pod期望副本数部分的最大值,向上取整
maxUnavailable:滚动升级过程中,可用Pod占Pod总数的百分比,向下取整,也可以是大于零的绝对值。
在上一次更新途中,如果又触发一次更新操作,将会终止上一次更新创建的Pod,然后再进行更新
新增或者修改Deployment的标签选择器时,必须修改Pod上的标签,不然原本的Pod会处于孤立状态,不会被系统自动删除,也不受新的RS控制。
删除Deployment标签选择器,对应的RS和Pod不会受到任何的影响。
# 查看Depolyment的历史 kubectl rollout history deployment/mynginx # 查看指定版本Depolyment的详情信息 kubectl rollout history deployment/mynginx --revision=4 # ⚠️⚠️⚠️只有更新Deployment时加上--record=true时才会记录该条历史 kubectl set image deployment/mynginx mynginx=nginx:1.9.1 --record=true
# 回滚到上一个版本 kubectl rollout undo deployment/mynginx # 回滚到指定版本 kubectl rollout undo deployment/mynginx --to-revision=3
# 暂停Deployment的更新,暂停后对deployment的更新不会触发操作,只有恢复后才会进行 kubectl rollout pause deployment/mynginx # 恢复Deployment的更新 kubectl rollout resume deployment/mynginx
暂停和更新有助于我们对Deployment进行复杂的修改
# 使用一个新的RC代替旧的RC kubectl rolling-update old-rc-name -f new-rc.yaml # 修改旧的RC镜像 kubectl rolling-update old-rc-name --image=image-name:version
1、配置DaemonSet的yaml滚动策略为RollingUpdate(1.6引入)
2、apply旧版本配置文件