kubernetes/k8s全栈技术讲解+企业级实战项目课程

随着云原生技术的成熟,Kubernetes (K8s) 已成为事实上的基础设施操作系统。然而,原生的 K8s 资源(如 Deployment、Service)主要关注通用型负载的编排。在处理复杂的业务逻辑(如数据库高可用切换、分布式任务调度、自定义中间件管理)时,直接使用 YAML 配置往往力不从心。此时,Kubernetes Operator 模式 应运而生。学习地址:pan.baidu.com/s/1WwerIZ_elz_FyPKqXAiZCA?pwd=waug

本文将带你深入 Operator 开发的核心战场,从定义自定义资源(CRD)到编写控制循环,手把手构建一个企业级的 Operator。

一、 架构设计理念:为何需要 Operator?

Operator 基于 Kubernetes 控制器模式。它通过"监控实际状态 -> 调整偏差 -> 使实际状态趋向期望状态"的无限循环来管理工作负载。

  • CRD (Custom Resource Definition) :扩展 K8s API,声明一种新的资源类型(如 MySQLCluster)。
  • Controller:业务逻辑的大脑,监听 CRD 的变化并执行操作。

二、 实战第一步:定义 CRD

假设我们要开发一个简单的 WebApp 资源,它能自动管理 Deployment 并根据副本数配置 HPA。首先,我们需要定义 CRD。

crd/webapp.yaml

yaml

复制

yaml 复制代码
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: webapps.example.com # 资源名称,复数形式
spec:
  group: example.com # API 组名
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                replicas:
                  type: integer
                image:
                  type: string
                port:
                  type: integer
            status:
              type: object
              properties:
                availableReplicas:
                  type: integer
  scope: Namespaced
  names:
    plural: webapps
    singular: webapp
    kind: WebApp
    shortNames:
      - wa

应用该 YAML 后,K8s 集群便识别了 WebApp 这种新资源。

三、 实战核心:使用 Kubebuilder 开发 Controller

虽然手写 client-go 也是可行的,但在企业级开发中,我们强烈推荐使用 KubebuilderOperator SDK,它们提供了脚手架和代码生成工具,极大地提升了效率。

1. 初始化项目

bash

复制

css 复制代码
# 安装 kubebuilder 后
kubebuilder init --domain example.com --repo myapp/operator
kubebuilder create api --group webapp --version v1 --kind WebApp

2. 编写 Reconcile 逻辑

这是 Operator 的灵魂。我们需要在 controllers/webapp_controller.go 中实现 Reconcile 方法。该方法的任务是:获取 WebApp 实例,查看是否有对应的 Deployment,没有则创建,有则更新。

go

复制

go 复制代码
package controllers

import (
	"context"
	"fmt"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"

	myappv1 "myapp/operator/api/v1"
)

// 定义注解,用于 OwnerReference
const finalizerName = "webapp.finalizer"

// WebAppReconciler 结构体
type WebAppReconciler struct {
	client.Client
	Scheme *runtime.Scheme
}

// +kubebuilder:rbac:groups=webapp.example.com,resources=webapps,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=webapp.example.com,resources=webapps/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete

// Reconcile 核心调协逻辑
func (r *WebAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	log := log.FromContext(ctx)

	// 1. 获取 WebApp 实例
	var webApp myappv1.WebApp
	if err := r.Get(ctx, req.NamespacedName, &webApp); err != nil {
		if errors.IsNotFound(err) {
			log.Info("WebApp resource not found. Ignoring since object must be deleted")
			return ctrl.Result{}, nil
		}
		return ctrl.Result{}, err
	}

	// 2. 查找关联的 Deployment
	foundDeploy := &appsv1.Deployment{}
	err := r.Get(ctx, client.ObjectKey{Name: webApp.Name, Namespace: webApp.Namespace}, foundDeploy)

	// 3. 如果 Deployment 不存在,则创建它
	if err != nil && errors.IsNotFound(err) {
		deploy := r.newDeployment(&webApp)
		log.Info("Creating a new Deployment", "Deployment.Namespace", deploy.Namespace, "Deployment.Name", deploy.Name)
		if err := r.Create(ctx, deploy); err != nil {
			log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", deploy.Namespace, "Deployment.Name", deploy.Name)
			return ctrl.Result{}, err
		}
		// 创建成功,重新入队等待状态更新
		return ctrl.Result{Requeue: true}, nil
	} else if err != nil {
		log.Error(err, "Failed to get Deployment")
		return ctrl.Result{}, err
	}

	// 4. 更新状态 (示例:简单地将副本数同步到 Status)
	webApp.Status.AvailableReplicas = foundDeploy.Status.AvailableReplicas
	if err := r.Status().Update(ctx, &webApp); err != nil {
		log.Error(err, "Failed to update WebApp status")
		return ctrl.Result{}, err
	}

	return ctrl.Result{}, nil
}

