kubeadm构建k8s源码阅读环境
目标
前面看了minikube的源码了解到其本质是调用了kubeadm来启动k8s集群,并没有达到最初看代码的目的。 所以继续看看kubeadm的代码,看看能否用来方便地构建源码调试环境。
k8s源码编译
kubeadm源码在k8s源码库中,所以要先克隆k8s源码。之前用minikube创建的k8s集群是v1.32.0

所以克隆v1.32.0版本的代码
git clone --branch v1.32.0 --single-branch https://github.com/kubernetes/kubernetes.git
考虑到后续可能要改改源码并保存下来,所以我fork了master分支去编译。
在Makefile中可以看到如何编译

在编译前先修改.go-version文件中go的版本, 默认里面指定的是1.23.4。k8s源码中要求go版本是1.23.0以上就可以了,我的是1.23.3不想重新下载go压缩包了,所以改了。
修改shell脚本让其输出编译的命令,看不到命令我不是很放心

通过环境变量指定版本号,修改完版本后执行编译命令编译kubeadm
export KUBE_GIT_VERSION=v1.32.0
export KUBE_GIT_COMMIT=$(git rev-parse --short HEAD)
export KUBE_GIT_TREE_STATE=clean
make all DBG=1 WHAT=cmd/kubelet
可以看到编译的命令已经带上了禁用优化的参数了

kubeadm在一开始检查的过程中会调用kubelet获取版本号,所以我把全部二进制文件都编译了
export KUBE_GIT_VERSION=v1.32.0
export KUBE_GIT_COMMIT=$(git rev-parse --short HEAD)
export KUBE_GIT_TREE_STATE=clean
make all DBG=1
调试命令如下
dlv --headless --listen=:8005 --api-version=2 --accept-multiclient --log exec /root/kubernetes/_output/bin/kubeadm -- init --cri-socket unix:///run/containerd/containerd.sock
vscode配置如下
{// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"name": "kubeadm","type": "go","request": "attach","mode": "remote","remotePath": "/root/kubernetes","port": 8005,"host": "4c","showLog": true,"trace": "verbose","substitutePath": [{"from": "${workspaceFolder}","to": "/root/kubernetes"},{"from": "/Users/wy/wy/workspace_go/pkg/mod", // 本地路径"to": "/root/go_path/pkg/mod" // 远程路径},]}]
}
调试源码前准备工作
PATH环境变量
将前面编译源码生成二进制文件的目录添加到PATH环境变量中,因为kubeadm需要调用kubelet
containerd启用cri插件
kubeadm中,contianerd是默认的容器运行时,containerd需要启动cri插件,随docker启动的contianerd默认是禁用了cri插件的。
containerd配置cri插件官方文档地址:
https://github.com/containerd/containerd/blob/main/docs/cri/config.md
docker version命令查看docker版本是27.5.0, containerd对应的版本是1.7.25
containerd配置文件默认位置是/etc/containerd/config.toml
在配置文档中有完整的配置文件样例且有大量的注释,有需要的时候再来看,但这不是我们目前要关注的

使用命令生成默认配置
# 备份旧配置
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
# 生成默认配置
containerd config default > /etc/containerd/config.toml
修改的值如下,v1.32.0版本k8s要求是3.10版本,没有的话会触发下载镜像的操作
SystemdCgroup = true
sandbox_image = "registry.k8s.io/pause:3.10"
需要重启containerd。由于我docker服务是apt安装的,估计是自动装的containerd,是由systemd托管的。所以重启命令如下
sudo systemctl restart containerd
下载k8s相关镜像
由于网络问题,你得先下载k8s的镜像
# 查看需要下载的镜像
kubeadm config images list
镜像清单如下
registry.k8s.io/kube-apiserver:v1.32.1
registry.k8s.io/kube-controller-manager:v1.32.1
registry.k8s.io/kube-scheduler:v1.32.1
registry.k8s.io/kube-proxy:v1.32.1
registry.k8s.io/coredns/coredns:v1.12.0
registry.k8s.io/pause:3.10
registry.k8s.io/etcd:3.5.17-0
然后用github action大法下载镜像,下载完成后,检查镜像
ctr --namespace k8s.io images list | awk '{print $1}'
镜像已经拉取成功了

