在ACK集群中配置工作负载(Deployment、StatefulSet、DaemonSet、Job、CronJob等)时,您需考虑多种因素,以确保应用可以稳定、可靠地运行。
声明每个Pod的Requests和Limits
在 Kubernetes 集群中,节点上调度过多 Pod 会导致负载过高,无法正常提供服务。配置Pod时,建议声明其所需的requests和limits,以便集群在部署Pod时可以根据资源需求找到合适的节点。
下方示例中,Nginx Pod的资源配置为:
CPU请求:1核;内存请求:1024Mi
CPU限制:2核;内存限制:4096Mi
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
resources: # 资源声明
requests:
memory: "1024Mi"
cpu: "1000m"
limits:
memory: "4096Mi"
cpu: "2000m"Kubernetes采用静态资源调度机制。每个节点的剩余资源的计算公式为节点剩余资源 = 节点总资源 - 已分配资源。手动运行资源密集型程序时,Kubernetes无法感知其实际资源使用量。因此公式中基于已分配资源进行计算,而非实际使用资源。
此外,所有Pod都应声明resources。如果Pod未声明resources,调度到节点后,Kubernetes不会为其预留资源。这可能导致节点上调度过多Pod,进而引发资源争用问题。
推荐使用ACK提供的资源画像功能,基于资源使用量的历史数据获得容器粒度的资源规格推荐,简化容器requests和limits的配置复杂度。
启动时等待下游服务,不要直接退出
有些应用可能存在一些外部依赖,例如需要从数据库(DB)读取数据或者依赖另外一个服务的接口。应用启动时,外部依赖可能无法完全满足。在传统手动运维中,通常采用“依赖不满足即退出”的方式(即failfast)。但在Kubernetes中,大多运维操作是自动化的,无需人工干预。例如部署应用时系统会自动选择节点并启动应用,应用失败时系统会自动重启,负载增加时可以通过HPA(Horizontal Pod Autoscaler)实现自动扩容。
假设有两个应用A和B,A依赖B,并且它们运行在同一节点上。如果该节点因某种原因重启,重启后A先启动,而B尚未启动,此时A的依赖无法满足。如果A按照传统方式直接退出,即使B启动后,A也不会自动恢复,需要人工干预。
在Kubernetes集群中,建议在启动时检查依赖。如果依赖不满足,可以通过轮询等待,而不是直接退出。这一功能可以通过Init Container实现。
配置restart policy
Pod 运行期间,进程退出是一种常见现象。代码缺陷或内存占用过多等问题都可能导致应用程序进程退出,从而导致 Pod 终止。您可以为 Pod 配置restartPolicy,确保在 Pod 退出后能够自动重启。`
apiVersion: v1
kind: Pod
metadata:
name: nginx-test
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6restartPolicy可选值如下:
Always:总是自动重启。OnFailure:异常退出时自动重启(进程退出状态非0)。Never:从不重启。
配置健康检查探针
为应对应用死锁、启动缓慢或服务失效等异常,配置探针赋予了 Kubernetes 故障自愈与流量管控能力。它能自动重启异常容器并仅向就绪实例分发请求,是保障服务高可用性与稳定性的关键机制。
startupProbe(启动探针):用于启动较慢的应用(如Java)检测是否完成启动。启动探测成功前,就绪探针和存活探针不会被执行,防止应用启动缓慢而被Kubelet误判为失败并重启。readinessProbe(就绪探针):用于业务流量控制,仅当检测通过后才将 Pod IP 加入 Service 的 Endpoints 列表,确保外部请求只分发给具备处理能力的容器。livenessProbe(存活探针):负责监测容器的存活状态,在检测到死锁或崩溃时由 kubelet 触发自动重启以实现故障自愈。
以下为一个Nginx无状态(Deployment)应用配置健康检查探针的参考示例。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-demo
spec:
replicas: 1 # 生产环境建议配置2以上保证高可用
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
ports:
- containerPort: 80
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 500m
# --- 健康检查探针 ---
# 启动探针 (Startup Probe): 确保容器内应用已完成启动
startupProbe:
httpGet:
path: / # Nginx默认根路径可访问即代表启动成功
port: 80
# 给予应用足够长的启动时间。总超时 = failureThreshold * periodSeconds,即 30 * 10 = 300 秒
failureThreshold: 30
periodSeconds: 10
# 就绪探针 (Readiness Probe): 判断容器是否准备好接收流量
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5 # 容器启动后5秒开始探测
periodSeconds: 5 # 每5秒探测一次
timeoutSeconds: 2 # 探测超时时间
successThreshold: 1 # 1次成功即标记为就绪
failureThreshold: 3 # 连续3次失败即标记为不就绪
# 存活探针 (Liveness Probe): 判断容器是否“存活”,用于实现故障自愈。
# 此配置应比readinessProbe更宽松,以避免因短暂抖动导致不必要的重启。
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15 # 在容器启动15秒后开始第一次探测,给予应用充分的初始化后稳定时间。
periodSeconds: 10 # 探测频率低于readinessProbe,以减少对系统资源的消耗。
timeoutSeconds: 3 # 超时时间可略长于readinessProbe。
successThreshold: 1 # 1次成功即代表存活。
failureThreshold: 3 # 连续3次失败(3*10=30秒)后,Kubelet将重启该容器。如需在生产环境配置零中断滚动部署,请参考实现零中断滚动部署。
每个进程一个容器
部分开发者习惯将容器当作虚拟机(VM)使用,并在一个容器中运行多个进程,例如监控进程、日志进程、sshd 进程,甚至整个 Systemd。这种做法会带来以下问题:
判断 Pod 的整体资源占用会更加复杂,也不利于正确配置 Requests 和 Limits。
如果容器内仅运行单个进程,当该进程中断时,外部容器引擎能够立即感知并重启容器。若容器内运行多个进程,即使其中一个进程崩溃,外部容器引擎也无法感知,可能导致容器无法正常工作。
Kubernetes支持多个进程的协同工作。例如,Nginx 和 PHP-FPM 可通过 Unix Domain Socket 通信,您可创建一个包含2个容器的 Pod,并将 Unix Domain Socket 存放于两者的共享 Volume 中。
确保不存在单点故障(Single Point of Failure)
如果应用仅有一个实例,当该实例发生故障时,尽管 Kubernetes 能够自动重启实例,但在这期间不可避免地会出现短暂的服务中断。即使在更新应用或发布新版本时,也可能出现类似的服务中断情况。
在 Kubernetes 中,应尽量避免直接管理 Pod,而是通过 Deployment 或 StatefulSet 来管理,并确保应用至少运行两个以上的 Pod 实例。这种做法能够有效提升系统的高可用性,避免因单个实例故障导致的服务中断。