大家好,我是张晋涛。
Kubernetes v1.27 是 2023 年的第一个大版本更新,包含了近 60 项主要的更新。 而 1.26 只有 37 项,所以这个版本可以说是一个变化非常显著的版本了。
其中 18 个增强功能正在进入 Alpha 阶段,29 个将升级到 Beta 阶段,而另外 13 个则将升级到稳定版。
尽管这个版本中包含了这么多的特性变更,但值得一提的是,这个版本应该算是第一个完全按照即定流程,恪守每个 deadline 的版本。 之前的版本中,每次都或多或少会有一些变数,不过这也从侧面可以看到 release team 做了很多幕后的工作。
我每期的 「k8s生态周报」都有一个叫上游进展的部分,所以很多值得关注的内容在之前的文章中已经发过了。 这篇中我会再额外介绍一些之前未涵盖的,和之前介绍过的值得关注的内容。
我们一起来具体看看吧!
SeccompDefault 达到 Stable
如果想要默认使用 seccomp profile,则必须在每个想要使用它的节点上为 kubelet 启用 --seccomp-default
选项。
如果启用了该选项,则 kubelet 将默认使用由容器运行时定义的 RuntimeDefault
seccomp profile,而不是使用 Unconfined
(禁用seccomp)模式。“
默认配置文件旨在提供强大的安全性设置,并保留工作负载功能。 容器运行时的不同发布版本之间可能存在不同的默认配置文件。
印象里很早之前 Docker 的配置文件就因为修补安全漏洞而调整过。
Pod 调度就绪机制达到 Beta
这个功能实际上是从 Kubernetes v1.26 开始增加的。是 KEP 3521 的第一部分。
首先我们来简单的回顾一下 Pod 的创建过程。
当 client 通过 kube-apiserver 创建成功 Pod 资源后,kube-scheduler 会去检查尚未被调度的 Pod,然后为其进行调度,分配 Node。之后 Node 获取到调度到该 Node 上的 Pod 然后进行创建。 这里省略了很多细节,但其他的部分与我们此处要介绍的内容关系不太大,就不展开了。
根据上述的过程,我们可以发现,在 Pod 创建成功后,其实就默认该 Pod 是可以被调度了,kube-scheduler 就应该开始工作了。
但在实际的场景中,Pod 通常还会需要一些其他的资源,最典型的比如存储。在一些环境中,这些资源是需要预先进行创建的, 尤其是在一些云厂商的场景中,还需要检查用户账户中是否还有余额可以用于创建云盘等。
一但前置的依赖无法满足,假如 kube-scheduler 已经完成了 Pod 的调度,那么 kubelet 侧就会处于尝试创建 Pod ,但失败的情况。
这个 KEP 的出现就可以很好的解决这个问题,增加了一个 Pod 是否准备好被调度的机制。 如果前置依赖不满足,那么 Pod 就无需被调度,这也不会消耗资源。kube-scheduler 和 kubelet 都无需进行处理。 待条件满足,Pod 再被调度和创建即可。
这个机制我个人感觉还是挺好的,甚至我可以有更灵活的策略来控制应用的副本。 比如在大流量,需要动态扩容的场景下,我可以利用此机制预先创建一些 Pod 资源以及准备好它的依赖, 甚至可以在 Node 上准备好镜像等。当需要增加副本时,直接标记 Pod 可被调度,
使用时,通过配置 Pod 的 .spec.schedulingGates
即可。
新增 NodeLogQuery 特性 - KEP-2258
我们通常最习惯使用 kubectl logs
命令来获取 Kubernetes 集群中运行的应用的日志,也可以通过给它传递一些参数来调整它的过滤范围。
比如:kubectl logs job/hello
来指定获取 hello 这个 job 的日志;也可以增加 -l
/ --selector=''
来基于 label 进行过滤。
但这并没有扩展到 Node 级别的日志,无法直接获取到某个 Node 上的全部日志,要想得到这个结果需要写一段很复杂的 Shell 来完成。
当前 Kubernetes 社区已经逐渐提供了更多 Node 调试工具,旨在为调试 Node 故障提供统一体验,并更好地支持极简操作系统。通过 KEP 2258: add node log query by LorbusChris · Pull Request #96120 · kubernetes/kubernetes ,我们现在可以远程获取底层 Node 日志。与容器日志记录一样,这是Kubelet API的一部分。
对于Linux系统,它查询journald;对于Windows系统,则查询事件日志(Event Log)。目前还没有专门针对此功能的 kubectl 命令,但可以使用如下命令进行尝试:
(MoeLove) ➜ kubectl get --raw "/api/v2/nodes/$NODE_NAME/proxy/logs/?query=kubelet
基于 CEL 的 Admission Control
对 Kubernetes 中的 Adminssion Control 感兴趣的小伙伴可以看看我之前的文章:理清 Kubernetes 中的准入控制(Admission Controller) | MoeLove
- KEP-3488: Implement secondary authz for ValidatingAdmissionPolicy by jpbetz · Pull Request #116054 · kubernetes/kubernetes
- KEP-3488: Implement Enforcement Actions and Audit Annotations by jpbetz · Pull Request #115973 · kubernetes/kubernetes
Kubernetes 在 v1.26 增加了一项很重要的特性,那就是允许使用 CEL 进行 Admission Control,具体内容可以参考我之前写的文章: Kubernetes v1.26 新特性一览 | MoeLove
其中引入了一个新的资源 ValidatingAdmissionPolicy ,使用起来如下:
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
name: "demo-policy.moelove.info"
Spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= 2"
但是在当时也只是实现了 KEP-3488 的一部分。
在这个 PR 中是在实现 Authz 的部分,这允许用 CEL 表达式编写复杂的 admission control 规则, 放置在声明式资源中,而不是构建和部署 webhook。
虽然 admission webhook 一直是我们灵活的与第三方工具集成的基石,但是对于新用户来说,它们有很多复杂性,新的 CEL 系统有望接管仅需要对默认规则进行小修改的简单独立案例。
以前,表达式上下文会公开有关当前请求和目标资源的信息,现在通过这个 PR 可以在授权层中动态检查 RBAC 权限。 一些有用的地方可能是使用 RBAC 进行每个字段的更新权限,允许 RBAC 检查特定对象而不使用 resourceNames 系统, 或基于请求者身份限制对程序敏感字段(例如 finalizers )的访问而无需生成复杂的 RBAC 策略。
例如:
authorizer.group('').resource('pods').namespace('default').check('create').allowed()
authorizer.path('/healthz').check('GET').allowed()
authorizer.requestResource.check('my-custom-verb').allowed()
本次还加入了#115973,该功能允许在失败时作为主要操作发出审计日志事件,或者如果需要更多数据,可以编写一个或多个CEL表达式,以提供详细的值, 这些值将发送到审计子系统。
这既可以在开发新策略时提供强大的调试选项,也可以进行运行时分析。 其他 CEL admission 特性包括成本检查,以防止您使用所有这些新功能意外拒绝服务自己的 kube-apiserver,以及改进的类型检查。
总的来说,基于 CEL 的 admission 处理有了很多新的功能,希望进一步将 webhook 推入到一个有限的用例空间中(防止滥用)。
Pod In-place 原地伸缩能力
这个功能允许在不重启 Pod 的情况下,更新 Pod 的 resources 配置。
经过 4 年的规划和至少 2 年的开发,在 Kubernetes v1.27 中终于推出了 Pod 的就地资源缩放的第一版。
这个PR实现了核心缩放功能和一些相关的API处理。
主要功能非常简单,现在可以在现有容器上编辑 resources
配置,而不会导致 API 错误。
在看到缩放请求后,Kubelet 会立即采取行动并检查节点是否有足够的资源来满足新的请求。
如果是这样,它将 Status.Resize
字段设置为 InProgress,并继续进行 CRI 调用和其他内部更新。
如果新的大小不合适,将启动其他状态流,但总体目标相同,即尝试在可能的情况下提供请求的更改。
还有一个新的 per-resource 缩放策略字段,可以设置为 RestartNotRequired
(默认值)表示不需要重新启动(但某些运行时仍然可能需要这样做),
或设置为 Restart
以强制关闭和重新启动容器(例如具有需要重新计算-Xmx 堆大小标志的 Java 应用)。
现在缺少一个显著的特性是基于缩放的驱逐。目前,Kubelet 不会自动处理它,但如果外部系统执行 Pod 删除,它将适当地作出反应。
尽管现在还处于比较早期的阶段,但至少我们看到了它的变化,期待后续的演进。
一些废弃提醒
不再提供的API版本:
- Kubeadm
v1beta2
,可以使用kubeadm config migrate
迁移到v1beta3
。 resource.k8s.io/v1alpha1.PodScheduling
:请使用resource.k8s.io/v1alpha2.PodSchedulingContext
。- DynamicResourceManagement
v1alpha1
:请使用v1alpha2
。 - CSIStorageCapacity:
storage.k8s.io/v1beta1
:请使用 v1。
已弃用,在下一个版本发布之前实现替代方案:
seccomp.security.alpha.kubernetes.io/pod
和container.seccomp.security.alpha.kubernetes.io
annotations :请改用securityContext.seccompProfile
字段。SecurityContextDeny
准入插件。service.kubernetes.io/topology-aware-hints
annotations:请改用service.kubernetes.io/topology-mode
。
已删除
- Feature gates:
IPv6DualStack
ExpandCSIVolumes
ExpandInUsePersistentVolumes
ExpandPersistentVolumes
ControllerManagerLeaderMigration
CSI Migration
CSIInlineVolume
EphemeralContainers
LocalStorageCapacityIsolation
NetworkPolicyEndPort
StatefulSetMinReadySeconds
IdentifyPodOS
DaemonSetUpdateSurge
- appProtocol:
kubernetes.io/grpc
. - kube-apiserver 参数:
--master-service-namespace
. - CLI 参数:
--enable-taint-manager
和--pod-eviction-timeout
. - kubelet 参数:
--container-runtime
,--master-service-namespace
. - Azure disk in-tree storage plugin.
- AWS kubelet credential provider: 使用
ecr-credential-provider
. - Metrics:
node_collector_evictions_number
被node_collector_evictions_total
替换scheduler_e2e_scheduling_duration_seconds
被scheduler_scheduling_attempt_duration_seconds
替换
以上就是 Kubernetes v1.27 版本中我认为主要值得关注的部分。下次再见!
欢迎订阅我的文章公众号【MoeLove】