工作负载能让Pod能拥有自恢复能力,会写Pod,研究不同的工作负载怎么控制Pod的行为
1. Deploy
2. StatefulSet
3. DaemonSet
4. Job
5. CronJob
Deployment控制RS,RS控制Pod的副本数
ReplicaSet: 只提供了副本数量的控制功能
Deployment: 每部署一个新版本就会创建一个新的副本集,利用他记录状态,回滚也是直接让指定的rs生效
################更新#################################
# kubectl set image deployment资源名 容器名=镜像名
kubectl set image deployment.apps/nginx-deployment php-redis=tomcat:8 --record
## yaml提取可更新的关键所有字段计算的hash。
web---- /hello
postman aservice- /hello
# 或者直接修改定义也行
kubectl edit deployment.v1.apps/nginx-deployment
# 查看状态
kubectl rollout status deployment.v1.apps/nginx-deployment
################查看历史并回滚####################################
# 查看更新历史-看看我们设置的历史总记录数是否生效了
kubectl rollout history deployment.v1.apps/nginx-deployment
# 回滚
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
###############累计更新##############
# 暂停记录版本
kubectl rollout pause deployment.v1.apps/nginx-deployment
# 多次更新操作。
## 比如更新了资源限制
kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
## 比如更新了镜像版本
kubectl set image deployment.apps/nginx-deployment php-redis=tomcat:8
## 在继续操作多次
## 看看历史版本有没有记录变化
kubectl rollout history deployment.v1.apps/nginx-deployment
# 让多次累计生效
kubectl rollout resume deployment.v1.apps/nginx-deployment
maxSurge(最大增量):除当前数量外还要添加多少个实例
maxUnavailable(最大不可用量):滚动更新过程中的不可用实例数
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
labels:
app: my-app
spec:
selector:
matchLabels:
app: my-app
replicas: 10
strategy:
# type: Recreate # 把以前全部杀死,直接新建
type: RollingUpdate
rollingUpdate:
maxSurge: 20%
maxUnavailable: 2
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: nginx
image: nginx:latest
https://github.com/kubernetes-sigs/metrics-server
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- nodes/stats
- namespaces
- configmaps
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --kubelet-insecure-tls
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/metrics-server:v0.4.3
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
periodSeconds: 10
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
# 应用的yaml已经做好
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: php-apache
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: php-apache
name: php-apache
spec:
replicas: 1
selector:
matchLabels:
run: php-apache
template:
metadata:
creationTimestamp: null
labels:
run: php-apache
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/php-hpa:latest
name: php-apache
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
# hpa配置 hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 50
# 进行压力测试
kubectl run -i --tty load-generator --image=busybox /bin/sh
# 回车然后敲下面的命令
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary-dep-v2
namespace: default
labels:
app: canary-dep-v2
spec:
selector:
matchLabels:
app: canary-nginx
v: v222
replicas: 1
template:
metadata:
labels:
app: canary-nginx
v: v222
spec:
containers:
- name: nginx
image: nginx
DaemonSet 控制器确保所有(或一部分)的节点都运行了一个指定的 Pod 副本。
DaemonSet 的典型使用场景有:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: logging
labels:
app: logging
spec:
selector:
matchLabels:
name: logging
template:
metadata:
labels:
name: logging
spec:
containers:
- name: logging
image: nginx
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
tolerations: # 设置容忍master的污点
- key: node-role.kubernetes.io/master
effect: NoSchedule
# 查看效果
kubectl get pod -l name=logging -o wide
有状态副本集;Deployment等属于无状态的应用部署(stateless)
如果一个应用程序不需要稳定的网络标识,或者不需要按顺序部署、删除、增加副本,就应该考虑使用 Deployment 这类无状态(stateless)的控制器
apiVersion: v1
kind: Service # 定义一个负载均衡网络
metadata:
name: stateful-tomcat
labels:
app: stateful-tomcat
spec:
ports:
- port: 8123
name: web
targetPort: 8080
clusterIP: None # NodePort:任意机器+NodePort都能访问,ClusterIP:集群内能用这个ip、service域名能访问,clusterIP: None;不要分配集群ip。headless;无头服务。稳定的域名
selector:
app: stateful-tomcat
---
apiVersion: apps/v1
kind: StatefulSet # 控制器
metadata:
name: stateful-tomcat
spec:
selector:
matchLabels:
app: stateful-tomcat # has to match .spec.template.metadata.labels
serviceName: "stateful-tomcat" #这里一定注意,必须提前有个service名字叫这个的
replicas: 3 # by default is 1
template:
metadata:
labels:
app: stateful-tomcat # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: tomcat
image: tomcat:7
ports:
- containerPort: 8080
name: web
# 观察效果
删除一个, 重启后名字, ip等都是一样的, 保证了状态
# 细节
kubectl explain StatefulSet.spec
podManagementPolicy:
OrderedReady(按序)、Parallel(并发)
serviceName -required-
设置服务名,就可以用域名访问pod了。
pod-specific-string.serviceName.default.svc.cluster.local
# 测试
kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
ping stateful-tomcat-0.stateful-tomcat
# 我们在这里没有加存储卷。如果有的话 kubectl get pvc -l app=stateful-tomcat 我们就能看到即使Pod删了再拉起,卷还是同样的
Kubernetes中的 Job 对象将创建一个或多个 Pod,并确保指定数量的 Pod 可以成功执行到进程正常结束:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never #Job情况下,不支持Always
backoffLimit: 4 # 任务4次都没成,认为失败
activeDeadlineSeconds: 10
# 默认这个任务需要成功执行一次。
# 查看job情况
kubectl get job
# 修改下面参数设置再试试
# 千万不要用阻塞容器。nginx。job由于Pod一直running状态。下一个永远得不到执行,而且超时了,当前running的Pod还会删掉
kubectl api-resources
# 参数说明
kubectl explain job.spec
activeDeadlineSeconds:10 总共维持10s
# 该字段限定了 Job 对象在集群中的存活时长,一旦达到 .spec.activeDeadlineSeconds 指定的时长,该 Job 创建的所有的 Pod 都将被终止。但是Job不会删除,Job需要手动删除,或者使用ttl进行清理
backoffLimit:
# 设定 Job 最大的重试次数。该字段的默认值为 6;一旦重试次数达到了 backoffLimit 中的值,Job 将被标记为失败,且尤其创建的所有 Pod 将被终止;
completions: # Job结束需要成功运行的Pods。默认为1
manualSelector:
parallelism: # 并行运行的Pod个数,默认为1
ttlSecondsAfterFinished:
ttlSecondsAfterFinished: 0 # 在job执行完时马上删除
ttlSecondsAfterFinished: 100 # 在job执行完后,等待100s再删除
# 除了 CronJob 之外,TTL 机制是另外一种自动清理已结束Job(Completed 或 Finished)的方式:
# TTL 机制由 TTL 控制器 提供,ttlSecondsAfterFinished 字段可激活该特性
# 当 TTL 控制器清理 Job 时,TTL 控制器将删除 Job 对象,以及由该 Job 创建的所有 Pod 对象。
# job超时以后 已经完成的不删,正在运行的Pod就删除
# 单个Pod时,Pod成功运行,Job就结束了
# 如果Job中定义了多个容器,则Job的状态将根据所有容器的执行状态来变化。
# Job任务不建议去运行nginx,tomcat,mysql等阻塞式的,否则这些任务永远完不了。
# 如果Job定义的容器中存在http server、mysql等长期的容器和一些批处理容器,则Job状态不会发生变化(因为长期运行的容器不会主动结束)。此时可以通过Pod的.status.containerStatuses获取指定容器的运行状态。
manualSelector:
CronJob 按照预定的时间计划(schedule)创建 Job(注意:启动的是Job不是Deploy,rs)。一个 CronJob 对象类似于 crontab (cron table) 文件中的一行记录。该对象根据 Cron 格式定义的时间计划,周期性地创建 Job 对象
Schedule
所有 CronJob 的 schedule 中所定义的时间,都是基于 master 所在时区来进行计算的。
一个 CronJob 在时间计划中的每次执行时刻,都创建 大约 一个 Job 对象。这里用到了 大约 ,是因为在少数情况下会创建两个 Job 对象,或者不创建 Job 对象。尽管 K8S 尽最大的可能性避免这种情况的出现,但是并不能完全杜绝此现象的发生。因此,Job 程序必须是 幂等的
当以下两个条件都满足时,Job 将至少运行一次:
# kubectl explain cronjob.spec
concurrencyPolicy:并发策略
"Allow" (允许,default):
"Forbid"(禁止): forbids;前个任务没执行完,要并发下一个的话,下一个会被跳过
"Replace"(替换): 新任务,替换当前运行的任务
failedJobsHistoryLimit:记录失败数的上限,Defaults to 1.
successfulJobsHistoryLimit: 记录成功任务的上限。 Defaults to 3.
# 指定了 CronJob 应该保留多少个 completed 和 failed 的 Job 记录。将其设置为 0,则 CronJob 不会保留已经结束的 Job 的记录。
jobTemplate: job怎么定义(与前面我们说的job一样定义法)
schedule: cron 表达式
startingDeadlineSeconds: 表示如果Job因为某种原因无法按调度准时启动,在spec.startingDeadlineSeconds时间段之内,CronJob仍然试图重新启动Job,如果在.spec.startingDeadlineSeconds时间之内没有启动成功,则不再试图重新启动。如果spec.startingDeadlineSeconds的值没有设置,则没有按时启动的任务不会被尝试重新启动。
suspend 暂停定时任务,对已经执行了的任务,不会生效; Defaults to false.
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *" #分、时、日、月、周
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
https://kubernetes.io/zh/docs/concepts/workloads/controllers/ttlafterfinished/
这是alpha版本
这个特性现在在v1.12版本是alpha阶段,而且默认关闭的,需要手动开启。
例如修改后的kube-scheduler.yaml的spec部分如下,kube-apiserver.yaml和kube-controller-manager.yaml也在spec部分加入- --feature-gates=TTLAfterFinished=true即可
什么是垃圾回收
Kubernetes garbage collector(垃圾回收器)的作用是删除那些曾经有 owner,后来又不再有 owner 的对象。描述
垃圾收集器如何删除从属对象
当删除某个对象时,可以指定该对象的从属对象是否同时被自动删除,这种操作叫做级联删除(cascading deletion)。级联删除有两种模式:后台(background)和前台(foreground)
如果删除对象时不删除自动删除其从属对象,此时,从属对象被认为是孤儿(或孤立的 orphaned)
通过参数 --cascade,kubectl delete 命令也可以选择不同的级联删除策略:
# 删除rs,但不删除级联Pod
kubectl delete replicaset my-repset --cascade=false