前言
2021 年开始第 4 个月了,因为工作过于忙碌的缘故很久没有开始文章的写作。其实始终以来我集体把写文章这件事,当作推动本人学习成长的一种形式。
这篇文章是 kubernetes 源码剖析的第一个主题,后续会陆续更新。大抵的大纲为 client-go、控制器、调度器、自定义控制器、operator、网络几个方面。
当操作资源与 apiserver 进行通信时,平时都是间接编写 YAML 资源文件,通过 kubectl 来提交创立对应等资源对象,那么它到底是怎么将 YAML 转换成对应等 API 进行通信?
Kubernetes 版本:v1.8.5
源码地址:https://github.com/kubernetes/
1.apiserver 介绍
k8s 通过 kube-apiserver 组件提供 API Server 性能,API Server 性能提供对 k8s 各类资源对象的减少改查,例如 pod、rc、Service 等 HTTP Rest 接口。
1.1 API 版本介绍
理解 api 版本之前,首先要理解 api 的申明。Kubernetes 在不同的 API 门路反对多个 API 版本, 例如 /api/v1 或者 /apis/batch。版本可分为:
- Alpha 版本:例如 v1alpha1、v1alpha3 示意该版本,默认状况下是被禁用的,能够随时删除对性能的反对,要慎用。
- Beta 版本:例如 v1beta1、v2beta1、v2beta2 示意该版本,默认状况下是启用的,示意代码曾经测试通过,然而对象的语义可能随后版本中不兼容。
- 稳固版本:例如 v1 示意稳定版,也会呈现在后续版本中。
1.2 API 门路介绍
在理解 api 版本信息后,能够一起来理解下 Kubernetes API Server 门路之间的关系。
<center> 图 1 -1 查看接口门路 </center>
通过如下命令能够查看 api 接口门路,如图 1 - 1 所示:
#kubectl get --raw /
除了通过以上命令能够看到 api 接口门路以外,还能够应用 proxy 进行代理,通过接口方式进行拜访。
#kubectl proxy
Starting to serve on 127.0.0.1:8001
代理后间接能够关上 http://localhost:8001/ 查看接 …
通过查看门路后,能够把门路做一个性能上的细分,通过图 1 - 2 能够看出 API 的门路构造。
<center> 图 1 -2 门路解析 </center>
本质上在 Kubernetes 集群中,一个 API 对象在 Etcd 中的残缺资源门路,是由 Group(API 组)、Version(API 组)和 Resource(API 资源类型)三个局部组成的。
Kubernetes API 反对通过规范 HTTP:GET、POST、PUT 和 DELETE 在指定 PATH 门路上创立、更新、删除和检索操作,并应用 JSON 作为默认的数据交互格局。
2. 解析 YAML 与 apiserver 之间的关系
通过第 1 节中,理解到 api 的分层,版本关系。那么接下来一起理解下 YAML 和 apiserver 之间的关系。
2.1 编写一个简略的 yaml 文件
比方当初要创立一个 nginx1.7.9 的 pod,那么能够编写一个编排的 YAML。创立一个 Deployment 对象,那么能够这么写:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
- apiVersion:api 的分组及版本,例如“apps/v1”,apps 对应分组,v1 对应版本。
- kind: 对象资源类型,这里有 Job、Service 等,也能够自定义资源。而资源 Resource 通常是小写复数,例如“Deployment”则是“deployments”。
- metadata·name:对应名称
- spec·replicas: 启动 pod 对应的个数。
- spec·template·containers·image: 拉取镜像地址。
- spec·template·containers·name:pod 对应名称。
- spec·template·containers·ports: pod 对应端口。
2.2 解析 kubectl 与 apiserver 的关系
kubectl 其实就是一个和 kubernetes apiserver 交互的一个命令行工具。通常状况通过 YAML 对 pod 进行编排,或者通过 YAML 创立资源时, 能够通过 kubectl 进行交互。命令如下:
#kubectl apply -f nginx.yaml
<center> 图 2 -1 通过 kubectl 创立 deployment</center>
如果要通过 kubectl 创立一个 deployment,kubectl 会发动对 apiserver 调用。会发动三个接口如图 2 - 1 所示。/openapi/v2 发动对 apiserver 的认证,认证之后会调用 /apis/apps/v1/namespaces/default/deployments/nginx-deployment 接口,接口的对应关系,如图 2 -2。
<center> 图 2 -2 查看资源对象接口 </center>
调用资源接口获取资源信息的目录是为了对 YAML 文件进行比拟,如果没有创立资源对象则会调用创立资源对象接口进行创立。如果曾经创立资源对象,并且 YAML 有变更,则走更新流程。
<center> 图 2 -3 创立资源对象接口 </center>
创立资源对象接口会创立对应到资源对应,这外面其实对应了 2.1 大节中的内容。apiVersion 是“apps/v1”对应接口分组与版本,kind 为“Deployment”对应“deployments”。
3. 源码调试
要调试源码之前首先要下载源代码,下载源代码能够通过 git clone 进行下载。然而因为 git clone 的地址是“github.com”, 在国内拜访 github 比较慢。能够应用镜像地址进行下载, 其实就是把“github.com”更换为“github.com.cnpmjs.org”,命令如下:
下载 kubernetes
#git clone https://github.com.cnpmjs.org/kubernetes/
切换到对应版本
#cd kubernetes
#git checkout v1.8.5
3.1 kubernetes 源码构造介绍
下载源码后,能够进入源码目录。能够通过 tree 看一下源码构造:
localhost:kubernetes edz$ tree . -L 1
.
├── BUILD.bazel -> build/root/BUILD.root
├── CHANGELOG
├── CHANGELOG.md -> CHANGELOG/README.md
├── CONTRIBUTING.md
├── Godeps
├── LICENSE
├── Makefile -> build/root/Makefile
├── Makefile.generated_files -> build/root/Makefile.generated_files
├── OWNERS
├── OWNERS_ALIASES
├── README.md
├── SECURITY_CONTACTS
├── SUPPORT.md
├── WORKSPACE -> build/root/WORKSPACE
├── _output
├── api
├── build
├── cluster
├── cmd
├── code-of-conduct.md
├── docs
├── go.mod
├── go.sum
├── hack
├── logo
├── pkg
├── plugin
├── staging
├── test
├── third_party
├── translations
└── vendor
k8s 源码自身是一个很大的我的项目,能够来看看对应源码目录构造的一些用处:
目录名 | 介绍 |
---|---|
build | 编译脚本目录 |
CHANGELOG | 变更记录文档 |
cmd | 对应命令行管理工具, 例如 kubeadm、kubectl、kubelet 等 |
staging | 曾经分库的我的项目 |
pkg | 各种性能包的实现代码 |
vendor | 依赖包 |
3.2 配置 IDE
在这里 IDE 抉择 Goland,如果要配置调试 kubectl 能够配置如图 3 - 1 所示:
<center> 图 3 -1 配置 goland</center>
调试 kubectl 比较简单,图中“Program argyments”执行 kubectl 对应的参数。理论命令如下:
kubectl apply -f /Users/edz/Desktop/kubernetes/nginx.yaml
3.3 调试
如果要调试 kubectl 能够在 cmd/kubectl/kubectl.go 中下断点,比方针对“command := cmd.NewDefaultKubectlCommand()”进行一个断点,如图 3 - 2 所示。
<center> 图 3 -2 kubectl 调试 </center>
cmd.NewDefaultKubectlCommand 其实 Cobra 对应的函数,Kubernetes 源码中 cmd 下都是调用 Cobra 对命令行参数进行解析。
如果要调试调用什么接口,其实最简略就是针对 golang 自带的 net 库 net/http/request.go 中 NewRequest 办法进行下断点。这样就能够获取执行 kubectl 的所有过程,较为简单。
<center> 图 3 -3 net 调试 </center>
总结
- kubectl 与 apiserver 的治理,kubectl 是封装 apiserver 对 Kubernetes 进行治理的一个工具。
- 能够通过“github.com.cnpmjs.org”对 github 拉取代码进行减速。
- apiserver 分为 Alpha 版本、Beta 版本、稳定版三个版本。