mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1445 字
4 分钟
Kubernetes 扩展机制:CRD、Operator 与 Webhook
2023-12-20

一、为什么需要扩展 Kubernetes?#

Kubernetes 提供了声明式的 API 和控制器模式来管理容器化工作负载。然而,在实际生产环境中,原生的 API 资源类型(Deployment、Service、ConfigMap 等)并不能满足所有业务需求。例如,为 MySQL 数据库创建一个高可用的 StatefulSet 并管理其主从复制,手动备份恢复等运维操作——这些事情 Kubernetes 原生并不支持。

扩展 Kubernetes 的核心思路是:在不修改核心代码的前提下,通过 Kubernetes 已有的扩展机制来增强平台能力。这与 Kubernetes 本身的设计哲学一脉相承——Kubernetes 是一个平台构建平台,而非一个功能大而全的解决方案。

Kubernetes 提供了多层次的扩展机制,从上到下依次为:

扩展层次典型技术扩展深度适用场景
API 资源层CRD + Operator管理有状态应用、自定义工作负载
API 服务层Aggregated APIServer将外部系统接入 Kubernetes API
准入控制层MutatingAdmissionWebhook注入 sidecar、修改资源默认值
调度器层Scheduler Framework自定义调度策略、bin-packing
网络层CNI容器网络插件
存储层CSI存储编排插件

网络层的 CNI 和存储层的 CSI 是 Kubernetes 最底层的基础设施扩展接口,它们的设计理念与上层的 CRD/Operator 一脉相承——通过声明式 API 和控制器模式实现解耦。本文主要聚焦于 API 层和准入控制层的扩展,CSI 和 CNI 的详细实现请参阅 CSI 存储插件开发CNI 网络插件

二、Kubernetes API 的扩展#

Kubernetes API 服务器(kube-apiserver)本身是高度可扩展的。任何符合 Kubernetes API 规范的资源都可以注册为新的 API 类型,无需修改 apiserver 本身。

2.1 CustomResourceDefinition(CRD)#

CRD 是 Kubernetes 最常用的扩展方式。通过定义一个 CRD,开发者可以创建完全自定义的资源类型,Kubernetes 会自动为其生成 CRUD API,无需编写额外的 API 服务器代码。

定义一个 CRD 非常简单:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myapps.myorg.io
spec:
group: myorg.io
names:
kind: MyApp
listKind: MyAppList
plural: myapps
singular: myapp
shortNames:
- ma
scope: Namespaced # 或 Cluster
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
image:
type: string
status:
type: object
properties:
availableReplicas:
type: integer

CRD 的局限性在于:它只是一个存储数据的机制,CRD 本身不包含任何业务逻辑。如果需要在创建/更新/删除资源时执行特定操作(例如自动创建关联的 Service 或 ConfigMap),就需要配合控制器(Controller)或 Operator 使用。

2.1.1 Operator 模式#

Operator 是 CRD 与控制器的组合产物。Operator 遵循 Kubernetes 的控制器模式——监听资源变化,将实际状态向期望状态收敛。Operator 的特别之处在于,它封装了运维领域的知识,使得复杂的运维操作可以被自动化执行。

以 Prometheus Operator 为例,它定义了 PrometheusServiceMonitor 等 CRD,用户只需声明式的配置,Operator 就会自动创建和管理关联的 StatefulSet、ConfigMap、Service 等资源。

编写一个 Operator 通常借助 Kubebuilder 或 Operator SDK 框架:

# 使用 kubebuilder 创建 Operator 项目
kubebuilder init --domain myorg.io --repo github.com/myorg/my-operator
kubebuilder create api --group myorg.io --version v1 --kind MyApp

Kubebuilder 会自动生成 CRD 定义、RBAC 配置和基础控制器代码,开发者只需要填充 Reconcile 逻辑:

controllers/myapp_controller.go
func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
// 获取 MyApp 实例
myapp := &myorgiov1.MyApp{}
if err := r.Get(ctx, req.NamespacedName, myapp); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// 创建或更新关联的 Deployment
deploy := r.generateDeployment(myapp)
if err := r.createOrUpdate(ctx, deploy); err != nil {
return ctrl.Result{}, err
}
// 更新状态
myapp.Status.AvailableReplicas = deploy.Status.AvailableReplicas
if err := r.Status().Update(ctx, myapp); err != nil {
return ctrl.Result{}, err
}
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}

Operator 的核心优势在于将运维知识编码为软件。例如,手动管理 Redis 集群需要了解主从切换、故障转移、持久化策略等复杂知识;将这些知识编码到 Operator 中,普通运维人员只需要声明 RedisCluster 资源的期望状态,Operator 自动完成所有运维操作。