配置kubelet
kubeadm init命令会使用systemctl命令重启kubelet,所以需要编写 /etc/systemd/system/kubelet.service
但是具体怎么写,需要通过官方提供的apt命令安装kubeadm后,使用kubeadm命令安装一次k8s,然后查看kubelet.service可以看到具体的脚本是怎么写的

可以看到需要编写两个文件,分别是kubelet.service以及 10-kubeadm.conf
编写/etc/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/home/
Wants=network-online.target
After=network-online.target[Service]
ExecStart=/root/kubernetes/_output/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10
KillMode=process
Delegate=yes[Install]
WantedBy=multi-user.target
编写/etc/systemd/system/kubelet.service.d/10-kubeadm.conf,可以看到这里指定了config.yaml文件
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/root/kubernetes/_output/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
然后启用该service
systemctl enable kubelet.service
调试源码
主要是想搞清kubeadm是怎么部署k8s集群的,看看能不能用来调试代码。
代码入口是/cmd/kubeadm/kubeadm.go
kubeadm源码调试
kebeadm中将部署集群的每个步骤抽象成phase组成一个数组,然后遍历这个数组,运行每个phase对应的函数,当phase数组遍历完了,kubeadm init命令就完成了

在cmd命令初始化的时候,可以看到有哪些phase

其实在磊哥的《深入剖析Kubernetes》中有写了kubeadm的部署原理,只是有些东西还是得自己看看才知道

很明显,kubelet的启动对应是NewKubeletStartPhase,随后的NewWaitControlPlanePhase中等待apiserver启动完成。
... 省略
initRunner.AppendPhase(phases.NewKubeletStartPhase())
initRunner.AppendPhase(phases.NewWaitControlPlanePhase())
... 省略
当 Kubelet 运行时,它会持续监视参数staticPodPath指定的目录,如果有新的 Pod 配置文件加入,Kubelet 会自动创建 Pod。这种启动Pod的方式叫静态启动,该过程不需要 apiserver 参与调度。
kubeadm生成的kubelet的配置文件中有个staticPodPath选项,值如下
staticPodPath: /etc/kubernetes/manifests
该目录下的yaml都是kubeadm生成的,共四个yaml文件,分别是
etcd.yamlkube-apiserver.yamlkube-controller-manager.yamlkube-scheduler.yaml
kubelet源码调试
正常情况下,kubelet是不会有问题的,如果在kubeadm init命令执行过程提示 kubelet失败,得看kubelet到底报啥错了。查看kubelet日志
journalctl -u kubelet
如果从日志上没看出是啥问题,可以调试下源码看看。当代码运行到启动kubelet时,启动所需要的配置文件都已经生成了,所以调试kubelet的时候,可以先退出kubeadm的调试。
调试kubelet需要先把kubeadm init的代码运行到下图中的位置,然后kill掉调试kubeadm init的dlv进程,然后调试kubelet进程

调试前需要先停止kubelet,并禁用自动重启
systemctl disable kubelet.service
systemctl stop kubelet
用下面的命令调试kubelet源码
KUBELET_CONFIG_ARGS="--config=/var/lib/kubelet/config.yaml"
KUBELET_KUBECONFIG_ARGS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.10"
dlv --headless --listen=:8005 --api-version=2 --accept-multiclient --log exec /root/kubernetes/_output/bin/kubelet -- $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
变量$KUBELET_EXTRA_ARGS是由文件/etc/default/kubelet中定义的,默认是空值,所以我没有赋值。
读取pod文件的代码位置如下,config.NewSourceFile中会启动goroutinue监听/etc/kubernetes/manifests的文件,如果文件有改动,会往一个 channel发送数据

最后在kubelet的主循环中处理channel中的数据,创建、更新或者删除pod

启动的代码东西太多了,等需要的时候再回来看,此处只是记录下代码的位置
kube-scheduler源码调试
回到主题上,k8s相关的组件都是通过静态pod的方式启动的,要了解一个pod,就得看它的yaml文件,以kube-scheduler组件为例

