当你创建了一个 Deployment 时,Kubernetes 内部发生了什么?
我们通常使用 kubectl 来管理我们的 Kubernetes 集群。 当我们需要一个 Nginx 服务时,可以使用以下命令来创建:
kubectl create deployment nginx --image nginx
返回:
deployment.apps/nginx created
稍等片刻,一个包含 Nginx 容器的 Pod 就会启动成功。那么在我们执行在上述命令后,Kubernetes 内部发生了什么呢?
核心组件
在介绍内部发生了什么之前,我们首先需要了解一下以下 4 个核心组件在 Kubernetes 集群中的角色和作用:
kube-apiserver: Kubernetes API 服务器验证并配置 API 对象的数据, 这些对象包括 pods、services 等。 API 服务器为 REST 操作提供服务,并为集群的共享状态提供前端, 所有其他组件都通过该前端进行交互。
kube-controller-manager: 运行控制器进程的控制平面组件。 从逻辑上讲,每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行,所以它会被称作为
manager。它包含 DeploymentController、ReplicaSetController、JobController 等一系列控制器。kube-scheduler: 控制平面组件,负责监视新创建的、未指定运行节点(node)的 Pods,选择节点让 Pod 在上面运行。 调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。
kubelet: 一个在集群中每个节点(node)上运行的代理。 它保证容器(containers)都运行在 Pod 中。 kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。
简化的核心过程