2.2 API Aggregation(聚合 API)#

CRD 适合扩展存储层的资源类型,但对于需要自定义 API 行为的场景(如特殊的认证逻辑、自定义查询参数、跨多个资源类型的复杂操作),聚合 API Server(Aggregated APIServer)是更合适的选择。

Aggregated APIServer 的架构是:在 kube-apiserver 之外,运行一个或多个额外的 API Server,这些 API Server 通过特殊的方式注册到 kube-apiserver 的代理路径下(通常是 /apis/mygroup.myorg.io/),对外部表现为统一的 Kubernetes API。

聚合 API Server 的优势在于:

  1. 完全独立的 API 行为:可以自定义认证、授权、序列化逻辑
  2. 独立的存储后端:可以使用 etcd 之外的其他存储(如 PostgreSQL、Redis)
  3. 独立的代码库:可以独立发布、版本演进,不影响核心 API

实现一个 Aggregated APIServer 通常需要:

main.go
import (
"k8s.io/apiserver/pkg/server"
"k8s.io/sample-apiserver/pkg/apiserver"
)
func main() {
// 创建自定义 API Server
cmd := apiserver.NewCommandStartFactory(os.Stdout, os.Stderr)
if err := cmd.Execute(); err != nil {
panic(err)
}
}

社区中许多知名项目采用 Aggregated APIServer 方式扩展 Kubernetes,例如 metrics-server(通过 Heapster 的替代品提供自定义指标 API)、Istio(通过 MCP 协议提供服务网格配置 API)等。

三、Kubernetes Scheduler 的扩展#

调度器的扩展在前文「Kubernetes 调度框架与自定义调度器开发」中已有详细介绍,核心是通过 Scheduler Framework 的扩展点注册自定义 Filter、Score、Reserve 等插件。

四、Kubernetes 客户端的扩展#

Kubernetes 客户端扩展通常指通过自定义资源定义(CRD)来扩展 API 对象,以及通过动态客户端(Dynamic Client)来访问这些自定义资源:

// 使用 client-go 访问 CRD 资源
import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
)
func getCustomResource() {
config, _ := rest.InClusterConfig()
dynamicClient, _ := dynamic.NewForConfig(config)
// 访问 myapps.myorg.io 资源
resource := dynamicClient.Resource(schema.GroupVersionResource{
Group: "myorg.io",
Version: "v1",
Resource: "myapps",
})
// 列出所有 MyApp 资源
list, _ := resource.List(metav1.ListOptions{})
for _, item := range list.Items {
fmt.Printf("Found MyApp: %s\n", item.GetName())
}
}

五、参考资料#


参考#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Kubernetes 扩展机制:CRD、Operator 与 Webhook
https://blog.souloss.com/posts/kubernetes/k8s-extend/
作者
Souloss
发布于
2023-12-20
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐
1
Kubernetes 应用管理:OAM、Helm 与 Operator
云原生 介绍如何在 Kubernetes 上以标准化方式发布和管理软件服务,涵盖 OAM 应用模型、Helm Chart 包管理、Operator 模式等应用交付方案。
2
Kubernetes 调度框架与自定义调度器开发
云原生 解析 Kubernetes 调度框架的扩展点机制,介绍如何通过实现自定义 Filter 和 Score 插件来开发生产可用的 Kubernetes 调度器扩展,附完整代码示例。
3
Kubernetes 服务发现与网络基础
云原生 深入 Kubernetes 服务发现与网络——Service 四种类型详解、Endpoints 与 EndpointSlice、Ingress 与 Ingress Controller、集群 DNS 服务发现、kube-proxy 的 iptables 与 IPVS 模式、NetworkPolicy 网络隔离,理解流量从客户端到 Pod 的路由机制。
4
Kubernetes 核心概念:Pod、Node 与控制面
云原生 深入 Kubernetes 核心概念——从控制面组件(API Server、etcd、Scheduler、Controller Manager)到工作节点组件(kubelet、kube-proxy),再到 Pod、Node、Namespace、Label 与 Selector 的设计哲学,理解声明式 API 与控制器模式的协作机制。
5
Kubernetes 安全:RBAC、Pod 安全与网络策略
云原生 深入 Kubernetes 安全体系——RBAC 权限模型(Role/ClusterRole/RoleBinding/ClusterRoleBinding)、ServiceAccount 身份管理、Pod 安全标准与 Pod Security Admission、SecurityContext 容器安全、NetworkPolicy 网络隔离、Secret 加密与外部密钥管理,构建纵深防御的安全架构。