可以看到是使用宿主机的网络命名空间,那么就可以直接使用执行源码编译的二进制文件启动kube-schedualer代替静态pod的方式来实现断点调试了。
先用kubeadm init命令把k8s部署成功,默认情况下,出于安全原因,不会在控制平面节点上调度 Pod。想要在控制平面节点上调度需要执行下面的命令
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
然后删除对应的kube-scheduler.yaml,由于kubelet是持续监视着/etc/kubernetes/manifests的,如果文件有变动,则执行对应的操作,例如我删除了yaml文件,kubelet会删除掉对应的pod
删除yaml文件后已经看不到kube-scheduler了,coredns是要等到CNI插件安装成功后才会启动,这里先不管

参考yaml中的启动命令,使用下面的命令调试
dlv --headless --listen=:8005 --api-version=2 --accept-multiclient --log exec /root/kubernetes/_output/bin/kube-scheduler -- --authentication-kubeconfig=/etc/kubernetes/scheduler.conf --authorization-kubeconfig=/etc/kubernetes/scheduler.conf --bind-address=127.0.0.1 --kubeconfig=/etc/kubernetes/scheduler.conf --leader-elect=false
参数说明
--authentication-kubeconfig负责身份认证,确保kube-scheduler可以连接 API Server。--authorization-kubeconfig负责权限授权,确保kube-scheduler有权限调度 Pod。--leader-elect=false因为没有多个节点,所以把leader选举关掉
可以看到已经能够成功断点调试了,SchedulerOne函数就是对Pod进行调度的入口函数。

