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使用
    controller-manager学习三部曲之一:通过脚本文件寻找程序入口_第1张图片

本篇概览

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

编译文件

  • 执行make命令会用到Makefile文件,里面会调用hack/make-rules/build.sh
    controller-manager学习三部曲之一:通过脚本文件寻找程序入口_第2张图片
  • 打开build.sh,里面调用了kube::golang::build_binaries
    controller-manager学习三部曲之一:通过脚本文件寻找程序入口_第3张图片
  • 在golang.sh文件中查看kube::golang::build_binaries方法,下面摘取最重要的内容,可见构建用的参数来自KUBE_ALL_TARGETS这个全局变量,咱们先记住这个KUBE_ALL_TARGETS,然后继续看构建的逻辑
    controller-manager学习三部曲之一:通过脚本文件寻找程序入口_第4张图片
  • 这时候应该看到了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
  • 然后调用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
  • 最终在build_some_binaries方法中完成编译构建
    controller-manager学习三部曲之一:通过脚本文件寻找程序入口_第5张图片
  • 至此,输入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[@]}"
)
  • 选其中一个来看看,这里选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)"
  • 现在终于清楚了,在编译构建kubernetes源码的时候,kube-controller-manager模块是用go install命令编译cmd/kube-controller-manager包下的源码生成的,也就是说这个服务的入口在下图位置
    controller-manager学习三部曲之一:通过脚本文件寻找程序入口_第6张图片

启动命令分析

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

查看启动命令

  • 找个现成的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
  • 可见controller-manager的pod名是kube-controller-manager-hedy,执行以下命令即可查看看pod的详细信息
kubectl describe pod kube-controller-manager-hedy -n kube-system
  • 上述命令会输出大量信息,这里只展示我们最关心的内容,即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
  • 可见启动controller-manager的时候,kubernetes向其传递了大量的flag
  • 至此,本篇的任务已经完成,咱们找到了应用的入口,也清楚了启动时会大概传入哪些参数,在接下来的文章该一同去深入学习controller-manager的源码了

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

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

你可能感兴趣的:(client-go,云原生,kubernetes实战,kubernetes,go,controller)