【K8s源码品读】004:Phase 1 - kubectl - 发送创建Pod请求的实现细节

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 理解kubectl是怎么向kube-apiserver发送请求的

聚焦目标

理解kubectl是怎么向kube-apiserver发送请求的

目录

  1. 向kube-apiserver发送请求
  2. RESTful客户端是怎么创建的
  3. Object是怎么生成的
  4. 发送post请求
  5. kubectl第一阶段源码阅读总结

send request

// 在RunCreate函数中,关键的发送函数
obj, err := resource.
                NewHelper(info.Client, info.Mapping).
                DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
                WithFieldManager(o.fieldManager).
                Create(info.Namespace, true, info.Object)

// 进入create函数,查看到
m.createResource(m.RESTClient, m.Resource, namespace, obj, options)

// 对应的实现为
func (m *Helper) createResource(c RESTClient, resource, namespace string, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) {
   
    return c.Post().
        NamespaceIfScoped(namespace, m.NamespaceScoped).
        Resource(resource).
        VersionedParams(options, metav1.ParameterCodec).
        Body(obj).
        Do(context.TODO()).
        Get()
}

/*

到这里,我们发现了2个关键性的定义:
1. RESTClient 与kube-apiserver交互的RESTful风格的客户端
2. runtime.Object 资源对象的抽象,包括Pod/Deployment/Service等各类资源

*/

RESTful Client

我们先来看看,与kube-apiserver交互的Client是怎么创建的

// 从传入参数来看,数据来源于Info这个结构
r.Visit(func(info *resource.Info, err error) error{
   })

// 而info来源于前面的Builder,前面部分都是将Builder参数化,核心的生成为Do函数
r := f.NewBuilder().
        Unstructured().
        Schema(schema).
        ContinueOnError().
        NamespaceParam(cmdNamespace).DefaultNamespace().
        FilenameParam(enforceNamespace, &o.FilenameOptions).
        LabelSelectorParam(o.Selector).
        Flatten().
        Do()

// 大致看一下这些函数,我们可以在Unstructured()中看到getClient函数,其实这就是我们要找的函数
func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) 

// 从返回值来看,client包括默认的REST client和配置选项
NewClientWithOptions(client, b.requestTransforms...)

// 这个Client会在kubernetes项目中大量出现,它是与kube-apiserver交互的核心组件,以后再深入。

Object

Object这个对象是怎么获取到的呢?因为我们的数据源是来自文件的,那么我们最直观的想法就是FileVisitor

func (v *FileVisitor) Visit(fn VisitorFunc) error {
   
    // 省略读取这块的代码,底层调用的是StreamVisitor的逻辑
    return v.StreamVisitor.Visit(fn)
}

func (v *StreamVisitor) Visit(fn VisitorFunc) error {
   
    d := yaml.NewYAMLOrJSONDecoder(v.Reader, 4096)
    for {
   
        // 这里就是返回info的地方
        info, err := v.infoForData(ext.Raw, v.Source)
  }
}

// 再往下一层看,来到mapper层,也就是kubernetes的资源对象映射关系
func (m *mapper) infoForData(data []byte, source string) (*Info, error){
   
  // 这里就是我们返回Object的地方,其中GVK是Group/Version/Kind的缩写,后续我们会涉及
  obj, gvk, err := m.decoder.Decode(data, nil, nil)
}

这时,我们想回头去看,这个mapper是在什么时候被定义的?

// 在Builder初始化中,我们就找到了
func (b *Builder) Unstructured() *Builder {
   
    b.mapper = &mapper{
   
        localFn:      b.isLocal,
        restMapperFn: b.restMapperFn,
        clientFn:     b.getClient,
    // 我们查找资源用到的是这个decoder
        decoder:      &metadataValidatingDecoder{
   unstructured.UnstructuredJSONScheme},
    }
    return b
}

// 逐层往下找,对应的Decode方法的实现,就是对应的数据解析成data:
func (s unstructuredJSONScheme) decode(data []byte) (runtime.Object, error) {
   
    // 细节暂时忽略
}

Post

了解了REST ClientObject的大致产生逻辑后,我们再回过头来看发送的方法

// RESTful接口风格中,POST请求对应的就是CREATE方法
c.Post().
        NamespaceIfScoped(namespace, m.NamespaceScoped).
        Resource(resource).
        VersionedParams(options, metav1.ParameterCodec).
        Body(obj).
        Do(context.TODO()). 
        Get() 

