前言

在等待了三个月之后,kubernetes 1.26 如期发布,这个版本引入了很多新功能,让我们通过这篇文章一睹为快。推荐读者将自己的测试集群升级到 1.26 体验这些新功能,因为这是一个十分值得尝试的版本!V1.26总计带来了37项增强功能。在这37项增强功能中,有11项功能成为稳定版,有10项是对现有功能的改进,有多达16项功能是全新的,有1项功能被废弃。

在此版本中,在各个领域都有诸多引人注目的更新,比如VolumeSnapshot支持跨命名空间使用、对高性能计算类应用的持续优化、windows支持主机网络模式等等。在众多的功能增强中,本文挑选了十项值得关注的新特性与大家分享

新功能介绍

Dynamic resource allocation

这是个更灵活的资源调度方式,在之前 pod 申请的资源一般都是 cpu、内存,或者 gpu,所以 kubernetes 默认的资源调度方式并不灵活。随着kubernetes的使用越来越广泛,pod所需的硬件资源种类也越来越多,例如通过网络获取的硬件资源,或者 FPGA 等硬件资源。
这个特性通过定义一些新的 api,为 pod 引入了动态的资源分配方式,用户只需要创建一个定义资源的ResourceClaim,并且在创建pod时绑定此资源,pod就可以使用这个资源。并且新api在设计时,就提供了足够多的语义,使得当前所有的 device plugin都可以与动态分配资源功能兼容。下面是一个样例:

apiVersion: gpu.example.com/v1
kind: GPURequirements
metadata:
  name: device-consumer-gpu-parameters
memory: "2Gi"
---
apiVersion: resource.k8s.io/v1alpha1
kind: ResourceClaimTemplate
metadata:
  name: device-consumer-gpu-template
spec:
  metadata:
  spec:
    resourceClassName: "acme-gpu"
    parametersRef:
      apiGroup: gpu.example.com
      kind: GPURequirements
      name: device-consumer-gpu-parameters
---
apiVersion: v1
kind: Pod
metadata:
  name: device-consumer
spec:
  resourceClaims:
  - name: "gpu" # this name gets referenced below under "claims"
    template:
      resourceClaimTemplateName: device-consumer-gpu-template
  containers:
  - name: workload
    image: my-app
    command: ["/bin/program"]
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
      claims:
        - "gpu"
  - name: monitor
    image: my-app
    command: ["/bin/other-program"]
    resources:
      requests:
        memory: "32Mi"
        cpu: "25m"
      limits:
        memory: "64Mi"
        cpu: "50m"
      claims:
      - "gpu"

这个新的api为资源的分配带了了很多新的功能,例如:

  • pod可以使用网络附加资源
  • 资源可以在多个容器间或者多个pod间共享。
  • 在多个pod中多次初始化资源
  • 可以通过设置参数,自定义资源的申请大小和初始化方式
    这个新功能的灵活性为资源分配带来了无限可能。相信在未来这个特性会令人瞩目。

Improved multi-numa alignment in Topology Manager

在高性能计算的场景中,服务器的性能大多都强的离谱,一台服务器中的cpu数量一般都会大于一个,这时候就需要 NUMA 技术,这种技术可以为程序更合理的分配不同的cpu,让 cpu 读取内存的速度更快,从而程序运行的更快。
在这个新的特性中,会根据NUMA优化pod的调度,让其运行的更快,在高性能计算中,性能非常敏感,因此这个功能也十分重要。
值得一提的是,在CNCF社区的批处理调度框架 Volcano项目 中,也已经支持了根据 NUMA 优化pod的调度的能力,博云的AI算力平台(BCC)底层也正是采用了 volcano,并在大量客户中进行了生产实践。在作业规模、性能等方面都取得了很大提升。在建设BCC的过程中,博云也已经将多个在生产实践中遇到的重要功能贡献到 volcano社区。

Kubelet evented PLEG for better performance

相信排查节点 notready 问题的同学,都会遇到过 kubelet 中有关PLEG的报错。PLEG是kubelet的一个关键功能,但是这个功能在性能和可靠性上又一言难尽,现在官方终于对其做出改变了,希望通过这个增强,能让kubelet更加健壮。在之前,kubelet为了掌握容器的状态,会以1秒为周期,轮询调用CRI,在容器的规模变大之后,轮询的开销也会随之变大。这个新功能主要优化的方式是,将之前的固定周期轮询改为kubernetes中久经考验的ListAndWatch机制,减少轮询频率,从而减少了开销。

Pod scheduling readiness

这是一个十分有趣的小功能。
有些时候,我们创建出了一些pod,但是可能还没准备好让这些pod被调度,我们想在合适的时机调度pod。目前缺少这么一个让pod“等待调度”的功能。
在 kubernetes 1.26 中,这个功能被添加了。如何使用呢?很简单,只要在pod.spec.schedulingGates字段添加键值对就可以了。下面具体演示
编写一个pod的yaml文件,在schedulingGates字段中添加两个元素

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  schedulingGates:
  - name: testSchedulingGate
  - name: addAnotherValue
  containers:
  - image: nginx
    name: nginx

使用这个yaml创建pod,查看pod的状态,会得到以下结果,pod没有被调度

root@k8s126master:~# kubectl get po
NAME    READY   STATUS            RESTARTS   AGE
nginx   0/1     SchedulingGated   0          31s

查看pod的status字段,可以看到详细的未被调度的原因

status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: null
    message: Scheduling is blocked due to non-empty scheduling gates
    reason: SchedulingGated
    status: "False"
    type: PodScheduled

当pod准备好被调度时,我们把schedulingGates字段中的内容删除,可以看到pod马上就会被调度

root@k8s126master:~# kubectl get po
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          3m30s

