背景
时代太快,容器化编排技术已经成为每个运维工作者,甚至是研发人员不得不具备的一个技能。除了知道如何使用,我们还可以去学习下kubernetes这个开源项目的具体实现。这样不仅能提升我们对kubernetes的理解,同时也能学习到kubernetes的代码设计模式以及编码技巧。
动机
我作为一个”精力旺盛,手活极好,盯屏能力极强”的运维工作人员,希望不被时代所淘汰,赶紧掏出小本本,学习学习,保证”锅”的平稳落地。
思路
整个系列我将基于kubernetes是如何创建一个deployment的全过程的角度来分析下kubernetes的核心机制。我将分析该命令所经历的每一个组件的源码实现。
概况
开始整个系列之前,请大家务必多kubernetes有个基本了解,如果不了解的,请转官网:kubernetes.io
整个kubernetes的集群信息如下:
- 版本:1.12.4
- 网络插件:calico-3.10.3
- docker:
部署方式:kubernetes.io/zh/docs/set…
集群地址:
- 10.110.100.168
- 10.110.100.125
我们创建第一个应用,执行命令
kubectl apply -f deploy.yaml
复制代码
另外我们看看deploy.yaml的文件,文件中的信息我都会注释
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
## pod的副本数
replicas: 1
## 这里标签选择pod模板
selector:
matchLabels:
app: nginx
## pod的模板
template:
metadata:
labels:
app: nginx
spec:
containers:
## 容器名
- name: nginx
## 镜像地址
image: nginx
ports:
- containerPort: 80
复制代码
执行上面文件后,我们将看看经过k8s处理后的yaml文件是怎样的,具体新增了哪些字段?
apiVersion: apps/v1
kind: Deployment
metadata:
## 注释
annotations:
## deployment的版本
deployment.kubernetes.io/revision: "1"
## 上次应用的配置情况
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-deployment","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx","name":"nginx","ports":[{"containerPort":80}]}]}}}}
## 创建时间
creationTimestamp: "2021-03-14T14:01:04Z"
##
generation: 1
## 标签
labels:
app: nginx
## “Server-side Apply”的功能,追踪对象字段的变化
## 管理的字段
managedFields:
- apiVersion: apps/v1
## 管理的字段类型
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
.: {}
f:app: {}
f:spec:
f:progressDeadlineSeconds: {}
f:replicas: {}
f:revisionHistoryLimit: {}
f:selector: {}
f:strategy:
f:rollingUpdate:
.: {}
f:maxSurge: {}
f:maxUnavailable: {}
f:type: {}
f:template:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:containers:
k:{"name":"nginx"}:
.: {}
f:image: {}
f:imagePullPolicy: {}
f:name: {}
f:ports:
.: {}
k:{"containerPort":80,"protocol":"TCP"}:
.: {}
f:containerPort: {}
f:protocol: {}
f:resources: {}
f:terminationMessagePath: {}
f:terminationMessagePolicy: {}
f:dnsPolicy: {}
f:restartPolicy: {}
f:schedulerName: {}
f:securityContext: {}
f:terminationGracePeriodSeconds: {}
## 字段管理器
manager: kubectl
## 管理器的操作
operation: Update
## 操作时间
time: "2021-03-14T14:01:04Z"
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:deployment.kubernetes.io/revision: {}
f:status:
f:availableReplicas: {}
f:conditions:
.: {}
k:{"type":"Available"}:
.: {}
f:lastTransitionTime: {}
f:lastUpdateTime: {}
f:message: {}
f:reason: {}
f:status: {}
f:type: {}
k:{"type":"Progressing"}:
.: {}
f:lastTransitionTime: {}
f:lastUpdateTime: {}
f:message: {}
f:reason: {}
f:status: {}
f:type: {}
f:observedGeneration: {}
f:readyReplicas: {}
f:replicas: {}
f:updatedReplicas: {}
## 字段管理器
manager: kube-controller-manager
## 操作方式
operation: Update
## 操作时间
time: "2021-03-14T14:01:31Z"
## deployment的名称
name: nginx-deployment
## deployment的命名空间
namespace: default
## deployment的当前资源版本号,这个用于inform的进行版本对比使用
resourceVersion: "197755"
uid: e2947357-c425-4f5c-a624-3327cc62ad30
## 资源期望
spec:
## 进程终止时间
progressDeadlineSeconds: 600
## 副本数
replicas: 1
## 保留历史版本数量
revisionHistoryLimit: 10
## 选择pod标签
selector:
matchLabels:
app: nginx
## 发布策略
strategy:
## 滚动发布
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
## pod的模板
template:
metadata:
creationTimestamp: null
## 这里的labels要与上面选中的一致
labels:
app: nginx
## pod的期望状态
spec:
## 容器配置
containers:
- image: nginx
## 镜像拉取策略
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
## 中断日志
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
## dns策略
dnsPolicy: ClusterFirst
## 重启策略,一般配合liveness使用
restartPolicy: Always
## 该pod的调度器名称
schedulerName: default-scheduler
## 安全上下文
securityContext: {}
## 当删除pod的时,最长等待终止时间。
terminationGracePeriodSeconds: 30
## deployment的最终状态,我们通过kubectl get deploy 所看到的信息
status:
## 可用副本数
availableReplicas: 1
## 条件
conditions:
- lastTransitionTime: "2021-03-14T14:01:31Z"
lastUpdateTime: "2021-03-14T14:01:31Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2021-03-14T14:01:04Z"
lastUpdateTime: "2021-03-14T14:01:31Z"
message: ReplicaSet "nginx-deployment-7848d4b86f" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
复制代码
里面的变化,重点说明下managerFields,它的出现肯定是有一定依据的,我们需要明白的是,Apply 这个操作,它并不是简简单单地将某个值给 (Set) 设定到你期望的值,因为实际的情况是很复杂的,简单无脑地将值改动,会造成严重的后果,所以 Apply 实际上是一种 (Merge) 合并的操作,也就是它要考虑当前对象的状况和之前对象的设定来与你现在的设定做一个合并。否则很容易出现冲突的情况。
具体可以参考:kubernetes.io/zh/docs/ref…
这里我还是整体的给大家讲解下kubernetes创建一个deployment的全过程。
大家也可以通过这篇文章:cloud.tencent.com/developer/a… 了解先。
首先我们先看一张图。
整个过程首先从kubectl发起,以kubelet生成相应的pod为结束。
-
kubelet
- 验证和生成器
- API 版本协商与 API 组
- 发送http请求到apiserver
-
apiserver
- 客户端身份认证
- 授权
- 准入控制
- 数据反序列化,存入etcd
-
etcd
- 获得数据
- 同步数据
- 保存数据
-
controller-manager
- deploy-controller
- ReplicaSet-controller
- pod-controller
-
scheduler
- 预选策略
- 优选策略
- 绑定节点
-
kubelet
- pod数据同步
- 初始化,资源,卷
- CRI和pause容器
- CNI和pod网络
- 容器启动过程
结束语
后续我将出一个系列的文章,如果大家感兴趣可以关注我。在这个过程中必然会有很多不严谨的地方,还希望大家包涵,大家吸取精华(如果有的话),去其糟粕。我的微信号:liyakuaile1991