当前位置: 首页 > news >正文

K8S数据流核心底层逻辑剖析

一、背景

        之前也在学习使用K8S,但是仅仅停留在Pod控制器的部署使用、Service、Ingress、Pod等等层面,底层的数据流逻辑没去细究。 最近花了点时间去详细剖析了一下,和大家做个分享。

        我查询过很多资料,B站、CSDN各种资料,我发现几乎没人能把底层的逻辑讲清楚,或者说K8S的整个数据流架构思想讲清楚。 真的这个思想不复杂,但是确实没人讲得很透

        一方面可能入门门槛较高,大家觉得会用都已经很不错了,细究原理比较少。还有的就是,可能大家也不想讲,要么收费课程啥的,讲得含糊其辞,怕别人理解了似的😂。

        所以我使用最通俗易懂的方式来讲解k8s数据流的核心底层逻辑,可以有利于我们深入学习k8s,也可以帮我们去理解如何做CRD二次开发,开发自定义的CRD、CRD控制器等等。

二、架构图

核心逻辑总结:

        1、提交期望的部署资源对象清单数据,到kube-apiserver, kube-apiserver校验,存储清单数据到etcd数据库

        2、资源对象controller程序,会持续订阅watch监听kube-apiserver关于该类型的资源对象event事件,例如新增、更新、删除等等。  得到对应类型event,执行对应逻辑,例如创建Pod、更新Pod、删除Pod等等。  会按照ETCD存储的清单目标,通过自己的逻辑无限逼近这个目标的达成,如果能够达成最好,达不成也会例如重试等机制,往目标状态贴近,直到最后目标状态一致

        3、K8S无外乎就是, 官方定义了很多内置/通用性强的资源对象类型,并且这些资源对象类型都有对应的controller控制器的代码实现.  如果内置对象不满足你的需求,同时也支持你扩展,定义自定义CRD、CRD控制器完成自定义的资源对象逻辑

整体逻辑就是如此,万变不离其宗。  无外乎我们都在学习Deployment、Pod、Service等等的字段,功能等等。 

三、CRD、CRD控制器

0、需求

        1、需求是创建一个名称叫DoubleDeployment的CRD

        2、DoubleDeployment存在2个字段:  replicas副本数、image镜像URL地址

        3、底层引用内置Deployment, 创建一个Deployment.  设置mainc存在一个容器,镜像地址是image,  并且副本数replicas = DoubleDeployment.replicas  x 2     也就是说的Double的含义

        4、也就是你一旦创建这个DoubleDeployment 资源对象,填写的replicas数量, 都会创建一个关联的Deployment, 并且这个Deployment的副本数 是 DoubleDeployment.replicas  x2  翻倍

1、CRD

        CRD类比,Java编程当中的class定义.  K8S内置的Deployment、DaemonSet、Pod等等资源对象,本质就是一种class类型.   既然类比class, 那么只是定一个这个数据类型或者资源对象的元数据,数据结构。 

        例如存在哪些字段,这些字段哪些是必须的、哪些非必须的,字段类型,字段的规则等等。仅仅只是定义了资源对象的数据结构

        下面就是一个简单的CRD清单:  DoubleDeployment-CRD.yml

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:name: doubledeployments.samplecontroller.demo.io
spec:group: "samplecontroller.demo.io"versions:- name: v1served: truestorage: trueschema:openAPIV3Schema:type: objectproperties:spec:type: objectproperties:replicas:type: integerminimum: 0maximum: 100image:type: stringrequired:- replicas- imagescope: Namespacednames:plural: doubledeploymentssingular: doubledeploymentkind: DoubleDeploymentshortNames:- dd

2、CRD实例/CRD资源清单

        光有class定义没啥作用,我们的目的是new生成这个对象实例,用于后续的使用。 CRD实例就是这么来的。  例如我们定义一个Deployment的yaml对象资源清单,本质就是类比new了这个Deployment类型的实例。

        存在CRD的资源清单/CRD实例: DoubleDeployment.yml

apiVersion: samplecontroller.demo.io/v1
kind: DoubleDeployment
metadata:name: test-ddnamespace: default
spec:replicas: 2         #副本数2个, 但是DoubleDeployment CRD底层控制器会 x2 最终等于4个 podimage: nginx:alpine

3、CRD控制器

      存在了CRD,也存在了CRD实例,还是不够的,这些会被提交到ETCD数据库进行存储. 还需要CRD控制器对这个CRD类型数据进行watch监听,执行实际操作,才能达到我们的目的。使用Go编写了一个简单的CRD controller程序:

        main.go:

package mainimport ("context""fmt""os"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/apimachinery/pkg/runtime/schema""k8s.io/client-go/dynamic""k8s.io/client-go/kubernetes""k8s.io/client-go/rest"_ "k8s.io/client-go/tools/clientcmd""k8s.io/klog/v2"ctrl "sigs.k8s.io/controller-runtime"
)// DoubleDeployment CRD 结构体
type DoubleDeployment struct {metav1.TypeMeta   `json:",inline"`metav1.ObjectMeta `json:"metadata,omitempty"`Spec struct {Replicas int32  `json:"replicas"`Image    string `json:"image"`} `json:"spec"`
}var (gvr = schema.GroupVersionResource{Group:    "samplecontroller.demo.io",Version:  "v1",Resource: "doubledeployments",}
)func main() {klog.SetOutput(os.Stdout)klog.InitFlags(nil)ctx := context.Background()// 获取 kubeconfig(本地或集群内)config := ctrl.GetConfigOrDie()// 创建 dynamic clientdynClient, err := dynamic.NewForConfig(config)if err != nil {panic(err)}// 启动控制器主循环for {// 列出所有 DoubleDeployment 资源list, err := dynClient.Resource(gvr).Namespace("default").List(ctx, metav1.ListOptions{})if err != nil {klog.ErrorS(err, "Failed to list DoubleDeployment")continue}for _, item := range list.Items {var dd DoubleDeploymentif err := runtime.DefaultUnstructuredConverter.FromUnstructured(item.Object, &dd); err != nil {klog.ErrorS(err, "Failed to convert unstructured", "name", item.GetName())continue}// 只处理未处理过的资源(比如没有标签标记)if item.GetLabels() == nil || item.GetLabels()["processed"] != "true" {if err := reconcileDeployment(ctx, config, &dd); err != nil {klog.ErrorS(err, "Failed to reconcile deployment", "name", dd.Name)} else {// 标记为已处理,避免重复创建item.SetLabels(map[string]string{"processed": "true"})_, uErr := dynClient.Resource(gvr).Namespace(dd.Namespace).Update(ctx, &item, metav1.UpdateOptions{})if uErr != nil {klog.ErrorS(uErr, "Failed to update CRD label", "name", dd.Name)}}}}select {case <-ctx.Done():returndefault:continue}}
}// reconcileDeployment:根据 CR 创建 Deployment
func reconcileDeployment(ctx context.Context, config *rest.Config, dd *DoubleDeployment) error {clientset, err := kubernetes.NewForConfig(config)if err != nil {return err}namespace := dd.Namespaceif namespace == "" {namespace = "default"}deployName := dd.Name// 副本数 * 2 创建这个deploymentreplicas := int32(dd.Spec.Replicas * 2)image := dd.Spec.Imagedeployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name:      deployName,Namespace: namespace,},Spec: appsv1.DeploymentSpec{Replicas: &replicas,Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": deployName},},Template: corev1.PodTemplateSpec{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": deployName},},Spec: corev1.PodSpec{Containers: []corev1.Container{{Name:  "mainc",Image: image,},},},},},}// 创建 Deployment_, err = clientset.AppsV1().Deployments(namespace).Create(ctx, deployment, metav1.CreateOptions{})if err != nil {fmt.Fprintf(os.Stderr, "Error creating deployment: %v\n", err)return err}fmt.Printf("✅ Created deployment: %s with replicas: %d\n", deployName, replicas)return nil
}

案例go代码,各位看官自取: 通过网盘分享的文件:crd-demo.zip 链接: https://pan.baidu.com/s/180C5MeTm-6ede_PFa9VdeQ?pwd=f42d 提取码: f42d

四、分享视频

        这里大家通过观看我的视频讲解,可能更加细致:

B站最清晰讲解,k8s(kubernetes)数据流核心底层逻辑-通俗易懂

五、总结

        通过本篇博文,你会恍然大悟,原来K8S的架构、数据流的底层原理也不过如此. 整体的玩法就是这么玩的, 不再云里雾里,不再觉得这玩意是庞然大物了。

        无论是运维还是开发,我们可以把K8S做为白盒去看待,遇到问题,也能知道怎么定位、怎么排查、怎么去开发CRD。

        希望能给大家一些思路上的一些启发~

http://www.dtcms.com/a/272471.html

相关文章:

  • AI进化论06:连接主义的复兴——神经网络的“蛰伏”与“萌动”
  • k8s集群--证书延期
  • 项目进度管控依赖Excel,如何提升数字化能力
  • 调度器与闲逛进程详解,(操作系统OS)
  • UI前端与数字孪生结合案例分享:智慧城市的智慧能源管理系统
  • 数据结构笔记10:排序算法
  • Windows 本地 使用mkcert 配置HTTPS 自签名证书
  • Java并发 - 阻塞队列详解
  • XSS(ctfshow)
  • 文心大模型4.5开源测评:保姆级部署教程+多维度测试验证
  • 图书管理系统(完结版)
  • PyCharm 中 Python 解释器的添加选项及作用
  • 创始人IP如何进阶?三次关键突破实现高效转化
  • QT解析文本框数据——详解
  • pycharm中自动补全方法返回变量
  • 自动化脚本配置网络IP、主机名、网段
  • React封装过哪些组件-下拉选择器和弹窗表单
  • 常用的.gitconfig 配置
  • 【显示模块】嵌入式显示与触摸屏技术理论
  • HarmonyOS AI辅助编程工具(CodeGenie)UI生成
  • 时序数据库的存储之道:从数据特性看技术要点
  • 使用深度学习框架yolov8训练监控视角下非机动车电动车头盔佩戴检测数据集VOC+YOLO格式11999张4类别步骤和流程
  • UEditor 对接 秀米 手机编辑器流程与问题
  • ClickHouse 查看正在执行的SQL查询
  • Django--01基本请求与响应流程
  • go go go 出发咯 - go web开发入门系列(四) 数据库ORM框架集成与解读
  • selenium跳转到新页面时如何进行定位
  • 前缀和|差分
  • S7-1200 与 S7-300 PNS7-400 PN UDP 通信 TIA 相同项目
  • 缓存一致性问题(Cache Coherence Problem)是什么?