Allow StatefulSet to control start replica ordinal numbering

这也是个比较有趣的功能,可以让用户自定义的StatefulSet 副本的启动序号,使用过StatefulSet的同学都知道,通过StatefulSet创建出的pod,末尾的序号都是从0开始,这个功能可以让用户自己设定pod的启动序号,例如我用下面的yaml创建一个StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  ordinals:
    start: 10
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

可以看到设定的副本数为5,启动序号为10,当这个StatefulSet被创建出来后,查看pod的信息,可以看到pod是按照我们的预期被创建的

root@k8s126master:~# kubectl get po
NAME     READY   STATUS    RESTARTS   AGE
web-10   1/1     Running   0          3m23s
web-11   1/1     Running   0          3m18s
web-12   1/1     Running   0          3m13s
web-13   1/1     Running   0          3m8s
web-14   1/1     Running   0          3m3s

Kubernetes component health SLIs

这个功能为用户带来了一种直观的查看kubernetes集群组件是否健康的方式
其引入了一个指标 kubernetes_healthcheck,返回标准的 prometheus格式的数据,告知用户kubernetes组件是否正常运行,方便用户更方便的监控集群状态。

Host network support for Windows pods

kubernetes 对 windows的支持一直都在稳步推进当中,之前的版本中,windows的容器已经可以使用特权容器,在kubernetes 1.26 版本,windows特权容器的功能已经达到稳定级别,并且windows容器终于可以使用主机网络模式了,虽然还是 alpha 阶段,但是kubernetes社区和微软合作的趋势是良好的。
博云也在大规模的生产环境中使用过部署在windows操作系统上的kubernetes集群,帮助客户实现了两个数量级级别的效率提升。博云自研的网络插件 fabric 的 windows 版也已经可以稳定运行在Windows生产环境中。

CEL for admission control

随着越来越多的CRD被创建,越来越多的准入控制器被创建,越来越多的webhook被创建。但其实很多时候,用户对于CRD的校验都是很简单的,不需要在集群中部署一个复杂的、浪费资源的webhook。例如只需要校验一个int类型的字段,它的值不能大于10。这种场景下,你就需要kubernetes 1.26 的这个新功能。
而且更优秀的是,这个功能不只为了CRD设计,它也可以用于kubernetes的内置资源,例如deployment
这个功能的使用也非常简单,下面是限制 deployment 的副本数的例子

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "validate-xyz.example.com"
spec:
  singletonPolicy: true
  match:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  defaultValidations:
  - expression: "object.spec.replicas < 100"

Minimizing iptables-restore input size

这个优化说起来很简单,引用设计文档的一句话:

Improve the performance of kube-proxy in iptables mode, by optimizing its calls to iptables-restore by not including rules that haven’t changed.

通过优化 iptables-restore 的调用,优化 iptables 模式下 kube-proxy 的性能。kube-proxy 的性能也是总被用户提及的一个问题,kubernetes 官方也采取了很多措施优化 kube-proxy的性能,例如引入 ipvs。
博云在自研网络插件的过程中,也体会到了kube-proxy的性能瓶颈和一些bug带来的痛苦,所以在fabic的发布版本中正式推出了fabric-proxy。Fabric-proxy已经完全集成了kube-proxy的功能,并且做了性能优化,用户在使用fabric时,将不再需要部署kube-proxy,从根源避免了kube-proxy带来的一些问题。

Provision volumes from cross-namespace snapshots

这是kubernetes 1.26着重宣传的一个功能。命名空间是kubernetes中隔离用户、资源的一个核心方式,它有优点,但是使用上也有不便。在 Kubernetes 1.26 之前,用户可以使用VolumeSnapshot为卷创建快照,但是这个功能没办法跨命名空间创建快照,在kubernetes 1.26中这个限制被打破了,通过引入一个新的资源ReferenceGrant,将允许用户跨命名空间为卷创建快照。
下面就是一个样例,这个名为bar的ReferenceGrant将命名空间test下的pvc和命名空间为prod的VolumeSnapshot关联到一起。

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: ReferenceGrant
metadata:
  name: bar
  namespace: prod
spec:
  from:
  - kind: PersistentVolumeClaim
    namespace: test
  to:
  - group: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    name: foo-backup
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-testing
  namespace: test
spec:
  accessModes:
  - ReadWriteOnce
  resources:
	requests:
	  storage: 10Mi
  dataSourceRef2:
	apiGroup: snapshot.storage.k8s.io/v1
	kind: VolumeSnapshot
	name: foo-backup
	namespace: prod
  volumeMode: Filesystem

总结

在经过了多年的发展之后,kubernetes已经是一个十分成熟的项目了,但经过上面的介绍,我们也可以看到,它依旧保持着充足的活力,引入很多新的功能,让用户在诸如高性能计算等领域看见大规模使用kubernetes的前景,这与开源社区的运作密切相关。博云愿与开源社区中的其他成员一起,共同建设kubernetes及其周边生态,为kubernetes创造更多可能!

参考链接

https://github.com/kubernetes/kubernetes/milestone/59 https://kubernetes.io/blog/2022/11/18/upcoming-changes-in-kubernetes-1-26/
https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation
https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3545-improved-multi-numa-alignment
https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3386-kubelet-evented-pleg
https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/3521-pod-scheduling-readiness
https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/3335-statefulset-slice
https://github.com/kubernetes/enhancements/tree/master/keps/sig-windows/3503-host-network-support-for-windows-pods
https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3488-cel-admission-control
https://github.com/google/cel-spec
https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3453-minimize-iptables-restore
https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/3294-provision-volumes-from-cross-namespace-snapshots
https://sysdig.com/blog/kubernetes-1-26-whats-new