资源配额 Resources
在 Kubernetes 中,resources 配置用于设置容器的资源请求和限制,以确保集群中的资源(如 CPU 和内存)得到合理分配和使用。
在之前的pod中,不写 resources 字段。就意味着 Pod 对运行的资源要求“既没有下限,也没有上限”,Kubernetes 不用管 CPU 和内存是否足够,可以把 Pod 调度到任意的节点上,而且后续 Pod 运行时也可以无限制地使用 CPU 和内存。
Pod 可能会因为资源不足而运行缓慢,或者是占用太多资源而影响其他应用,所以我们应当合理评估 Pod 的资源使用情况,尽量为 Pod 加上限制。
Pod 容器的描述部分添加一个新字段 resources 进行资源限额
ngx-pod-resources.yml
apiVersion: v1
kind: Pod
metadata:name: ngx-pod-resourcesspec:containers:- image: nginx:alpinename: ngxresources:requests:cpu: 10mmemory: 100Milimits:cpu: 20mmemory: 200Mi
containers.resources,它下面有两个字段:
- “requests”,意思是容器要申请的资源,也就是说要求 Kubernetes 在创建 Pod 的时候必须分配这里列出的资源,否则容器就无法运行。
- “limits”,意思是容器使用资源的上限,不能超过设定值,否则就有可能被强制停止运行。
cpu 和 memory 资源表达方式
- 内存的写法和磁盘容量一样,使用 Ki、Mi、Gi 来表示 KB、MB、GB,比如 512Ki、100Mi、0.5Gi 等。
- kubernetes 里 CPU 的最小使用单位是 0.001,为了方便表示用了一个特别的单位 m,也就是“milli”“毫”的意思,比如说 500m 就相当于 0.5。
ngx-pod-resources.yml 向系统申请的是 1% 的 CPU 时间和 100MB 的内存,运行时的资源上限是 2%CPU 时间和 200MB 内存。有了这个申请,Kubernetes 就会在集群中查找最符合这个资源要求的节点去运行 Pod。
Kubernetes 会根据每个 Pod 声明的需求,像搭积木或者玩俄罗斯方块一样,把节点尽量“塞满”,充分利用每个节点的资源,让集群的效益最大化。
运行命令
vim ngx-pod-resources.ymlkubectl apply -f ngx-pod-resources.ymlkubectl get pod
如果pod资源配额不够,会是什么情况
修改 ngx-pod-resources.yml cpu为10个cpu
apiVersion: v1
kind: Pod
metadata:name: ngx-pod-resourcesspec:containers:- image: nginx:alpinename: ngxresources:requests:cpu: 10memory: 100Milimits:cpu: 20memory: 200Mi
执行命令
kubectl delete -f ngx-pod-resources.yml
kubectl get pod
vim ngx-pod-resources.yml
kubectl apply -f ngx-pod-resources.yml
kubectl get pod
# 获取pod详情
kubectl describe pod ngx-pod-resources
使用 kubectl apply 创建这个 Pod,你可能会惊奇地发现,虽然我们的 Kubernetes 集群里没有足够的 CPU,但 Pod 也能创建成功。不过我们再用 kubectl get pod 去查看的话,就会发现它处于“Pending”状态,实际上并没有真正被调度运行:
kubectl describe 来查看具体原因,会发现有这么一句提示:
集群中没有足够的可用 CPU 资源来调度新的 Pod,同时有一个节点(master 节点)存在污点 (taint),导致 Pod 无法被调度到该节点上。
检查探针 Probe
探针 Probe
Kubernetes 为了能更细致地监控 Pod 的状态,除了保证崩溃重启,还必须要能够探查到 Pod 的内部运行状态,定时给应用做“体检”,让应用时刻保持“健康”,能够满负荷稳定工作。
Kubernetes 在应用的“检查口”里提取点数据,就可以从这些信息来判断应用是否“健康”了,这项功能被称为“探针”(Probe),也可以叫“探测器”。
探针类型:
- Startup,启动探针,用来检查应用是否已经启动成功,适合那些有大量初始化工作要做,启动很慢的应用。
- Liveness,存活探针,用来检查应用是否正常运行,是否存在死锁、死循环。
- Readiness,就绪探针,用来检查应用是否可以接收流量,是否能够对外提供服务。
三种探针的递进关系:
- 应用程序先启动,加载完配置文件等基本的初始化数据就进入了 Startup 状态
- 之后如果没有什么异常就是 Liveness 存活状态,但可能有一些准备工作没有完成,还不一定能对外提供服务
- 只有到最后的 Readiness 状态才是一个容器最健康可用的状态。
如果一个 Pod 里的容器配置了探针,Kubernetes 在启动容器后就会不断地调用探针来检查容器的状态:
- 如果 Startup 探针失败,Kubernetes 会认为容器没有正常启动,就会尝试反复重启,当然其后面的 Liveness 探针和 Readiness 探针也不会启动。
- 如果 Liveness 探针失败,Kubernetes 就会认为容器发生了异常,也会重启容器。
- 如果 Readiness 探针失败,Kubernetes 会认为容器虽然在运行,但内部有错误,不能正常提供服务,就会把容器从 Service 对象的负载均衡集合中排除,不会给它分配流量。
容器中使用状态探针
开发应用时预留出“检查口
nginx-config-cm.yml
apiVersion: v1
kind: ConfigMap
metadata:name: ngx-confdata:default.conf: |server {listen 80;location = /ready {return 200 'I am ready';}}
执行命令
vim nginx-config-cm.yml
kubectl apply -f nginx-config-cm.yml
Pod 定义探针:
ngx-pod-probe.yml
apiVersion: v1
kind: Pod
metadata:name: ngx-pod-probespec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:alpinename: ngxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-volstartupProbe:periodSeconds: 1exec:command: ["cat", "/var/run/nginx.pid"]livenessProbe:periodSeconds: 10tcpSocket:port: 80readinessProbe:periodSeconds: 5httpGet:path: /readyport: 80
startupProbe、livenessProbe、readinessProbe 这三种探针的配置方式都是一样的,关键字段:
- periodSeconds,执行探测动作的时间间隔,默认是 10 秒探测一次。
- timeoutSeconds,探测动作的超时时间,如果超时就认为探测失败,默认是 1 秒。
- successThreshold,连续几次探测成功才认为是正常,对于 startupProbe 和 livenessProbe 来说它只能是 1。
- failureThreshold,连续探测失败几次才认为是真正发生了异常,默认是 3 次。
Kubernetes 支持 3 种探测方式:Shell、TCP Socket、HTTP GET ,它们也需要在探针里配置:
- exec,执行一个 Linux 命令,比如 ps、cat 等等,和 container 的 command 字段很类似。
- tcpSocket,使用 TCP 协议尝试连接容器的指定端口。
- httpGet,连接端口并发送 HTTP GET 请求。
ngx-pod-probe.yml配置解析
- StartupProbe 使用了 Shell 方式,使用 cat 命令检查 Nginx 存在磁盘上的进程号文件(/var/run/nginx.pid),如果存在就认为是启动成功,它的执行频率是每秒探测一次。
- LivenessProbe 使用了 TCP Socket 方式,尝试连接 Nginx 的 80 端口,每 10 秒探测一次。
- ReadinessProbe 使用的是 HTTP GET 方式,访问容器的 /ready 路径,每 5 秒发一次请求。
执行命令
vim ngx-pod-probe.yml
kubectl apply -f ngx-pod-probe.yml
kubectl get pod
kubectl logs ngx-pod-probe
Kubernetes ReadinessProbe 探针以大约 5 秒一次的频率,向 URI /ready 发送 HTTP 请求,不断地检查容器是否处于就绪状态。
验证StartupProbe 探针失败情况
修改ngx-pod-probe.yml的startupProbe
startupProbe:exec:command: ["cat", "nginx.pid"] #错误的文件
执行命令
kubectl delete -f ngx-pod-probe.yml
kubectl get pod
vim ngx-pod-probe.yml
kubectl apply -f ngx-pod-probe.yml
kubectl get pod
kubectl logs ngx-pod-probe
当 StartupProbe 探测失败的时候,Kubernetes 就会不停地重启容器,现象就是 RESTARTS 次数不停地增加,而 livenessProbe 和 readinessProbePod 没有执行,Pod 永远不会 READY。
修改ngx-pod-probe.yml的livenessProbe(startupProbe内容要还原)
livenessProbe:tcpSocket:port: 8080 #错误的端口号
执行命令
kubectl delete -f ngx-pod-probe.yml
kubectl get pod
vim ngx-pod-probe.yml
kubectl apply -f ngx-pod-probe.yml
kubectl get pod
kubectl logs ngx-pod-probe
因为 failureThreshold 的次数默认是三次,所以 Kubernetes 会连续执行三次 livenessProbe TCP Socket 探测,每次间隔 10 秒,30 秒之后都失败才重启容器。