在了解上述核心组件的角色后,我们来看一下 Kubernetes 内部到底发生了哪些事情:
用户通过 kubectl 向 kube-apiserver 发起一个创建 Deployment 对象的请求。
kube-apiserver 在对上述请求进行认证(authn)、授权(authz)、准入控制(admission control)、验证(validation)等一系列操作后,会创建一个 Deployment 对象。
上述的 Deployment 创建事件,会被 DeploymentController 通过其内部的 DeploymentInformer 监听到,然后根据 DeploymentController 内部设定的逻辑,它将会创建一个 ReplicaSet 对象。源码 syncDeployment
上述的 ReplicaSet 创建事件,会被 ReplicaSetController 通过其内部的 ReplicaSetInformer 监听到,然后根据 ReplicaSetController 内部设定的逻辑,它将创建一个 Pod 对象,而此时 Pod 的 Spec.nodeName 字段的值为空;源码 syncReplicaSet
上述的 Pod 创建事件,会被 Scheduler 通过其内部的 PodInformer 监听到,Scheduler 会根据其内部的调度算法,选择一个合适的 Node 节点,例如 node-A,并更新 Pod 的 Spec.nodeName 字段。源码 Schedule
上述的 Pod 更新事件,会被 node-A 节点上 kubelet 感知到,它会发现自己的 nodeName 和 Pod 的 Spec.nodeName 相匹配,接着 kubelet 将按照一定的步骤顺序启动 Pod 中的容器,并将容器已启动的信息写入 Pod 的 Status 中。源码 syncPod
如上所述,DeploymentController、ReplicaSetController 等许多独立的控制循环都是通过监听 kube-apiserver 上对象的变化进行通信,而这些变化会通过各种 Informer 触发事件,执行其对应的业务逻辑。之所以这么设计,是为了减少对 apiserver 的压力。
kubelet 创建 Pod 的过程
Pod 的创建的过程大体上可以分为 4 个步骤(实际上为 7 步,这里省略了前置的 3 个步骤。源码 SyncPod):
为 Pod 创建沙盒,即基础设施容器 Infrastructure Container(镜像名称为 k8s.gcr.io/pause),它的主要作用是创建并共享进程命名空间。
创建 Pod 规格中指定的临时容器 Ephemeral Containers(Alpha 功能,默认不开启),临时容器是一种特殊的容器,该容器在现有 Pod 中临时运行,以便完成用户发起的操作,例如故障排查。 你可以使用临时容器来检查服务,而不是用它来构建应用程序。
创建 Pod 规格中指定的初始化容器 Init Containers,初始化容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。
依次创建 Pod 规格中指定的常规容器 Containers。
参考
- 张磊《深入剖析 Kubernetes》
- Michael Hausenblas, Stefan Schimanski《Kubernetes 编程》
- Kubernetes 组件
- 详解 Kubernetes Deployment 的实现原理
- 详解 Kubernetes ReplicaSet 的实现原理
- 详解 Kubernetes Pod 的实现原理
- Kubernetes CRI 分析 - kubelet 创建 Pod 分析
更多
更多经典示例请参考:https://github.com/jxlwqq/kubernetes-examples
当你创建了一个 Deployment 时,Kubernetes 内部发生了什么?的更多相关文章
- 使用ArrayList时代码内部发生了什么(jdk1.7)?
前言 ArrayList(这里的ArrayList是基于jdk1.7)是在项目中经常使用的集合类,例如我们从数据库中查询出一组数据.这篇文章不去剖析它的继承和实现,只是让我们知道实例化及增删改查时它的 ...
- 当一个 Pod 被调度时,Kubernetes 内部发生了什么?
在 Kubernetes 中,调度是指将 Pod 放置到合适的 Node 上,然后对应 Node 上的 Kubelet 才能够运行这些 Pod . kube-scheduler 是集群控制平面的主要组 ...
- 一个web项目在myeclipse中add deployment时无法被识别出来的原因
当我们一个web项目,在myeclipse中,add deployment时,可能发现,根本无法被识别成web项目,可能的原因有: 1. 项目的properties ->Myeclipse ...
- 第一次通过AVD Manager创建了一个虚拟设备,但是在Android Studio运行程序时却无设备可选
第一次通过AVD Manager创建了一个虚拟设备,但是在Android Studio运行程序时却无设备可选 原因是adb.exe未运行起来 至于adb.exe未正常运行起来的原因多半是5037端口被 ...
- 在Kubernetes上运行SAP UI5应用(下): 一个例子体会Kubernetes内容器的高可用性和弹性伸缩
上一篇文章 在Kubernetes上运行SAP UI5应用(上),我介绍了如何在Docker里运行一个简单的SAP UI5应用,并且已经成功地将一个包含了这个UI5应用的docker镜像上传到Dock ...
- Kubernetes — 从0到1:搭建一个完整的Kubernetes集群
准备工作 首先,准备机器.最直接的办法,自然是到公有云上申请几个虚拟机.当然,如果条件允许的话,拿几台本地的物理服务器来组集群是最好不过了.这些机器只要满足如下几个条件即可: 满足安装 Docker ...
- 手动部署一个单节点kubernetes
目录 简要说明 安装环境说明 部署 生成相关证书 证书类型说明 安装cfssl证书生成工具 生成CA证书 生成Kubernetes master节点使用的证书 生成kubectl证书 生成kube-p ...
- 创建第一个Maven项目
-----------------------siwuxie095 创建第一个 Maven 项目 1.打开 Ec ...
- 使用Visual Studio Code创建第一个ASP.NET Core应用程序
全文翻译自:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 这篇文章将向你展示如何在Mac上写出你的第一个A ...
随机推荐
- RHEL 7 “There are no enabled repos” 的解决方法
RHEL 7 "There are no enabled repos" 的解决方法 [root@system1 Desktop]# yum install squidLoaded ...
- springmvc学习日志四
一.回顾 1.文件上传 1.1引入fileupload的jar包 1.2在springmvc的配置文件中引入CommonsMutilpartResolver文件上传解析器 1.3在控制层在写入代码 2 ...
- 天翼云安装jdk(注意有坑)
1.下载jdk8 查看Linux位数,到oracle官网下载对应的jdk ① sudo uname --m 确认32位还是64位 ② https://www.oracle.com/technetwo ...
- SpringBoot配置Cors跨域请求
一.同源策略简介 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 什么是源 源[or ...
- 2021年哪个低代码平台更值得关注?T媒体盘点国内主流低代码厂商
2020年圣诞前夜,国内知名创投科技媒体T媒体旗下的T研究发布了2020中国低代码平台指数测评报告.报告除了对国内低代码行业现状进行总结外,还对主流低代码厂商的市场渗透和曝光进行测评. 报告认为,低代 ...
- VSCode——滚动鼠标控制字体大小
第一步:找到设置 文件-->首选项-->设置 第二步:打开settings.json文件 第三步:在settings.json文件中添加 "editor.mouseWheelZo ...
- shell循环语句for
1.方式1 for i in {list[0]} {list[1]} .. do 执行命令 done 2.方式2(三要素循环) for (( 初始值; 判断值; 步长; )) do 执行命令 done
- Centos7最小化系统安装_配置
本文总结了作者使用centos最小化安装时,碰到的问题和解决方案. 网络问题.作者使用虚拟机安装时,网卡并没有激活.操作: 1 cd /etc/sysconfig/network-script 2 v ...
- 前端路由原理之 hash 模式和 history 模式
什么是路由? 个人理解路由就是浏览器 URL 和页面内容的一种映射关系. 比如你看到我这篇博客,博客的链接是一个 URL,而 URL 对应的就是我这篇博客的网页内容,这二者之间的映射关系就是路由. 其 ...
- IS(上升子序列)
前言: 这是一篇杂题选讲+作者口胡的博客,不喜勿喷. 正文: 提示:在阅读时请留意加粗的字体是"极长"还是"最长". 今天改题时碰到了一道关于线段树 ...