前言
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路径之间的关系。
通过如下命令可以查看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的路径结构。
实质上在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
如果要通过kubectl创建一个deployment,kubectl会发起对apiserver调用。会发起三个接口如图2-1所示。/openapi/v2发起对apiserver的认证,认证之后会调用/apis/apps/v1/namespaces/default/deployments/nginx-deployment 接口,接口的对应关系,如图2-2。
调用资源接口获取资源信息的目录是为了对YAML文件进行比较,如果没有创建资源对象则会调用创建资源对象接口进行创建。如果已经创建资源对象,并且YAML有变更,则走更新流程。
创建资源对象接口会创建对应到资源对应,这里面其实对应了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所示:
调试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所示。
cmd.NewDefaultKubectlCommand其实Cobra对应的函数,Kubernetes源码中cmd下都是调用Cobra对命令行参数进行解析。
如果要调试调用什么接口,其实最简单就是针对golang自带的net库net/http/request.go中NewRequest方法进行下断点。这样就可以获取执行kubectl的所有过程,较为简单。
总结
- kubectl与apiserver的管理,kubectl是封装apiserver对Kubernetes进行管理的一个工具。
- 可以通过“github.com.cnpmjs.org”对github拉取代码进行加速。
- apiserver分为Alpha版本、Beta版本、稳定版三个版本。