K8S 运维管理

Node 管理

Node是K8S中负责运行业务的计算节点,常见的操作有:1)将一个新的Node加入到集群,2)对某个存在的Node进行升级维护(扩大内存,增加磁盘,升级OS,重启等),3)将一个不再使用的Node从集群中删除。

  • join

在新的Node上安装完kubeadm,kubelet,containerd等以后,可以在新Node上执行 kubeadm join将该Node加入到集群。执行以下命令,可以打印出加入集群的命令,kubeadm token create --print-join-command

  • taint

对某个Node打上taint标记,K8S不会将新的Pod调度到有taint的Node上,除非这个Pod标记了可以容忍这个taint,taint是Key-Value的定义形式。

  • cordon

将某个Node标记为不可调度(SchedulingDisable),这样任何Pod都不会被调度到此Node上。

  • uncordon

恢复对某个Node的调度。

  • drain

将某个Node标记为不可调度,同驱逐其上面的Pod到其它Node。一般在需要对该Node进行维护时使用。

  • delete

删除某个Node,将其从K8S集群中移除。

cordon、drain和delete三个命令都会使node停止被调度,后期创建的pod不会继续被调度到该节点上,但操作的暴力程度却不一样。

cordon 停止调度(不可调度,临时从K8S集群隔离)。影响最小,只会将node标识为SchedulingDisabled不可调度状态。之后K8S再创建的pod资源,不会被调度到该节点,但旧有的pod不会受到影响,仍正常对外提供服务。

drain 驱逐节点(先不可调度,然后排干)。首先,驱逐Node上的pod资源到其他节点重新创建。接着,将节点调为SchedulingDisabled不可调度状态。drain方式是安全驱逐pod,会等到pod容器应用程序优雅停止后再删除该pod。drain驱逐流程:先在Node节点删除pod,然后再在其他Node节点创建该pod。

delete 删除节点。delete是一种暴力删除node的方式。在驱逐pod时是强制干掉容器进程,做不到优雅终止Pod。相比较而言,显然drain更安全。

集群环境共享与隔离

K8S集群可以被多个租户使用,不同的租户具备相应的权限,同时,不同租户在K8S中创建的资源是被隔离的,胡不影响。

K8S中通过Namespace和Context能够实现多租户管理以及资源的隔离,不同的租户操作的都是自己Namespace中的资源。通过可以对ServiceAccount进行RBAC授权管理,使用某个租户只具备某些权限,例如只能查看Pod,Service而不能创建Pod或Service。

容器资源限制

在创建Pod时,可以通过指定requests和limits来限定Pod中容器对CPU和内存的申请数量以及上限数量。K8S只会将Pod调度到满足此要求的Node上,如果没有任何Node满足此要求,则Pod会调度失败。

如果每个Pod都手动增加requests和limits限制,操作比较繁琐,可以在Namespace上创建LimitRange来设定默认的requests和默认的limits。

服务质量管理(QoS)

服务质量包含三个层级,BestEffort,Burstable和Guaranteed,服务等级依次增高。如果Node资源不足,K8S会优先kill掉低服务等级的Pod,从而为高等级的Pod腾出资源。

Guaranteed:1)Pod中的每个容器都定义了requests和limits,且对应的值一样(需要同时定义CPU和内存限制)。2)Pod中每个容器都定义了limits。默认requests和limits的值一样,所以可以只定义limits。是*别的 QoS 级别,它可以保证在任何情况下资源需求得到满足。当一个 Pod 被划分到这种 QoS 级别时,它会在可用资源范围内得到最大比例的资源分配。这种 QoS 级别通常用于需要高可靠性和高可用性的任务,比如数据库、关键业务等。

Burstable:1)虽然Pod中的每个容器都定义了requests和limits,但其值不一样。2)一个容器定义了资源配置,而另一个没有定义。3)一个容器没定义CPU限制,另一个容器没定义内存限制。是中级 QoS 级别,它可以保证在特定情况下资源需求得到满足。当一个 Pod 被划分到这种 QoS 级别时,它会在可用资源范围内得到一定比例的资源分配。Kubernetes 调度器会为这类 Pod 分配足够的资源,以满足它们的需求。这种 QoS 级别通常用于一些非关键任务,比如网页浏览、电子邮件发送等。

