当你创建了一个 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 ...
随机推荐
- shell脚本基本使用教程
sh脚本的固定第一行 #!/bin/bash 变量 #!/bin/bash var1=1 var2=2 var3=$[var1+var2] echo "$var3" 传达参数 sh ...
- Clusternet - 新一代开源多集群管理与应用治理项目
作者 徐迪,腾讯云容器技术专家. 汝英哲,腾讯云高级产品经理. 摘要 在过去的数年里,云计算领域经历了多次巨大的变革,当前越来越多的组织将应用部署在本地和云上的多个基础设施平台上,这些平台可能是两个公 ...
- C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)
两个对象是否为同一个对象:是看两个对象是否指向堆中的同一块内存. 1.使用object.ReferenceEquals() class Program { static void Main(strin ...
- UWP使用命名管道与桌面程序通信 (C#)
关于UWP的历史,其起源是Microsoft在Windows 8中引入的Metro apps.(后来又被称作Modern apps, Windows apps, Universal Windows A ...
- java基本数据类型转换字符串
1.基本数据类型转换为字符串 int t1 = 2; String t2 = Integer.toString(t1); 2.字符串转换为基本数据类型 int t3 = Integer.parseIn ...
- 自建纯净谷歌搜索「GitHub 热点速览 v.21.35」
作者:HelloGitHub-小鱼干 虽然 Google 搜索的结果不如百度搜索结果那般广告丛生,但是对于一心只想找到匹配结果的我们而言,推广的信息条目能免则免.whoogle-search 便是一个 ...
- IDEA常用设置及推荐插件
IDEA常用设置及推荐插件 本文主要记录IDEA的一些常用设置,IDEA与Eclipse的常用快捷键对比及推荐一些好用的插件. 基本设置 设置界面风格及修改外部UI尺寸大小 打开IDEA时设置不重新打 ...
- 字符型:char
字符型:char 字符变量的定义和输出 字符变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节.在给字符型变量赋值时,需要用一对因为半角格式的单引号(' ')把字 ...
- Linux 安装 Harbor 私有镜像仓库
下载 最新发行:https://github.com/goharbor/harbor/releases # 下载文件 wget https://github.com/goharbor/harbor/r ...
- 集合框架3-Arrays 类
Arrays 和 Collections是分别操作数组和集合的两个工具类.今天就来对 Arrays 中的内容作个总结. 一.Arrays 类概述 Arrays 类位于 java.util包中.Arra ...