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 和控制循环模式,是迈向云原生高阶开发者的必经之路。

相关推荐
无限大62 小时前
为什么"数据压缩"能减小文件大小?——从冗余数据到高效编码
后端
用户729429432232 小时前
基于Dubbo的分布式系统架构+事务解决方案
后端
程序员鱼皮2 小时前
什么是 RESTful API?凭什么能流行 20 多年?
前端·后端·程序员
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue健身房管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
用户729429432232 小时前
Shiro框架工作原理与实践精讲
后端
用户729429432232 小时前
uni-app实战在线教育类app开发
后端
用户729429432232 小时前
数据中心虚拟化之KVM虚拟化基本部署视频课程
后端
幌才_loong2 小时前
深入解析 C# async/await 执行原理:从语法糖到状态机
后端·.net