BestEffort:Pod中的每个容器都没有定义requests和limits,就是BestEffort。是一种最低优先级,主要用于无法保证服务的资源请求,比如不消耗任何资源,没有任何网络延迟,它适用于一切不可用的情况。Pod 被划分为这种 QoS 级别,通常是由于它的服务类型,比如备份任务、流量转向等。这类 Pod 不受 Kubernetes 调度器约束,可能会在资源空闲时被调度到节点上。

下面示例三种不同QoS的Pod,

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
  namespace: qos-example
spec:
  containers:
  - name: guaranteed
    image: nginx
    resources:
      requests:
        memory: "100Mi"
        cpu: "200m"
      limits:
        memory: "100Mi"
        cpu: "200m"
---
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
  namespace: qos-example
spec:
  containers:
  - name: burstable
    image: nginx
    resources:
      requests:
        memory: "50Mi"
        cpu: "100m"
---
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
  namespace: qos-example
spec:
  containers:
  - name: best-effort
    image: nginx

资源配额管理 (Quotas)

虽然通过limits和requests可以限制每个Pod的资源使用情况,但是其无法限制某个Namespace中所有Pod的资源使用总和,资源配额管理(Quotas)可以满足此需求。其对某个Namespace中的CPU request,CPU limit,Memory request,Memory limit,Pod,Storage等总的数量进行限制,以免该Namespace中的这些配额超标。
同时,可以通过scopes来指定Quotas限定的QoS的作用域,例如,只针对BestEffort或者Burstable的Pod进行限制。

以下是Quotas示例,

1)限制CPU和内存总量

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-demo
spec:
  hard:
    limits.cpu: '6'        #所有非终止状态的 Pod,其 CPU 限额总量不能超过该值。
    limits.memory: '20Gi'  #所有非终止状态的 Pod,其内存限额总量不能超过该值。
    requests.cpu: '4'        #所有非终止状态的 Pod,其 CPU 需求总量不能超过该值。
    requests.memory: '15Gi'  #所有非终止状态的 Pod,其内存需求总量不能超过该值。

2)限制存储使用总量 

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-sc-demo
spec:
  hard:
    requests.storage: "20Gi"     #所有 PVC,存储资源的需求总量不能超过该值。
    persistentvolumeclaims: "50Gi"  #在该命名空间中所允许的 PVC 总量。
    local-path.storageclass.storage.k8s.io/requests.storage: "10Gi"  #在所有与 <storage-class-name> 相关的持久卷申领中,存储请求的总和不能超过该值 。
    local-path.storageclass.storage.k8s.io/persistentvolumeclaims: 3  #在与 storage-class-name 相关的所有持久卷申领中,命名空间中可以存在的持久卷申领总数

3)限制对象数量 

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-count-demo
spec:
  hard:
    configmaps: 10  #在该命名空间中允许存在的 ConfigMap 总数上限。
    persistentvolumeclaims: 5  #在该命名空间中允许存在的 PVC 的总数上限。
    pods: 15    #在该命名空间中允许存在的非终止状态的 Pod 总数上限。Pod 终止状态等价于 Pod 的 .status.phase in (Failed, Succeeded) 为真。
    replicationcontrollers: 10  #在该命名空间中允许存在的 ReplicationController 总数上限。
    resourcequotas: 5  #在该命名空间中允许存在的 ResourceQuota 总数上限。
    services: 5        #在该命名空间中允许存在的 Service 总数上限。
    services.loadbalancers: 5  #在该命名空间中允许存在的 LoadBalancer 类型的 Service 总数上限。
    services.nodeports: 5      #在该命名空间中允许存在的 NodePort 类型的 Service 总数上限。
    secrets: 7  #在该命名空间中允许存在的 Secret 总数上限。

更多详细信息参考官方文档:限制范围 | Kubernetes

资源紧缺时Pod的驱逐机制

Kubelet在驱逐用户Pod之前,会先尝试回收Node级别的资源。例如先删除已经停掉的Pod来清除nodefs上的存储资源,如果是imagesfs达到了驱逐阈值,会删除掉无用的image。
如果kubelet无法在Node上回收足够的资源,则其会尝试驱逐用户的Pod,按照QoS等级进行先后 驱逐,即先驱逐BestEffort,然后Burstable,最后Guaranteed。

上一篇:[RK3566-Android11] 关于 a2dpsink -蓝牙支持接收播放/无PIN码连接


下一篇:Redis类型 Stream Bitfield