配额
相关概念
request与limits
Kubernetes采用request和limit两种限制类型来对资源进行分配
- request(资源需求):即运行- Pod的节点必须满足运行- Pod的最基本需求才能运行- Pod
- limits(资源限额):描述- Pod运行期间,内存最大可申请大小
一个容器申请0.5个CPU,就相当于申请1个CPU的一半,加个后缀m表示千分之一的概念。
比如说100m的CPU,表示0.1个cpu
配额与
Pod优先级关系
- Request=Limit:- Pod类型为- Guaranted(保证型),只有内存使用量超限(OOM)时才会被- kill
- Request<Limit:- Pod类型为- Burstable(突发流量型),节点计算资源不足时,可能会被- kill回收
- 未设置Request Limit:Pod类型为Best Effort(尽最大努力型),节点计算资源不足时,会被首先kill
配额限制维度
节点级计算资源限制
- Kubelet Node Allocatable用来为- Kube组件和- System进程预留资源, 从而保证当节点出现满负荷时也能保证- k8s系统服务和- System宿主机守护进程有足够的资源
- Node Capacity:- Node的所有硬件资源
- kube-reserved:- kube组件预留的资源
- system-reserved:- System进程预留的资源
- eviction-threshold(阈值):- kubelet eviction(回收)的阈值设定
- allocatable: 真正- scheduler调度- Pod时的参考值(保证- Node上所有- Pods的- request resource不超过- Allocatable)
查看当前节点的
Capacity和Allocatable
[root@node1 ~]# kubectl describe node node1
...
Capacity:
  cpu:                4
  ephemeral-storage:  17394Mi
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             4004944Ki
  pods:               300
Allocatable:
  cpu:                3600m
  ephemeral-storage:  17394Mi
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             3371721521
  pods:               300
  ...
查看
docker驱动
cgroup驱动如果为systemd,则开启不了Kubelet Node Allocatable
[root@node1 ~]# docker info | grep "Cgroup Driver"
 Cgroup Driver: systemd
调整
docker驱动为cgroupfs
调整/etc/docker/daemon.json内容,添加/修改以下值(需升级内核)
"exec-opts": ["native.cgroupdriver=cgroupfs"]
重启docker
systemctl daemon-reload
systemctl restart docker
调整
kubelet参数配置
修改/var/lib/kubelet/kubeadm-flags.env,调整/增加以下参数:
# 修改`kubelet cgroup`驱动`systemd`为`cgroupfs`
--cgroup-driver=cgroupfs
# 开启为kube组件和系统守护进程预留资源的功能
--enforce-node-allocatable=pods,kube-reserved,system-reserved
# 设置k8s组件的cgroup
--kube-reserved-cgroup=/system.slice/kubelet.service
# 设置系统守护进程的cgroup
--system-reserved-cgroup=/system.slice
# 配置为k8s组件预留资源的大小,CPU、MEM
--kube-reserved=cpu=1,memory=1Gi
# 配置为系统进程(诸如 sshd、udev 等系统守护进程)预留资源的大小,CPU、MEM
--system-reserved=cpu=0.5,memory=1Gi
# 驱逐pod的配置:硬阈值(保证95%的内存利用率)
--eviction-hard=memory.available<5%,nodefs.available<10%,imagefs.available<10%
# 驱逐pod的配置:软阈值
--eviction-soft=memory.available<10%,nodefs.available<15%,imagefs.available<15%
# 定义达到软阈值之后,持续时间超过多久才进行驱逐
--eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m
# 驱逐pod前最大等待时间=min(pod.Spec.TerminationGracePeriodSeconds, eviction-max-pod-grace-period),单位秒
--eviction-max-pod-grace-period=30
# 至少回收多少资源,才停止驱逐
--eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=500Mi,imagefs.available=500Mi
调整
kubelet.service
调整文件/etc/systemd/system/kubelet.service
修改前
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
ExecStart=/usr/local/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
修改后
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/hugetlb/system.slice/kubelet.service
ExecStart=/usr/local/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
重启
kubelet再次查看节点的Capacity和Allocatable
[root@node1 ~]# systemctl daemon-reload
[root@node1 ~]# systemctl restart kubelet
[root@node1 ~]# kubectl describe node node1
...
Capacity:
  cpu:                4
  ephemeral-storage:  17394Mi
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             4004944Ki
  pods:               300
Allocatable:
  cpu:                2500m
  ephemeral-storage:  14267554175
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             1748525873
  pods:               300
...
官方的样例说明
这是一个用于说明节点可分配(Node Allocatable)计算方式的示例:
- 节点拥有32Gi memeory,16 CPU和100Gi Storage资源:- --kube-reserved被设置为- cpu=1,memory=2Gi,ephemeral-storage=1Gi
- --system-reserved被设置为- cpu=500m,memory=1Gi,ephemeral-storage=1Gi
- --eviction-hard被设置为- memory.available<500Mi,nodefs.available<10%
 
在这个场景下,Allocatable将会是14.5 CPUs、28.5Gi内存以及88Gi本地存储。 调度器保证这个节点上的所有Pod的内存requests总量不超过28.5Gi,存储不超过88Gi。 
当Pod的内存使用总量超过28.5Gi或者磁盘使用总量超过88Gi时, kubelet将会驱逐它们。
如果节点上的所有进程都尽可能多地使用CPU,则Pod加起来不能使用超过14.5 CPUs的资源。
当没有执行kube-reserved和/或system-reserved策略且系统守护进程 使用量超过其预留时,
如果节点内存用量高于31.5Gi或存储大于90Gi,kubelet将会驱逐Pod
命名空间级计算资源限制
设置限定对象数据的资源配额
指定命名空间test01生效
cat <<EOF | kubectl -n test01 apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
spec:
  hard:
    persistentvolumeclaims: "2" # 持久存储卷
    services.loadbalancers: "2" # 负载均衡器
    services.nodeports: "0" # NodePort 数量
EOF
设置限定计算资源配额限制
指定命名空间test01生效
cat <<EOF | kubectl -n test01 apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources
spec:
  hard:
    pods: "4"
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
EOF
命名空间容器默认配额设置
缺省值
创建测试命名空间
kubectl create ns test01
创建命名空间容器默认配额设置
cat <<EOF | kubectl -n test01 apply -f -
apiVersion: v1 
kind: LimitRange 
metadata:  
  name: limitrange-memory 
spec:  
  limits:  
  - default:
      memory: 512Mi # default limit
    defaultRequest:  
      memory: 256Mi # default request  
    max:      
      memory: 1Gi   # max limit
    min:      
      memory: 100Mi # min request   
    type: Container
EOF
- 容器如果未声明request与limits-> 会根据命名空间下LimitRange策略对容器配额赋值
- 容器如果声明limits未声明request-> 则容器的内存request和limits值一致
- 容器如果声明request,未声明limits-> 容器request值被设置为声明的值,limits被设置成了LimitRange值
容器级计算资源限制
针对业务容器设置配额
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64M"
        cpu: "0.25"
      limits:
        memory: "128M"
        cpu: "0.5"