// newDeployment 生成 Deployment 对象的辅助函数
func (r *WebAppReconciler) newDeployment(cr *myappv1.WebApp) *appsv1.Deployment {
	labels := map[string]string{"app": cr.Name}
	return &appsv1.Deployment{
		ObjectMeta: ctrl.ObjectMeta{
			Name:      cr.Name,
			Namespace: cr.Namespace,
		},
		Spec: appsv1.DeploymentSpec{
			Replicas: &cr.Spec.Replicas,
			Selector: &metav1.LabelSelector{
				MatchLabels: labels,
			},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{Labels: labels},
				Spec: corev1.PodSpec{
					Containers: []corev1.Container{
						{
							Name:  "nginx",
							Image: cr.Spec.Image,
							Ports: []corev1.ContainerPort{
								{ContainerPort: cr.Spec.Port},
							},
						},
					},
				},
			},
		},
	}
}

// SetupWithManager 注册控制器到 Manager
func (r *WebAppReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&myappv1.WebApp{}).
		Owns(&appsv1.Deployment{}). // 监控 Owned 资源
		Complete(r)
}

四、 本地调试与部署

开发完成后,不要急着部署到集群,利用 make run 可以在本地直接运行控制器,它会连接到你的 ~/.kube/config 指定的集群。

bash

复制

bash 复制代码
make install # 安装 CRD
make run     # 运行控制器

此时,在另一个终端创建一个 WebApp 实例:

yaml

复制

yaml 复制代码
apiVersion: webapp.example.com/v1
kind: WebApp
metadata:
  name: my-demo-app
spec:
  replicas: 3
  image: nginx:1.19
  port: 80

应用 YAML 后,观察控制器日志,你会发现它自动创建了对应的 Deployment,并维持了 3 个副本。

五、 总结

Kubernetes Operator 开发不仅仅是为了自动化部署,更是为了将领域知识(Domain Knowledge)编码进 K8s。通过 CRD 定义业务模型,通过 Controller 实现运维逻辑,我们成功地将 K8s 变成了一个可编程的操作系统。掌握 Kubebuilder 和控制循环模式,是迈向云原生高阶开发者的必经之路。

相关推荐
赵文宇15 分钟前
CNCF Dragonfly 毕业啦!基于P2P的镜像和文件分发系统快速入门,在线体验
后端
程序员爱钓鱼34 分钟前
Node.js 编程实战:即时聊天应用 —— WebSocket 实现实时通信
前端·后端·node.js
Libby博仙1 小时前
Spring Boot 条件化注解深度解析
java·spring boot·后端
源代码•宸2 小时前
Golang原理剖析(Map 源码梳理)
经验分享·后端·算法·leetcode·golang·map
小周在成长2 小时前
动态SQL与MyBatis动态SQL最佳实践
后端
瓦尔登湖懒羊羊2 小时前
TCP的自我介绍
后端
小周在成长2 小时前
MyBatis 动态SQL学习
后端
子非鱼9212 小时前
SpringBoot快速上手
java·spring boot·后端
我爱娃哈哈2 小时前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端
JavaGuide2 小时前
Maven 4 终于快来了,新特性很香!
后端·maven