// Do方法,发送请求
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
   
        result = r.transformResponse(resp, req)
    })

// Get方法,获取请求的返回结果,用来打印状态
switch t := out.(type) {
   
    case *metav1.Status:
        if t.Status != metav1.StatusSuccess {
   
            return nil, errors.FromObject(t)
        }
    }

Summary

到这里我们对kubectl的功能有了初步的了解,希望大家对以下的关键内容有所掌握:

  1. 命令行采用了cobra库,主要支持7个大类的命令;
  2. 掌握Visitor设计模式,这个是kubectl实现各类资源对象的解析和校验的核心;
  3. 初步了解RESTClientObject这两个对象,它们是贯穿kubernetes的核心概念;
  4. 调用逻辑
    1. cobra匹配子命令
    2. 用Visitor模式构建Builder
    3. 用RESTClient将Object发送到kube-apiserver
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
7天前
|
存储 Kubernetes 调度
【赵渝强老师】什么是Kubernetes的Pod
Pod 是 Kubernetes 中的基本逻辑单位,代表集群上的一个应用实例。它可以由一个或多个容器组成,并包含数据存储和网络配置等资源。Pod 支持多种容器执行环境,如 Docker。Kubernetes 使用 Pod 管理容器,具有简化部署、方便扩展和调度管理等优点。视频讲解和图示详细介绍了 Pod 的组成结构和使用方式。
|
1月前
|
Kubernetes API 调度
k8s中节点无法启动Pod
【10月更文挑战第3天】
82 6
|
7天前
|
存储 Kubernetes Docker
【赵渝强老师】Kubernetes中Pod的基础容器
Pod 是 Kubernetes 中的基本单位,代表集群上运行的一个进程。它由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。基础容器负责维护 Pod 的网络空间,对用户透明。文中附有图片和视频讲解,详细介绍了 Pod 的组成结构及其在网络配置中的作用。
【赵渝强老师】Kubernetes中Pod的基础容器
|
7天前
|
运维 Kubernetes Shell
【赵渝强老师】K8s中Pod的临时容器
Pod 是 Kubernetes 中的基本调度单位,由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。临时容器用于故障排查和性能诊断,不适用于构建应用程序。当 Pod 中的容器异常退出或容器镜像不包含调试工具时,临时容器非常有用。文中通过示例展示了如何使用 `kubectl debug` 命令创建临时容器进行调试。
|
7天前
|
Kubernetes 调度 容器
【赵渝强老师】K8s中Pod中的业务容器
Pod 是 Kubernetes 中的基本调度单元,由一个或多个容器组成。除了业务容器,Pod 还包括基础容器、初始化容器和临时容器。本文通过示例介绍如何创建包含业务容器的 Pod,并提供了一个视频讲解。示例中创建了一个名为 "busybox-container" 的业务容器,并使用 `kubectl create -f firstpod.yaml` 命令部署 Pod。
|
7天前
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
|
8天前
|
弹性计算 Kubernetes Perl
k8s 设置pod 的cpu 和内存
在 Kubernetes (k8s) 中,设置 Pod 的 CPU 和内存资源限制和请求是非常重要的,因为这有助于确保集群资源的合理分配和有效利用。你可以通过定义 Pod 的 `resources` 字段来设置这些限制。 以下是一个示例 YAML 文件,展示了如何为一个 Pod 设置 CPU 和内存资源请求(requests)和限制(limits): ```yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image:
|
10天前
|
Kubernetes Nacos 微服务
探讨了在Kubernetes中使用Nacos v2.2.3时,强制删除Pod后Pod仍存在的常见问题
本文深入探讨了在Kubernetes中使用Nacos v2.2.3时,强制删除Pod后Pod仍存在的常见问题。通过检查Pod状态、事件、配置,调整Nacos和Kubernetes设置,以及手动干预等步骤,帮助开发者快速定位并解决问题,确保服务稳定运行。
32 2
|
7天前
|
Kubernetes 应用服务中间件 nginx
【赵渝强老师】Kubernetes命令行管理工具:kubectl
kubectl 是 Kubernetes 的命令行工具,用于管理和操作 Kubernetes 集群。本文通过视频讲解和具体示例,介绍了 kubectl 的常用命令,包括显示 Pod 信息、创建 Deployment 和 Service、更新和回滚 Deployment、以及删除资源等操作。
|
7天前
|
存储 Kubernetes 调度
深入理解Kubernetes中的Pod与Container
深入理解Kubernetes中的Pod与Container
15 0