一.pod资源限制:
对pod资源限制原因:高并发占用所有的cpu资源、内存资源、会造成雪崩
当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小,以及其他类型的资源。
方式:
- 对pod做限制
- 对k8s做限制
1.pod资源限制方式:
- 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。
- 最常见的可设定资源是 CPU 和内存大小,以及其他类型的资源。
2.pod资源限制指定时指定的参数:
- request 资源:
当为 Pod 中的容器指定了 request 资源时,调度器就使用该信息来决定将 Pod 调度到哪个节点上。
- limit 资源:
当还为容器指定了 limit 资源时,kubelet 就会确保运行的容器不会使用超出所设的 limit 资源量。kubelet 还会为容器预留所设的 request 资源量, 供该容器使用。
如果 Pod 运行所在的节点具有足够的可用资源,容器可以使用超出所设置的 request 资源量。不过,容器不可以使用超出所设置的 limit 资源量。
- 两种资源匹配方式:
如果给容器设置了内存的 limit 值,但未设置内存的 request 值,Kubernetes 会自动为其设置与内存 limit 相匹配的 request 值。 类似的,如果给容器设置了 CPU 的 limit 值但未设置 CPU 的 request 值,则 Kubernetes 自动为其设置 CPU 的 request 值 并使之与 CPU 的 limit 值匹配。
3.资源限制的示例:
3.1官网示例:
Resource Management for Pods and Containers | Kubernetes
3.2Pod和容器的资源请求和限制格式:
#Pod 和 容器 的资源请求和限制:
spec.containers[].resources.requests.cpu //定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.memory //定义创建容器时预分配的内存资源
spec.containers[].resources.limits.cpu //定义 cpu 的资源上限
spec.containers[].resources.limits.memory //定义内存的资源上限
3.3CPU 资源单位介绍:
- CPU 资源的 request 和 limit 以 cpu 为单位。
- Kubernetes 中的一个 cpu 相当于1个 vCPU(1个超线程)
- Kubernetes 也支持带小数 CPU 的请求。
- spec.containers[].resources.requests.cpu 为 0.5 的容器能够获得一个 cpu 的一半 CPU 资源(类似于Cgroup对CPU资源的时间分片)。表达式 0.1 等价于表达式 100m(毫核),表示每 1000 毫秒内容器可以使用的 CPU 时间总量为 0.1*1000 毫秒。
- Kubernetes 不允许设置精度小于 1m 的 CPU 资源。
4.案例一:OOMKilled:资源不足被杀死:
apiVersion: v1
kind: Pod
metadata:name: ky-web-db
spec:containers:- name: webimage: nginxenv:- name: WEB_ROOT_PASSWORDvalue: "password"resources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"- name: dbimage: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: "abc123"resources:requests:memory: "64Mi"cpu: "0.25"limits:memory: "128Mi"cpu: "500m"
5.案例二 :给足资源:
apiVersion: v1
kind: Pod
metadata:name: ky-web-db
spec:containers:- name: webimage: nginxenv:- name: WEB_ROOT_PASSWORDvalue: "password"resources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"- name: dbimage: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: "abc123"resources:requests:memory: "64Mi"cpu: "0.5"limits:memory: "1Gi"cpu: "1"
二、健康检查,又称为探针(Probe):
探针是由kubelet对容器执行的定期诊断
1.探针的三种规则:
livenessProbe :
判断容器是否正在运行。如果探测失败,则kubelet会杀死容器,并且容器将根据 restartPolicy 来设置 Pod 状态。 如果容器不提供存活探针,则默认状态为Success。
readinessProbe :
判断容器是否准备好接受请求。如果探测失败,端点控制器将从与 Pod 匹配的所有 service 址endpoints 中剔除删除该Pod的IP地。 初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success。
startupProbe(这个1.17版本增加的):
判断容器内的应用程序是否已启动,主要针对于不能确定具体启动时间的应用。如果配置了 startupProbe 探测,在则在 startupProbe 状态为 Success 之前,其他所有探针都处于无效状态,直到它成功后其他探针才起作用。 如果 startupProbe 失败,kubelet 将杀死容器,容器将根据 restartPolicy 来重启。如果容器没有配置 startupProbe, 则默认状态为 Success。 #注:以上规则可以同时定义。在readinessProbe检测成功之前,Pod的running状态是不会变成ready状态的。
2.Probe支持三种检查方法(探测):
exec:
在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。
tcpSocket:
对指定端口上的容器的IP地址进行TCP检查(三次握手)。如果端口打开,则诊断被认为是成功的。
httpGet:
对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。
3.每次探测都将获得以下三种结果之一:
●成功:容器通过了诊断。
●失败:容器未通过诊断。
●未知:诊断失败,因此不会采取任何行动。
官网示例:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
4.探针三种方式示例:
4.1.exec方式:
apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: liveness-exec
spec:containers:- name: livenessimage: busyboximagePullPolicy: IfNotPresentargs: ###启动容器参数- /bin/sh- -c- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60livenessProbe: #定义了容器的就绪探针exec: #在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。command: #指定了执行的命令- cat- /tmp/healthyfailureThreshold: 1 #就绪探针在连续失败一次后被视为失败initialDelaySeconds: 5 #延迟5秒启动容器periodSeconds: 5 #每隔5秒探测一次// - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
创建一个名为 /tmp/healthy 的文件,暂停执行脚本,等待 30 秒钟,删除后,再次暂停执行脚本,等待额外的 60 秒钟
因为/tmp/healthy文件不存在,所以探测失败
4.2.httpGet方式:
apiVersion: v1
kind: Pod
metadata:name: liveness-httpgetnamespace: default
spec:containers:- name: liveness-httpget-containerimage: soscscs/myapp:v1 #soscscs:nginx1.12imagePullPolicy: IfNotPresent #拉取策略ports:- name: httpcontainerPort: 80livenessProbe: #探针httpGet:port: httppath: /index.htmlinitialDelaySeconds: 1 #延迟1秒开始探测periodSeconds: 3 #每3秒探测一次timeoutSeconds: 10 #超时时间10秒
删除index.html:
查看:
当我们删除页面后,会报错404;然后就会探测失败,最后会重启
4.3tcpSocket方式:
apiVersion: v1
kind: Pod
metadata:name: liveness-httpgetnamespace: default
spec:containers:- name: liveness-httpget-containerimage: soscscs/myapp:v1 #soscscs:nginx1.12imagePullPolicy: IfNotPresent #拉取策略ports:- name: httpcontainerPort: 80livenessProbe: #探针httpGet:port: httppath: /index.htmlinitialDelaySeconds: 1 #延迟1秒开始探测periodSeconds: 3 #每3秒探测一次timeoutSeconds: 10 #超时时间10秒
这个例子同时使用 readinessProbe 和 livenessProbe 探测。kubelet 会在容器启动 5 秒后发送第一个 readinessProbe 探测。这会尝试连接 goproxy 容器的 8080 端口。如果探测成功,kubelet 将继续每隔 10 秒运行一次检测。除了 readinessProbe 探测,这个配置包括了一个 livenessProbe 探测。kubelet 会在容器启动 15 秒后进行第一次 livenessProbe 探测。就像 readinessProbe 探测一样,会尝试连接 goproxy 容器的 8080 端口。如果 livenessProbe 探测失败,这个容器会被重新启动。
4.4.就绪探针readinessProbe1:
vim readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:name: readiness-httpgetnamespace: default
spec:containers:- name: readiness-httpget-containerimage: soscscs/myapp:v1 #指定了容器使用的镜像imagePullPolicy: IfNotPresent #指定了镜像拉取策略为仅在本地不存在时才拉取ports: #定义了容器暴露的端口,这里使用的是 80 端口- name: httpcontainerPort: 80readinessProbe: #就绪探测配置,用于检查容器是否准备好接受请求httpGet: #指定了进行 HTTP GET 请求的方式进行探port: 80 #探测请求将发送到容器的 80 端口path: /index1.html #探测请求发送的路径为 "/index1.html"initialDelaySeconds: 1 #容器启动后等待 1 秒后开始进行就绪探测periodSeconds: 3 #进行就绪探测的间隔为 3 秒livenessProbe: #存活探测配置,用于检查容器是否存活httpGet: #指定了进行 HTTP GET 请求的方式进行探测port: http #探测请求将发送到容器的 "http" 端口(实际上可能是 "http" 端口的映射,比如 8080)path: /index.html #探测请求发送的路径为 "/index.html"initialDelaySeconds: 1 #器启动后等待 1 秒后开始进行存活探测periodSeconds: 3 #进行存活探测的间隔为 3 秒timeoutSeconds: 10 #探测请求的超时时间为 10 秒
kubectl create -f readiness-httpget.yaml#readiness探测失败,无法进入READY状态
kubectl get pods
kubectl exec -it readiness-httpget sh
cd /usr/share/nginx/html/
ls
50x.html index.html
echo 123 > index1.html
exitkubectl get pods
4.5.就绪探针readinessProbe2:
vim readiness-myapp.yaml
---
apiVersion: v1
kind: Pod
metadata:
apiVersion: v1
kind: Pod
metadata:name: myapp1labels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10
---
apiVersion: v1
kind: Pod
metadata:name: myapp2labels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10
---
apiVersion: v1
kind: Pod
metadata:name: myapp3labels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10
---
apiVersion: v1
kind: Service
metadata:name: myapp
spec:selector:app: myapptype: ClusterIPports:- name: httpport: 80targetPort: 80
kubectl create -f readiness-myapp.yamlkubectl get pods,svc,endpoints -o widekubectl exec -it pod/myapp1 -- rm -rf /usr/share/nginx/html/index.html#readiness探测失败,Pod 无法进入READY状态,且端点控制器将从 endpoints 中剔除删除该 Pod 的 IP 地址
kubectl get pods,svc,endpoints -o wide
4.6.启动、退出动作 :
#启动、退出动作
vim post.yamlapiVersion: v1
kind: Pod
metadata:name: lifecycle-demo
spec:containers:- name: lifecycle-demo-containerimage: soscscs/myapp:v1lifecycle: #此为关键字段postStart:exec:command: ["/bin/sh", "-c", "echo Hello from the postStart handler >> /var/log/nginx/message"] preStop:exec:command: ["/bin/sh", "-c", "echo Hello from the poststop handler >> /var/log/nginx/message"]volumeMounts:- name: message-logmountPath: /var/log/nginx/readOnly: falseinitContainers:- name: init-myserviceimage: soscscs/myapp:v1command: ["/bin/sh", "-c", "echo 'Hello initContainers' >> /var/log/nginx/message"]volumeMounts:- name: message-logmountPath: /var/log/nginx/readOnly: falsevolumes:- name: message-loghostPath:path: /data/volumes/nginx/log/type: DirectoryOrCreate
kubectl create -f post.yamlkubectl get pods -o widekubectl exec -it lifecycle-demo -- cat /var/log/nginx/message#在 node01 节点上查看
[root@node01 ~]# cd /data/volumes/nginx/log/
[root@node01 log]# ls
access.log error.log message
[root@node01 log]# cat message
Hello initContainers
Hello from the postStart handler
#由上可知,init Container先执行,然后当一个主容器启动后,Kubernetes 将立即发送 postStart 事件。#在master删除 pod 后,再在 node01 节点上查看
kubectl delete pod lifecycle-demo[root@node01 log]# cat message
Hello initContainers
Hello from the postStart handler
Hello from the poststop handler
#由上可知,当在容器被终结之前, Kubernetes 将发送一个 preStop 事件。
三、总结:
1.pod容器探针三种方式:
存活探针:
判断容器是否运行正常,如果探测失败则杀死容器(不是pod),容器根据容器策略决定是否重启
就绪探针:
判断pod是否能进入ready状态,做好接受请求的准备,如果探测失败会进入notready状态,并且从serivce资源的endpointis中的提出,service将不会再把访问请求转发给这个pod
启动探针:
判断容器内的应用是否启动成功,在探测成功状态为success之前,其他探针都会处于失效状态
2.三种探测方式:
exec:
通过command设置,执行在容器内执行的Linux命令来进行探测,如果返回码为0,则为探测成功;非0则为探测失败
httpget:
通过http get 请求访问指定容器端口和url路径,如果访问状态码为>=200且<400(2xx 300),则认为探测成功,否则失败
tcpsocket:
通过指定的端口发送tcp连接,如果端口无误且三次握手成功(tcp连接成功),则认为探测成功