生命周期与资源管理
#### 一、Pod生命周期
##### 生命周期
表示Pod对象从创建直至终止的时间范围,这段范围用于运行复杂的逻辑如启动顺序、依赖关系、生成配置、数据预加载、检测、安装等
初始化容器:initContainer
容器探针:
生命探测:livenessProbe
就绪探测:readinessProbe
启动探测:startupProbe
事件处理函数:
启动后回调:PostStart
结束前回调:PreStop

```yaml
# 测试初始化容器
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
restartPolicy: OnFailure # Always选项对初始化容器无效
initContainers: # never失败不重启,会导致主容器永远不启动
- name: inithttp1 # 初始化任务失败,主容器不会启动
image: myos:8.5
command: [sh]
args:
- -c
- |
ID=${RANDOM}
echo "${RANDOM}"
sleep 3
exit $((ID%2))
- name: inithttp2 # 可以定义多个初始化容器
image: myos:latest # 初始化容器可以使用不容镜像
command: [sh]
args:
- -c
- |
ID=${RANDOM}
echo "${RANDOM}"
sleep 3
exit $((ID%2)) # 状态非零表示失败,会重新执行初始化
containers:
- name: http
image: myos:httpd
```
```shell
# 验证初始化容器执行
kubectl replace --force -f web1.yaml
# 查看细节
kubectl get pods -w
kubectl logs apache -c inithttp1
kubectl logs apache -c inithttp2
# 验证主容器重启,初始化容器不执行
kubectl exec -it http -- bash
```
##### 容器探针
###### 启动探针
启动探针在主容器中运行,不同于初始化必须在一个独立的容器中运行。若容器启动失败探针通知Pod重启容器。用于保护启动慢的容器,比如java需要先编译后运行
```yaml
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: http
image: myos:httpd
startupProbe: # 启动探针
initialDelaySeconds: 30 # 首次检查延时
failureThreshold: 3 # 可失败的次数
periodSeconds: 10 # 检查间隔
tcpSocket: # 使用 tcp 协议检测
port: 80 # 端口号
```
```shell
# 查看测试容器状态
kubectl apply -f web2.yaml
kubectl get pods -w
# 查看帮助,获取字段说明
kubectl get pods apache -o jsonpath='{.spec.containers[*].startupProbe}' | python3 -m json.tool
```
###### 生命探针
默认探测器只会检测pid为1的进程,而生命探针会探测容器中某个核心资源是否可用,“核心资源”通常指容器内**维持应用正常运行的关键依赖**,具体包括进程状态、文件存在、服务连通、内部依赖等等。
```yaml
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: http
image: myos:httpd
startupProbe:
initialDelaySeconds: 30
failureThreshold: 3
periodSeconds: 10
tcpSocket:
port: 80
livenessProbe: # 定义存活探针
timeoutSeconds: 3 # 服务影响超时
httpGet: # 使用 HTTP 协议检测
path: /info.php # 请求的 URL 路径
port: 80 # 服务端口号
```
```shell
# 测试
kubectl apply -f web2.yaml
kubectl exec -it apache -- bash
在容器中包含index.html和info.php
# 测试删除静态资源index.html,容器不会重启
# 测试删除动态资源info.php,容器重启
```
###### 就绪探针
就绪探针用于确定容器是否已准备好**接收外部流量**,如果就绪探针失败,Kubernetes 会将该 Pod 从 Service 的 Endpoints 列表中移除,**停止向其发送流量**,但不同于生命探针的是就绪探针不会重建容器
```yaml
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: http
image: myos:httpd
startupProbe:
initialDelaySeconds: 30
failureThreshold: 3
periodSeconds: 10
tcpSocket:
port: 80
livenessProbe:
timeoutSeconds: 3
httpGet:
path: /info.php
port: 80
readinessProbe: # 定义就绪探针
failureThreshold: 3 # 失败确认次数
periodSeconds: 5 # 检测间隔
exec: # 执行命令进行检测
command: # 检测命令
- sh
- -c
- |
read ver < /var/www/html/version.txt
if (( ${ver:-0} > 2 ));then
res=0
fi
exit ${res:-1} # 版本大于 2 成功,否则失败
```
```shell
# 测试
kubectl apply -f web2.yaml
kubectl exec -it apache -- bash
# 容器内测试成功结果
echo 3 > /var/www/html/version.txt
# 容器外测试状态
kubectl get pods -w
# 测试失败结果
echo 1 > /var/www/html/version.txt
# 容器外查看状态
kubectl get pods -w
```
##### 事件处理函数
###### 启动回调与结束回调
```yaml
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: web
image: myos:httpd
lifecycle: # 定义启动后事件处理函数
postStart:
exec:
command:
- sh
- -c
- |
echo "start server" | tee -a /tmp/web.log
sleep 10
preStop: # 定义关闭前事件处理函数
exec:
command:
- sh
- -c
- |
echo "stop server" | tee -a /tmp/web.log
sleep 10
```
```shell
# 测试返回结果
kubectl apply -f web3.yaml
# 进入容器查看日志结果
kubectl exec -it apache -- bash
cat /tmp/web.log
# 容器外结束容器
kubectl delete pods web3
# 在容器退出的宽限期内查看结果
cat /tmp/web.log
```
#### 二、资源的配额与限额
##### 资源配额
保护pod
```yaml
# 配额测试
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: web3
image: myos:httpd
resources: # 配置资源策略
requests: # 配额策略
cpu: 1500m # 计算资源配额
memory: 800Mi # 内存资源配额
```
###### 验证资源配额
```shell
## 验证创建4个pods
for i in {1..4}
do
sed "s,apache,apache$i," application.yml | kubectl apply -f -
done
# 查看pod状态,虽然4个pod都能创建成功但pod3与pods4处于pending状态
kubectl get pods
-------------------------------------------------------
# 占用CPU资源
curl http://10.244.1.10/info.php?id=5000000
# 占用内存资源
memtest.py 500
```
##### 资源限额
限制pod
```yaml
# 调整资源限额
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: web3
image: myos:httpd
resources: # 配置资源策略
limits: # 限额策略
cpu: 500m # 计算资源限额
memory: 800Mi # 内存资源限额
```
###### 验证资源限额
```shell
## 验证限额,当前pod:cpu限额500m,内存限额800Mi
# 将文件传给容器并添加执行权限用于测试
kubectl cp memtest.py apache:/usr/bin/
chmod +x /usr/bin/memtest.py
# 验证多端同时申请占用内存资源测试限额度
memtest.py 500
# 两个端口总计需要占用1024Mi内存,超出总共提供800Mi,系统会随机杀死一个端口申请的进程
# 验证大量连续访问容器服务,占用cpu资源测试限额度
curl http://10.244.21.160/info.php?id=5000000 &
curl http://10.244.21.160/info.php?id=5000000 &
curl http://10.244.21.160/info.php?id=5000000 &
# 容器查看信息
kubectl top pods apache
-------------------------------------------------------
# 占用CPU资源
curl http://10.244.1.10/info.php?id=5000000
# 占用内存资源
memtest.py 500
```
#### 三、Pod 服务质量与Quota 资源管理的配额
##### 服务质量
为了防止资源饥饿,kubelet可以回收一个或多个pods的资源。在节点压力驱逐期间,kubelet会将Pod状态设置为Failed并终止其运行
三种QoS类别:
Guaranteed类型:这类Pod有稳定的资源配额/限额,被当作驱逐目标的概率很小
当资源配额**等于**资源限额时,Pod属于Cuaranteed类型
Burstable类型:该类Pod使用资源在有限制的范围内波动,节点资源不足时会被驱逐
当资源配额**小于**资源限额,则Pod属于Burstable类型
BestEffort类型:没有明确的资源使用量,是首选被驱逐的对象
当一个Pod没有设置资源配额和资源限额,属于BestEffort类型
```yaml
---
kind: Pod
apiVersion: v1
metadata:
name: apache
spec:
containers:
- name: web3
image: myos:httpd
# ↑BestEffort型--------------------------------------------------------
resources:
requests:
cpu: 500m
memory: 800Mi
# ↑Burstable型--------------------------------------------------------
limits:
cpu: 500m
memory: 800Mi
# ↑Guaranteed型--------------------------------------------------------
```
###### 验证QoS
```shell
# 验证BestEffort型
vim application.yml
kubectl apply -f application.yml
kubectl describe pods apache | grep QoS
# 验证Burstable型
vim application.yml
kubectl replace --force -f application.yml
kubectl describe pods apache | grep QoS
# 验证Guaranteed型
vim application.yml
kubectl replace --force -f application.yml
kubectl describe pods apache | grep QoS
```
##### 设置全局资源配额
**全局资源配额(Resource Quota)**需要创建ResourceQuota对象,并绑定到特定的命名空间(Namespace)
资源单位格式:
CPU:1 = 1核,500m = 0.5核
内存:1G = 1000M,1Gi = 1024Mi
```shell
# 快速生成quota的1号测试模板
kubectl create quota my-quota-1 --namespace=testns --hard=pods=3 --scopes=BestEffort --dry-run=client -o yaml > quota.yml
# 参数说明
--hard: 指定资源限制(如 cpu=10,memory=20Gi,pods=100)
--dry-run=client: 仅生成模板,不实际创建
-o yaml: 输出YAML格式
# 创建名称空间以及更新配额策略quota
kubectl create namespace testns
kubectl apply -f quota.yml
# 查看当前quota状态
kubectl describe namespaces testns
# 使用BestEffort型,测试创建多个pods后查看配额信息
for i in {1..4}
do
sed 's,apache,apache$i,' application.yml | kubectl -n testns apply -f - # 第4个创建失败,因为scopes只有3个限制
done
kubectl describe namespaces testns
```
生成测试模板
```yaml
---
apiVersion: v1
kind: ResourceQuota # 全局资源限额对象
metadata:
creationTimestamp: null # 记录资源的创建时间
name: my-quota-1 # 规则名称
namespace: testns # 规则作用的名称空间
spec: # 定义ResourceQuota.spes
hard: # 创建强制规则
pods: "3" # 限制创建资源对象总量
scopes: # 配置服务质量类型
- BestEffort # Pod QoS类型
status: {}
```
##### 设置服务质量配额
通过资源与数量双重配额,限制手段更灵活
```shell
# 生成2号测试模板
kubectl create quota my-quota-2 \
--namespace=testns \
--hard=cpu=2300m,memory=1500M,pods=10 \
--scopes=NotBestEffort \
--dry-run=client -o yaml >> quota.yml
# 名称空间已存在不用创建,但要清空名称空间的测试pods以及重新更新配额策略quota
kubectl -n testns delete pods --all
kubectl replace --force -f quota.yml
# 查看当前quota状态
kubectl describe namespaces testns
# 使用Guaranteed型并且cpu和内存的开支只设置200,测试创建多个pods后查看配额信息
for i in {1..10}
do
sed 's,apache,apache'$i',' application.yml | kubectl -n testns apply -f - # 第8个开始创建失败,因为内存只设置了1500M,7×200+200>1500
done
kubectl describe namespaces testns
# 若把quota内存限制修改至2G将会从第11个开始创建失败,三重限制cpu、内存、数量都达到上限
```
生成测试模板
```yaml
---
apiVersion: v1
kind: ResourceQuota
metadata:
creationTimestamp: null # 记录资源的创建时间
name: my-quota-2 # 创建名称不能使用下划线"_",无法创建会报错
namespace: testns
spec:
hard:
cpu: 2300m # 计算资源配额
memory: 1500M # 内存资源配额
pods: "10" # 限制创建资源对象总量
scopes:
- NotBestEffort
status: {}
```
---------------------------
```shell
# 清理实验配置环境
kubectl -n testns delete pods --all
kubectl delete namespace testns
```
620

被折叠的 条评论
为什么被折叠?



