在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
就是这货