为Kubelet预留资源

在kubernetes集群运行过程中,kubelet需要定时向 API Server 发送心跳,报告运行状态

此处实际上存在很大的安全隐患

因为在节点上, Kubelet 和 节点上运行的Pods 需要共享 CPU 和 RAM 资源,这就导致在极端情况下,Kubelet 可能无法得到足够的资源来运行自己

也就是说 Pods 很可能 消耗掉全部的节点物理资源,导致 节点心跳停止 或 报告不及时,API Server 可能会错误的认为,这个节点已经离线

理想主义的状态下,部署到这个节点上的所有Pod,不应该消耗100%的物理资源

例如

100m cpu * 9 ,这样理论上 会剩余 100m

但是由于集群环境极为复杂,而且无法保证调度器会为每个节点预留资源,而且更无法保证每个有权限的操作人员都会留意到这个问题

所以经常会有资源超载的情况,导致kubelet心跳停止

解决办法非常的简单粗暴

部署一个 “占位” 应用,并且分配它的 requests cpu 资源为 100m

这个占位应用(比如Nginx)因为没有具体应用,所以不会真的消耗cpu

这里requests属于好控制的

1000m的 单核可以支持

100m * 9 的正常应用,100m * 1 的占位Nginx,

不过requests只影响 容器调度 和 cpu竞争,无法保证 cpu 资源不被耗尽

把limits也设置成

100m * 9 应用,100m * 1 占位Nginx,这回好了,不过limits是可以超卖的,所以也无法保证所有管理员都给你留出那 100m

结论,

最好是只使用 limits,这样可以保证 requests 默认和 limits保持一致

因为requests无法超卖,所以有Nginx 占位 100m的情况下,那 9 个 只写了limits的正常应用,就不能超过900m了

以上是一种偏方来处理这个问题,那kubernetes原生应用有处理这个问题么

答案是 有,但是麻烦

  • --kube-reserved,用于配置为kube组件(kubelet,kube-proxy,dockerd等)预留的资源量,比如--kube-reserved=cpu=1000m,memory=8Gi,ephemeral-storage=16Gi
  • --kube-reserved-cgroup,如果你设置了--kube-reserved,那么一定要设置对应的cgroup,并且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为kube-reserved-cgroup=/kubelet.service 。如果不设置此项,上面的--kube-reserved也不会生效。
  • --system-reserved,用于配置为System进程预留的资源量,比如--system-reserved=cpu=500m,memory=4Gi,ephemeral-storage=4Gi
  • --system-reserved-cgroup,如果你设置了--system-reserved,那么一定要设置对应的cgroup,并且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为system-reserved-cgroup=/system.slice。如果不设置此项的话,上面的--system-reserved也不会生效。

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStartPre=-/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service /sys/fs/cgroup/hugetlb/system.slice/kubelet.service
ExecStart=/opt/kubernetes/bin/kubelet \
  --eviction-hard=memory.available<1024Mi,nodefs.available<10%,nodefs.inodesFree<5% \
  --system-reserved=cpu=0.5,memory=1G \
  --kube-reserved=cpu=0.5,memory=1G \
  --kube-reserved-cgroup=/system.slice/kubelet.service \
  --system-reserved-cgroup=/system.slice \
  --enforce-node-allocatable=pods,kube-reserved,system-reserved \
  --address=192.168.0.101 \
  --hostname-override=192.168.0.101 \
  --cgroup-driver=cgroupfs \
  --pod-infra-container-image=hub.breezey.top/kubernetes/pause-amd64:3.0 \
  --experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \
  --kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \
  --cert-dir=/opt/kubernetes/ssl \
  --cluster-dns=192.168.0.200 \
  --cluster-domain=k8s.breezey.top. \
  --hairpin-mode=promiscuous-bridge \
  --allow-privileged=true \
  --fail-swap-on=false \
  --serialize-image-pulls=false \
  --max-pods=60 \
  --logtostderr=true \
  --v=2 
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

而且很遗憾,在rke安装的kubernetes集群中

并没有使用这种方式

默认是没有kubelet.service的

需要手动添加

再通过参数指定

rke默认情况下安装的kubernetes

kubelet 进程使用的 cgroup 是这样的

6:cpu,cpuacct:/docker/4b28805380958bf3efb5c0d0a9c93ba42fab4d36e1be9036f3b9c4b01ef3bd62

就是这货

Send a Message