一、资源限制
1.1 资源限制的定义
当定义Pod时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是CPU和内存大小,以及其他类型的资源。
当为Pod中的容器指定了request资源时,调度器就使用该信息来决定将Pod调度到哪个节点上。当还为容器指定了limit资源时,kubelet就会确保运行的容器不会使用超出所设的limit资源量。kubelet还会为容器预留所设的request资源量, 供该容器使用。
如果Pod运行所在的节点具有足够的可用资源,容器可以使用超出所设置的request资源量。不过,容器不可以使用超出所设置的limit资源量。
如果给容器设置了内存的limit值,但未设置内存的request值,Kubernetes会自动为其设置与内存limit相匹配的request值。 类似的,如果给容器设置了CPU的 limit值但未设置CPU的request 值,则Kubernetes自动为其设置CPU的request值并使之与CPU的limit值匹配。
官方示例:https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
1.2 Pod和容器的资源请求和限制
spec.containers[].resources.requests.cpu | 定义创建容器时预分配的CPU资源 |
---|---|
spec.containers[].resources.requests.memory | 定义创建容器时预分配的内存资源 |
spec.containers[].resources.limits.cpu | 定义 cpu 的资源上限 |
spec.containers[].resources.limits.memory | 定义内存的资源上限 |
1.3 CPU资源单位
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资源。
1.4 内存资源单位
内存的request和limit以字节为单位。可以以整数表示,或者以10为底数的指数的单位(E、P、T、G、M、K)来表示, 或者以2为底数的指数的单位(Ei、Pi、Ti、Gi、Mi、Ki)来表示。
1.5 实验操作
1.5.1 OOM资源不足被干掉
apiVersion: v1
kind: Pod
metadata:
name: ky-web-db
spec:
containers:
- name: web
image: nginx
env:
- name: WEB_ROOT_PASSWORD
value: "password"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "abc123"
resources:
requests:
memory: "64Mi"
cpu: "0.25"
limits:
memory: "128Mi"
cpu: "500m"
资源不足第一个进程被杀死,注意如果节点上有资源会拉取节点资源创建,可先把节点关闭
查看日志信息,db因资源不足被干掉
1.5.2 资源充足
apiVersion: v1
kind: Pod
metadata:
name: ky-web-db
spec:
containers:
- name: web
image: nginx
env:
- name: WEB_ROOT_PASSWORD
value: "password"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "abc123"
resources:
requests:
memory: "64Mi"
cpu: "0.5"
limits:
memory: "1Gi"
cpu: "1"
给足资源后,状态为running
查看日志信息后,调度给了node01
查看node01详细信息,可以看到资源详细情况
二、探针
2.1 探针的定义
健康检查:又称为探针(Probe) ,探针是由kubelet对容器执行的定期诊断。
2.2 探针的规则
- 存活探针(livenessProbe):判断容器是否运行正常,如果探测失败则杀死容器(不是pod),容器根据容器策略决定是否重启
- 就绪探针(readinessProbe):判断pod是否能进入ready状态,做好接受请求的准备。如果探针失败会进入not ready状态且从service自愿的endpoints中剔除,service将不会再把访问请求转发给pod
- 启动探针(startupProbe):判断容器内的应用是否启动成功,在检测成功状态为success真会玩,其他的探针都会处于失效状态
2.3 Probe三种检查方式
- exec:通过command设置,执行在容器内执行的linux命令来进行探测,如果返回码为0,则为探测成功,非0就为探测失败
- httpget:通过http get请求访问制定容器端口和url路径,如果访问状态吗为>=200且<=400(2xx 300),则认为探测成功
- tcpsocket:通过制定的端口发送TCP连接,如果端口无误且三次握手成功(TCP连接成功),则认为探测成功
2.4 探测的结果
- 成功:容器通过了诊断。
- 失败:容器未通过诊断。
- 未知:诊断失败,因此不会采取任何行动
2.5 实验部署
2.5.1 exec方式——liveness
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox
imagePullPolicy: IfNotPresent
args: ###启动容器参数
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
livenessProbe: #定义了容器的就绪探针
exec: #在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。
command: #指定了执行的命令
- cat
- /tmp/healthy
failureThreshold: 1 #就绪探针在连续失败一次后被视为失败
initialDelaySeconds: 5 #延迟5秒启动容器
periodSeconds: 5 #每隔5秒探测一次
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
创建一个名为
/tmp/healthy
的文件,暂停执行脚本,等待 30 秒钟,删除后,再次暂停执行脚本,等待额外的 60 秒钟
initialDelaySeconds:指定kubelet在执行第一次探测前应该等待5秒,即第一次探测是在容器启动后的第6秒才开始执行。默认是0秒,最小值是0。
periodSeconds:指定了kubelet应该每5秒执行一次存活探测。默认是10秒。最小值是1。
failureThreshold: 当探测失败时,Kubernetes将在放弃之前重试的次数。 存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃Pod会被打上未就绪的标签。默认值是 3。最小值是1。
timeoutSeconds:探测的超时后等待多少秒。默认值是1秒。最小值是1。(在Kubernetes 1.20版本之前,exec探针会忽略timeoutSeconds探针会无限期地持续运行,甚至可能超过所配置的限期,直到返回结果为止。)总结:可以看到Pod中只有一个容器。kubelet在执行第一次探测前需要等待5秒,kubelet会每5秒执行一次存活探测。kubelet 在容器内执行命令cat /tmp/healthy来进行探测。如果命令执行成功并且返回值为0,kubelet 就会认为这个容器是健康存活的。 当到达第31秒时,这个命令返回非0值,kubelet会杀死这个容器并重新启动它。
探针失败
/tmp/healthy文件不存在,探测失败
2.5.2 httpGet方式
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: soscscs/myapp:v1 #soscscs:nginx1.12
imagePullPolicy: IfNotPresent #拉取策略
ports:
- name: http
containerPort: 80
livenessProbe: #探针
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1 #延迟1秒开始探测
periodSeconds: 3 #每3秒探测一次
timeoutSeconds: 10 #超时时间10秒
删除index.html页面,报错404,探针失败
httpget:通过http get请求访问制定容器端口和url路径,如果访问状态吗为>=200且<=400(2xx 300),则认为探测成功
当我们删除页面后会404报错,然后就会探测失败,最后会重启
2.5.3 tcpSocket方式
apiVersion: v1
kind: Pod
metadata:
name: xzq-tcp-live
spec:
containers:
- name: nginx
image: soscscs/myapp:v1
livenessProbe:
initialDelaySeconds: 5 #第一次探测延迟5秒,第6秒开始
timeoutSeconds: 1
tcpSocket:
port: 8080
periodSeconds: 10 #每10秒探测一次
failureThreshold: 2 #允许2次失败
2.5.4 就绪检测——readiness
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget
namespace: default
spec:
containers:
- name: readiness-httpget-container
image: soscscs/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
port: 80
path: /index1.html
initialDelaySeconds: 1
periodSeconds: 3
livenessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
有实例在运行,但是就绪失败
探针http,404报错
bash可能是权限不足,用sh进入写一个页面
kubectl describe pod readiness-httpget
2.5.5 就绪检测2——readiness
apiVersion: v1
kind: Pod
metadata:
name: myapp1
labels:
app: myapp
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 10
---
apiVersion: v1
kind: Pod
metadata:
name: myapp2
labels:
app: myapp
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 10
---
apiVersion: v1
kind: Pod
metadata:
name: myapp3
labels:
app: myapp
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
查看集群中服务、pod和端点的信息
删除页面看效果,readiness探测失败,Pod无法进入READY状态,且端点控制器将从 endpoints中剔除删除该Pod的IP地址
2.5.6 启动、退出动作
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: soscscs/myapp:v1
lifecycle: #此为关键字段,定义容器的生命周期
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-log #存储卷名字
mountPath: /var/log/nginx/
readOnly: false #可以读和写
initContainers:
- name: init-myservice
image: soscscs/myapp:v1
command: ["/bin/sh", "-c", "echo 'Hello initContainers' >> /var/log/nginx/message"]
volumeMounts:
- name: message-log
mountPath: /var/log/nginx/
readOnly: false
volumes:
- name: message-log
hostPath: #hostPath类型,将存储卷挂载到主机上
path: /data/volumes/nginx/log/ #主机路径
type: DirectoryOrCreate #类型为目录,如无目录,会自动创建
创建后去node01查看日志
进入到日志路径下,日志瞎看到先初始化后才探针
在node01下删除pod
关闭探针=关闭生命周期
cat message