相关文章:
kubeadm构建k8s源码阅读环境
目标 前面看了minikube的源码了解到其本质是调用了kubeadm来启动k8s集群,并没有达到最初看代码的目的。 所以继续看看kubeadm的代码,看看能否用来方便地构建源码调试环境。 k8s源码编译 kubeadm源码在k8s源码库中,所以要先克隆k8s源码。之…...
【Flink快速入门-1.Flink 简介与环境配置】
Flink 简介与环境配置 实验介绍 在学习一门新的技术之前,我们首先要了解它的历史渊源,也就是说它为什么会出现,它能够解决什么业务痛点。所以本节我们的学习目的是了解 Flink 的背景,并运行第一个 Flink 程序,对它有…...
硬盘修复后,文件隐身之谜
在数字时代,硬盘作为数据存储的重要载体,承载着无数珍贵的信息与回忆。然而,当硬盘遭遇故障并经过修复后,有时我们会遇到这样一个棘手问题:硬盘修复后,文件却神秘地“隐身”,无法正常显示。这一…...
如何处理网络连接错误导致的fetch失败?
处理由于网络连接错误导致的 fetch 失败通常涉及捕获网络错误并提供适当的用户反馈。以下是如何在 Vue 3 中实现这一点的步骤和示例。 一、更新 useFetch 函数 在 useFetch 函数中,需要捕获网络错误,并设置相应的错误信息。网络错误通常会抛出一个 TypeError,可以根据这个…...
Qt之设置QToolBar上的按钮样式
通常给QAction设置icon后,菜单栏的菜单项和工具栏(QToolBar)上对应的按钮会同时显示该icon。工具栏还可以使用setToolButtonStyle函数设置按钮样式,其参数为枚举值: enum ToolButtonStyle {ToolButtonIconOnly,ToolButtonTextOnly,ToolButtonTextBesideIcon,ToolButtonTe…...
责任链模式(Chain Responsibility)
一、定义:属于行为型设计模式,包含传递的数据、创建处理的抽象和实现、创建链条、将数据传递给顶端节点; 二、UML图 三、实现 1、需要传递处理的数据类 import java.util.Date;/*** 需要处理的数据信息*/ public class RequestData {priva…...
docker安装 mongodb
1、拉取镜像 docker run -dit --name mongo \ -p 17017:27017 \ -e MONGO_INITDB_ROOT_USERNAMEadmin \ -e MONGO_INITDB_ROOT_PASSWORD2018 \ --restartalways \ mongo2、进入容器 docker exec -it mongo bash 3、进入mongo ./bin/mongosh -u admin -p 2018 --authenticat…...
RabbitMQ 从入门到精通:从工作模式到集群部署实战(五)
#作者:闫乾苓 系列前几篇: 《RabbitMQ 从入门到精通:从工作模式到集群部署实战(一)》:link 《RabbitMQ 从入门到精通:从工作模式到集群部署实战(二)》: lin…...
salesforce SF CLI 数据运维经验分享
SF CLI data默认使用bulk api v2, 数据操作效率有了极大的提高。 Bulk api v2的优点: 执行结果可以很直观的从Bulk Data Load Jobs中看到。相较于bulk api v1,只能看到job执行in progress,或者closed的状态,有了很大的改善。执行…...
5.2Internet及其作用
5.2.1Internet概述 Internet称为互联网,又称英特网,始于1969年的美国ARPANET(阿帕网),是全球性的网络。 互连网指的是两个或多个不同类型的网络通过路由器等网络设备连接起来,形成一个更大的网络结构。互连…...
【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记
第十一届省赛真题代码部分 前言赛题代码思路笔记竞赛板配置内部振荡器频率设定键盘工作模式跳线扩展方式跳线 建立模板明确设计要求和初始状态显示功能部分数据界面第一部分第二部分第三部分调试时发现的问题 参数设置界面第一部分第二部分和第四部分第三部分和第五部分 按键功…...
数据分析:企业数字化转型的金钥匙
引言:数字化浪潮下的数据金矿 在数字化浪潮席卷全球的背景下,有研究表明,只有不到30%的企业能够充分利用手中掌握的数据,这是否让人深思?数据已然成为企业最为宝贵的资产之一。然而,企业是否真正准备好从数…...
网络工程师 (23)OSI模型层次结构
前言 OSI(Open System Interconnect)模型,即开放式系统互联模型,是一个完整的、完善的宏观模型,它将计算机网络体系结构划分为7层。 OSI七层模型 1. 物理层(Physical Layer) 功能:负…...
DeepSeek添加知识库
1、下载dify 项目地址:https://github.com/langgenius/dify 2、通过docker安装 端口报错 修改端口 .env文件下所有80端口替换成了其它端口 执行正常了 查看 docker容器 <...
2、k8s的cni网络插件和基本操作命令
kube-prxoy属于节点组件,网络代理,实现服务的自动发现和负载均衡。 k8s的内部网络模式 1、pod内的容器于容器之间的通信。 2、一个节点上的pod之间的通信,docker0网桥直接通信。 3、不同节点上的pod之间的通信: 通过物理网卡的…...
Next.js简介:现代 Web 开发的强大框架(ChatGPT-4o回答)
prompt: 你是一位专业的技术博客撰稿人,你将写一篇关于介绍next.js这个开发框架的技术博文,语言是中文,风格专业严谨,用词自然、引人入胜且饶有趣味 在现代 Web 开发的世界中,选择合适的框架可以显著提升开发效率和应用…...
【DeepSeek:国产大模型的崛起与ChatGPT的全面对比】
DeepSeek:国产大模型的崛起与ChatGPT的全面对比 目录 引言DeepSeek的技术架构 2.1 混合专家(MoE)架构2.2 动态路由机制2.3 训练数据与成本 ChatGPT的技术架构 3.1 Transformer架构3.2 训练数据与成本 性能对比 4.1 推理能力4.2 语言处理4.3…...
input 超出maxlength限制后,输入框变红
一、前言 最近收到产品的一个需求:输入框限制了maxlength“11”,需要在输入第12位时,输入框变红;当然,第12位是不能真正输入到输入框中的。 二、实现难点 其实,单纯的要监听 字母和数字以及字符 还是比较容…...
Docker 构建镜像并搭建私人镜像仓库教程
构建镜像教程 步骤 1:安装 Docker #在安装 Docker 之前,建议先更新系统软件包。 sudo yum update -y # 移除旧的Docker版本和Podman、runc软件包及其相关依赖。 yum remove -y docker docker-client docker-client-latest docker-ce-cli docker-commo…...
doris:MySQL Dump
Doris 在 0.15 之后的版本已经支持通过 mysqldump 工具导出数据或者表结构 使用示例 导出 导出 test 数据库中的 table1 表:mysqldump -h127.0.0.1 -P9030 -uroot --no-tablespaces --databases test --tables table1 导出 test 数据库中的 table1 表结构&am…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
raid存储技术
1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划,涵盖存储系统的布局、数据存储策略等,它明确数据如何存储、管理与访问,为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...
2025-06-01-Hive 技术及应用介绍
Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具,它为海量结构化数据提供类 SQL 的查询能力…...
