• controller-manager学习三部曲之一:通过脚本文件寻找程序入口


    欢迎访问我的GitHub

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

    关于《controller-manager学习三部曲》

    • 《controller-manager学习三部曲》是欣宸原创的kubernetes深入学习系列之一,在前面的《client-go实战》系列中,咱们通过反复的实践,对controller的开发和使用已经很熟练了,接下来就该称热打铁去研究kubernetes的源码,了解它的controller是如何设计和实现的,这里面一定有很多值得学习的地方,掌握了这些,反过来又能对咱们自己开发controller有所帮助,所以,别犹豫啦,一起来看看kubernetes的controller吧
    • 整个《controller-manager学习三部曲》由以下三部分内容组成
    1. 寻找入口:kubernetes博大精深,那么多代码和脚本,如何找到controller-manager的代码,以及程序启动的入口?
    2. 源码分析:这个整个系列的核心,面对诸多controller,kubernetes如何做到这两件事情:第一,将启动命令中的各种flag(cobra中的flag)传递给各个controller,第二,创建和启动每个controller
    3. 典型controller:controller-manager只负责将controller启动,具体的controller功能是各不相同的,这里会挑一个典型的controller来学习
    • 注意:整个系列用的源码来自kubernetes的master分支,go版本是1.20

    关于controller-manager

    • 下图是kube-system这个namespace下面所有pod的信息,黄色箭头所指即controller-manager,它负责诸多内置controller的创建和启动,还有就是从启动命令中搜集参数,以便各controller使用
      在这里插入图片描述

    本篇概览

    • 本文是《三部曲》的第一篇,咱们要从kubernetes源码中找到controller-manager的入口,以便后续的学习
    • controller-manager是个典型的go模块工程,所以结构和脚本也是咱们常见的格式(只不过内容多了些)
    • 本篇从Makefile入手开始分析,找到编译controller-manager的详细逻辑,没什么难度,只是几个脚本的阅读而已

    编译文件

    • 执行make命令会用到Makefile文件,里面会调用hack/make-rules/build.sh
      在这里插入图片描述
    • 打开build.sh,里面调用了kube::golang::build_binaries
      在这里插入图片描述
    • 在golang.sh文件中查看kube::golang::build_binaries方法,下面摘取最重要的内容,可见构建用的参数来自KUBE_ALL_TARGETS这个全局变量,咱们先记住这个KUBE_ALL_TARGETS,然后继续看构建的逻辑
      在这里插入图片描述
    • 这时候应该看到了build_binaries_for_platform,可见binaries的内容会被分别存入statics和nonstatics
    kube::golang::build_binaries_for_platform() {
      # This is for sanity.  Without it, user umasks can leak through.
      umask 0022
    
      local platform=$1
    
      local -a statics=()
      local -a nonstatics=()
      local -a tests=()
    
      for binary in "${binaries[@]}"; do
        if [[ "${binary}" =~ ".test"$ ]]; then
          tests+=("${binary}")
          kube::log::info "    ${binary} (test)"
        elif kube::golang::is_statically_linked_library "${binary}"; then
          statics+=("${binary}")
          kube::log::info "    ${binary} (static)"
        else
          nonstatics+=("${binary}")
          kube::log::info "    ${binary} (non-static)"
        fi
      done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 然后调用build_some_binaries方法
      if [[ "${#statics[@]}" != 0 ]]; then
        build_args=(
          -installsuffix=static
          ${goflags:+"${goflags[@]}"}
          -gcflags="${gogcflags}"
          -asmflags="${goasmflags}"
          -ldflags="${goldflags}"
          -tags="${gotags:-}"
        )
        CGO_ENABLED=0 kube::golang::build_some_binaries "${statics[@]}"
      fi
    
      if [[ "${#nonstatics[@]}" != 0 ]]; then
        build_args=(
          ${goflags:+"${goflags[@]}"}
          -gcflags="${gogcflags}"
          -asmflags="${goasmflags}"
          -ldflags="${goldflags}"
          -tags="${gotags:-}"
        )
        kube::golang::build_some_binaries "${nonstatics[@]}"
      fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 最终在build_some_binaries方法中完成编译构建
      在这里插入图片描述
    • 至此,输入make后的大致流程算是知道了,接下来该回头看看那个重要的参数KUBE_SERVER_TARGETS

    关于KUBE_ALL_TARGETS

    • 前面曾经提到,构建参数来自KUBE_ALL_TARGETS,这里来看下这个变量里面是啥,定义在golang.sh文件中,如下所示,是由多个变量组成的
    readonly KUBE_ALL_TARGETS=(
      "${KUBE_SERVER_TARGETS[@]}"
      "${KUBE_CLIENT_TARGETS[@]}"
      "${KUBE_TEST_TARGETS[@]}"
      "${KUBE_TEST_SERVER_TARGETS[@]}"
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 选其中一个来看看,这里选KUBE_SERVER_TARGETS,可见是每个需要构建的模块的路径
    kube::golang::server_targets() {
      local targets=(
        cmd/kube-proxy
        cmd/kube-apiserver
        cmd/kube-controller-manager
        cmd/kubelet
        cmd/kubeadm
        cmd/kube-scheduler
        vendor/k8s.io/component-base/logs/kube-log-runner
        vendor/k8s.io/kube-aggregator
        vendor/k8s.io/apiextensions-apiserver
        cluster/gce/gci/mounter
      )
      echo "${targets[@]}"
    }
    
    IFS=" " read -ra KUBE_SERVER_TARGETS <<< "$(kube::golang::server_targets)"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 现在终于清楚了,在编译构建kubernetes源码的时候,kube-controller-manager模块是用go install命令编译cmd/kube-controller-manager包下的源码生成的,也就是说这个服务的入口在下图位置
      在这里插入图片描述

    启动命令分析

    • 找到了程序的入口,还要了解启动服务时的参数,这样在阅读源码时,面对各种不同入参的处理,也能做到心里有数,找准关键代码去看

    查看启动命令

    • 找个现成的kubernetes系统,看一下真正运行的controller-manager的启动命令是啥样的
    • 以我自己测试用的kubernetes环境为例,先查看pod名
    kubectl get pods -n kube-system
    NAME                           READY   STATUS    RESTARTS       AGE
    coredns-78fcd69978-jztff       1/1     Running   6 (35d ago)    125d
    coredns-78fcd69978-ts7gq       1/1     Running   6 (35d ago)    125d
    etcd-hedy                      1/1     Running   6 (35d ago)    125d
    kube-apiserver-hedy            1/1     Running   7 (35d ago)    125d
    kube-controller-manager-hedy   1/1     Running   11 (30h ago)   125d
    kube-proxy-2qx6k               1/1     Running   6              125d
    kube-scheduler-hedy            1/1     Running   11 (30h ago)   125d
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 可见controller-manager的pod名是kube-controller-manager-hedy,执行以下命令即可查看看pod的详细信息
    kubectl describe pod kube-controller-manager-hedy -n kube-system
    
    • 1
    • 上述命令会输出大量信息,这里只展示我们最关心的内容,即controller-manager的启动命令
        Command:
          kube-controller-manager
          --allocate-node-cidrs=true
          --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf
          --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf
          --bind-address=0.0.0.0
          --client-ca-file=/etc/kubernetes/pki/ca.crt
          --cluster-cidr=100.64.0.0/10
          --cluster-name=kubernetes
          --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
          --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
          --controllers=*,bootstrapsigner,tokencleaner
          --experimental-cluster-signing-duration=876000h
          --feature-gates=TTLAfterFinished=true,EphemeralContainers=true
          --kubeconfig=/etc/kubernetes/controller-manager.conf
          --leader-elect=true
          --port=0
          --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
          --root-ca-file=/etc/kubernetes/pki/ca.crt
          --service-account-private-key-file=/etc/kubernetes/pki/sa.key
          --service-cluster-ip-range=10.96.0.0/22
          --use-service-account-credentials=true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 可见启动controller-manager的时候,kubernetes向其传递了大量的flag
    • 至此,本篇的任务已经完成,咱们找到了应用的入口,也清楚了启动时会大概传入哪些参数,在接下来的文章该一同去深入学习controller-manager的源码了

    你不孤单,欣宸原创一路相伴

    1. Java系列
    2. Spring系列
    3. Docker系列
    4. kubernetes系列
    5. 数据库+中间件系列
    6. DevOps系列
  • 相关阅读:
    代码随想录算法训练营Day59 | 503.下一个更大元素II 42. 接雨水
    推荐几个接私活的利器
    01-docker基础
    Linux、Unix、WindowsC语言理解查看字节序排序
    官宣|Apache Flink 1.20 发布公告
    浏览器---chrome 高级调试技巧汇总(后期继续添加)
    Pytest----如何通过filterwarnings配置不显示告警或将告警报错
    【趣学Python算法100例】兔子产子
    App自动化测试框架设计与实现
    vim相关介绍(三)
  • 原文地址:https://blog.csdn.net/boling_cavalry/article/details/133407485