k8s入坑之路(2)kubernetes架构详解
每个微服务通过 Docker 进行发布,随着业务的发展,系统中遍布着各种各样的容器。于是,容器的资源调度,部署运行,扩容缩容就是我们要面临的问题。
基于 Kubernetes 作为容器集群的管理平台被广泛应用,今天我们一起来看看 Kubernetes 的架构中有那些常用的组件以及运行原理。
Kubernetes 架构概述
Kubernetes 是用来管理容器集群的平台。既然是管理集群,那么就存在被管理节点,针对每个 Kubernetes 集群都由一个 Master 负责管理和控制集群节点。
我们通过 Master 对每个节点 Node 发送命令。简单来说,Master 就是管理者,Node 就是被管理者。
Node 可以是一台机器或者一台虚拟机。在 Node 上面可以运行多个 Pod,Pod 是 Kubernetes 管理的最小单位,同时每个 Pod 可以包含多个容器(Docker)。

通常我们都是通过 kubectl 对 Kubernetes 下命令的,它通过 APIServer 去调用各个进程来完成对 Node 的部署和控制。
APIServer 的核心功能是对核心对象(例如:Pod,Service,RC)的增删改查操作,同时也是集群内模块之间数据交换的枢纽。
它包括了常用的 API,访问(权限)控制,注册,信息存储(etcd)等功能。在它的下面我们可以看到 Scheduler,它将待调度的 Pod 绑定到 Node 上,并将绑定信息写入 etcd 中。
etcd 包含在 APIServer 中,用来存储资源信息。接下来就是 Controller Manager 了,如果说 Kubernetes 是一个自动化运行的系统,那么就需要有一套管理规则来控制这套系统。
Controller Manager 就是这个管理者,或者说是控制者。它包括 8 个 Controller,分别对应着副本,节点,资源,命名空间,服务等等。
紧接着,Scheduler 会把 Pod 调度到 Node 上,调度完以后就由 kubelet 来管理 Node 了。
kubelet 用于处理 Master 下发到 Node 的任务(即 Scheduler 的调度任务),同时管理 Pod 及 Pod 中的容器。
在完成资源调度以后,kubelet 进程也会在 APIServer 上注册 Node 信息,定期向 Master 汇报 Node 信息,并通过 cAdvisor 监控容器和节点资源。
由于,微服务的部署都是分布式的,所以对应的 Pod 以及容器的部署也是。为了能够方便地找到这些 Pod 或者容器,引入了 Service(kube-proxy)进程,它来负责反向代理和负载均衡的实施。
上面就是 Kubernetes 架构的简易说明,涉及到了一些核心概念以及简单的信息流动。
将一些功能收录到了 APIServer 中,这个简图比官网的图显得简单一些,主要是方便大家记忆。
后面我们会用一个简单的例子,带大家把 Kubernetes 的概念的由来做深入的了解。
从一个例子开始
假设使用 Kubernetes 部署 Tomcat 和 MySQL 服务到两个 Node 上面。其中 Tomcat 服务生成两个实例也就是生成两个 Pod,用来对其做水平扩展。

这里我们假设 Kubernetes 和 Docker 的安装都已经完成,并且镜像文件都已经准备好了。重点看 Kubernetes 如何部署和管理容器。
kubectl 和 APIServer
既然我们要完成上面的例子,接下来就要部署两个应用。
首先,根据要部署的应用建立 Replication Controller(RC)。RC 是用来声明应用副本的个数,也就是 Pod 的个数。
按照上面的例子,Tomcat 的 RC 就是 2,MySQL 的 RC 就是 1。
由于 kubectl 作为用户接口向 Kubernetes 下发指令,那么指令是通过“.yaml”的配置文件编写的。
- 1 apiVersion: V1
- 2 kind: ReplicationController
- 3 metadata:
- 4 name: mysql#RC的名称,全局唯一
- 5 spec:
- 6 replicas:1 #Pod 副本的期待数量
- 7 selector :
- 8 app: mysql
- 9 template: #Pod模版,用这个模版来创建Pod
- 10 metadata:
- 11 labels:
- 12 app:mysql#Pod副本的标签
- 13 spec:
- 14 containers:#容器定义部分
- 15 -name:mysql
- 16 Image:mysql#容器对应的DockerImage
- 17 Ports:
- 18 -containerPort:3306#容器应用监听的端口号
- 19 Env:#注入容器的环境变量
- 20 -name:MYSQL_ROOT_PASSWORD
- 21 Value:”123456”
从上面的配置文件可以看出,需要对这个 RC 定义一个名字,以及期望的副本数,以及容器中的镜像文件。然后通过 kubectl 作为客户端的 cli 工具,执行这个配置文件。
通过 kubectl 执行 RC 配置文件
执行了上面的命令以后,Kubernetes 会帮助我们部署副本 MySQL 的 Pod 到 Node。

Kubernetes API Server 通过一个名为 kube-apiserver 的进程提供服务,该进程运行在 Master 上。
可以通过 Master 的 8080 端口访问 kube-apiserver 进程,它提供 REST 服务。
因此可以通过命令行工具 kubectl 来与 Kubernetes APIServer 交互,它们之间的接口是 RESTful API。
APIServer 的架构从上到下分为四层:
API 层:主要以 REST 方式提供各种 API 接口,针对 Kubernetes 资源对象的 CRUD 和 Watch 等主要 API,还有健康检查、UI、日志、性能指标等运维监控相关的 API。
访问控制层:负责身份鉴权,核准用户对资源的访问权限,设置访问逻辑(Admission Control)。
注册表层:选择要访问的资源对象。PS:Kubernetes 把所有资源对象都保存在注册表(Registry)中,例如:Pod,Service,Deployment 等等。
- etcd 数据库: 保存创建副本的信息。用来持久化 Kubernetes 资源对象的 Key-Value 数据库。
当 kubectl 用 Create 命令建立 Pod 时,是通过 APIServer 中的 API 层调用对应的 RESTAPI 方法。
之后会进入权限控制层,通过 Authentication 获取调用者身份,Authorization 获取权限信息。
AdmissionControl 中可配置权限认证插件,通过插件来检查请求约束。例如:启动容器之前需要下载镜像,或者检查具备某命名空间的资源。
还记得 mysql-rc.yaml 中配置需要生成的 Pod 的个数为 1。到了 Registry 层会从 CoreRegistry 资源中取出 1 个 Pod 作为要创建的 Kubernetes 资源对象。
然后将 Node,Pod 和 Container 信息保存在 etcd 中去。这里的 etcd 可以是一个集群,由于里面保存集群中各个 Node/Pod/Container 的信息,所以必要时需要备份,或者保证其可靠性。
Controller Manager,Scheduler 和 kubelet
前面通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 上面建立 Pod 和 Container。
在 APIServer,经过 API 调用,权限控制,调用资源和存储资源的过程。实际上还没有真正开始部署应用。
这里需要 Controller Manager,Scheduler 和 kubelet 的协助才能完成整个部署过程。
在介绍他们协同工作之前,要介绍一下在 Kubernetes 中的监听接口。从上面的操作知道,所有部署的信息都会写到 etcd 中保存。

Kubernetes 就是用这种 List-Watch 的机制保持数据同步的,如上图:
这里有三个 List-Watch,分别是 kube-controller-manager(运行在Master),kube-scheduler(运行在 Master),kublete(运行在 Node)。他们在进程已启动就会监听(Watch)APIServer 发出来的事件。
kubectl 通过命令行,在 APIServer 上建立一个 Pod 副本。
这个部署请求被记录到 etcd 中,存储起来。
当 etcd 接受创建 Pod 信息以后,会发送一个 Create 事件给 APIServer。
由于 Kubecontrollermanager 一直在监听 APIServer 中的事件。此时 APIServer 接受到了 Create 事件,又会发送给 Kubecontrollermanager。
Kubecontrollermanager 在接到 Create 事件以后,调用其中的 Replication Controller 来保证 Node 上面需要创建的副本数量。
上面的例子 MySQL 应用是 1 个副本,Tomcat 应用是两个副本。一旦副本数量少于 RC 中定义的数量,Replication Controller 会自动创建副本。总之它是保证副本数量的 Controller。PS:扩容缩容的担当。
在 Controller Manager 创建 Pod 副本以后,APIServer 会在 etcd 中记录这个 Pod 的详细信息。例如在 Pod 的副本数,Container 的内容是什么。
同样的 etcd 会将创建 Pod 的信息通过事件发送给 APIServer。
由于 Scheduler 在监听(Watch)APIServer,并且它在系统中起到了“承上启下”的作用
“承上”是指它负责接收创建的 Pod 事件,为其安排 Node;“启下”是指安置工作完成后,Node 上的 kubelet 服务进程接管后继工作,负责 Pod 生命周期中的“下半生”。
换句话说,Scheduler 的作用是将待调度的 Pod 按照调度算法和策略绑定到集群中 Node 上,并将绑定信息写入 etcd 中。
Scheduler 调度完毕以后会更新 Pod 的信息,此时的信息更加丰富了。除了知道 Pod 的副本数量,副本内容。还知道部署到哪个 Node 上面了。
同样,将上面的 Pod 信息更新到 etcd 中,保存起来。
etcd 将更新成功的事件发送给 APIServer。
注意这里的 kubelet 是在 Node 上面运行的进程,它也通过 List-Watch 的方式监听(Watch)APIServer 发送的 Pod 更新的事件。
实际上,在第 9 步的时候创建 Pod 的工作就已经完成了。
为什么 kubelete 还要一直监听呢?
原因很简单,假设这个时候 kubectl 发命令,需要把原来的 MySQL 的 1 个 RC 副本扩充成 2 个。那么这个流程又会触发一遍。
作为 Node 的管理者 kubelet 也会根据最新的 Pod 的部署情况调整 Node 端的资源。
又或者 MySQL 应用的 RC 个数没有发生变化,但是其中的镜像文件升级了,kubelet 也会自动获取最新的镜像文件并且加载。

Controller Manager
它分为 8 个 Controller,上面我们介绍了 Replication Controller,这里我们把其他几个都列出来,就不展开描述了。
Controller Manager
它分为 8 个 Controller,上面我们介绍了 Replication Controller,这里我们把其他几个都列出来,就不展开描述了。
Scheduler 与 kubelet
说白了,Scheduler 是 boss,kubelet 是干活的工人,他们都通过 APIServer 进行信息交换。
Service 和 kubelet
经历上面一系列的过程,终于将 Pod 和容器部署到 Node 上了。
Service 与后端 Pod 副本集群之间是通过 Label Selector 来实现连接的。Service 所访问的这一组 Pod 都会有同样的 Label,通过这样的方法知道这些 Pod 属于同一个组。
写 MySQL 服务的配置文件(mysql-svc.yaml)如下:
- 1 apiVersion : v1
- 2 kind: Service #说明创建资源对象的类型是Service
- 3 metadata:
- 4 name: mysql#Service全局唯一名称
- 5 spec:
- 6 prots:
- 7 -port: 3306#Service的服务端口号
- 8 selector:#Service对应的Pod标签,用来给Pod分类
- 9 app: mysql
按照惯例运行 kubectl,创建 Service:
再用 getsvc 命令检查 Service 信息:
因此在 Kubernetes 集群内部,可以在任意 Node 上发起对 Service 的访问请求。
先生成配置文件,myweb-rc.yaml 看看:
- 1 apiVersion: V1
- 2 kind: ReplicationController
- 3 metadata:
- 4 name: myweb#RC的名称,全局唯一
- 5 spec:
- 6 replicas:2#Pod 副本的期待数量,这里的数量是2,需要建立两个Tomcat的副本
- 7 selector :
- 8 app: myweb
- 9 template: #Pod模版,用这个模版来创建Pod
- 10 metadata:
- 11 labels:
- 12 app:myweb#Pod副本的标签
- 13 spec:
- 14 containers: #容器定义部分
- 15 -name:mysql
- 16 Image:kubeguide/tomcat-app:v1#容器对应的DockerImage
- 17 Ports:
- 18 -containerPort:8080#容器应用监听的端口号
在 kubectl 中使用 Create 建立 myweb 副本。
副本创建完毕以后,创建对应的服务配置文件 myweb-svc.yaml。
- 1 apiVersion : v1
- 2 kind: Service #说明创建资源对象的类型是Service
- 3 metadata:
- 4 name: myweb#Service全局唯一名称
- 5 spec:
- 6 prots:
- 7 -port: 8080#Service的服务端口号
- 8 nodePort: 30001#这个就是外网访问Kubernetes内部应用的端口。
- 9 selector: #Service对应的Pod标签,用来给Pod分类
- 10 app: myweb
同样在 kubectl 中运行 Create 命令,建立 Service 资源。
如果按照上面的配置,部署了两个 Tomcat 应用,当外网访问时选择那个 Pod 呢?这里需要通过 Kubernetes 之外的负载均衡器来实现的。
至此,MySQL(RC 1)和 Tomcat(RC 2)已经在 Kubernetes 部署了。并在 Kubernetes 内部 Pod 之间是可以互相访问的,在外网也可以访问到 Kubernetes 内部的 Pod。
总结
k8s入坑之路(2)kubernetes架构详解的更多相关文章
- 【转载】k8s入坑之路(2)kubernetes架构详解
每个微服务通过 Docker 进行发布,随着业务的发展,系统中遍布着各种各样的容器.于是,容器的资源调度,部署运行,扩容缩容就是我们要面临的问题. 基于 Kubernetes 作为容器集群的管理平台被 ...
- k8s入坑之路(7)kubernetes设计精髓List/Watch机制和Informer模块详解
1.list-watch是什么 List-watch 是 K8S 统一的异步消息处理机制,保证了消息的实时性,可靠性,顺序性,性能等等,为声明式风格的API 奠定了良好的基础,它是优雅的通信方式,是 ...
- k8s入坑之路(15)kubernetes共享存储与StatefulSet有状态
共享存储 docker默认是无状态,当有状态服务时需要用到共享存储 为什么需要共享存储: 1.最常见有状态服务,本地存储有些程序会把文件保存在服务器目录中,如果容器重新启停则会丢失. 2.如果使用vo ...
- k8s入坑之路(10)kubernetes coredns详解
概述 作为服务发现机制的基本功能,在集群内需要能够通过服务名对服务进行访问,那么就需要一个集群范围内的DNS服务来完成从服务名到ClusterIP的解析. DNS服务在kubernetes中经历了三个 ...
- k8s入坑之路(16)kubernetes中CICD/基于宿主机jenkins
cicd的结合组件 需要代码仓库如gitlab.github.包构建工具Maven等,持续集成工具如jenkins,github/cicd.结合自己脚本实现重复式任务自动化. 传统服务发布流程: 提交 ...
- k8s入坑之路(13)kubernetes重要资源(namespace隔离 resources资源管理 label)
Namespace --- 集群的共享与隔离 语言中namespace概念 namespace核心作用隔离 以上是隔离的代码.namespace隔离的是: 1.资源对象的隔离:Service.Depl ...
- k8s入坑之路(11)kubernetes服务发现
kubernetes访问场景 1.集群内部访问 2.集群内部访问外部 3.集群外部访问内部 1.集群内部访问 1.pod之间直接ip通讯(利用calico通过路由表经过三层将ip流量转发)由于容器之间 ...
- k8s入坑之路(13)服务迁移(定时任务 微服务 传统服务)
定时任务迁移kubernetes 服务迁移步骤 1.安装好java 2.安装好maven 项目打包 mvn package 测试传参运行 java -cp cronjob-demo-1.0-SNAPS ...
- k8s入坑之路(9)k8s网络插件详解
Flannel: 最成熟.最简单的选择 Calico: 性能好.灵活性最强,目前的企业级主流 Canal: 将Flannel提供的网络层与Calico的网络策略功能集成在一起. Weave: 独有的功 ...
随机推荐
- JScript.net
参考网址一.JScript帮助指南 http://doc.51windows.net/jscript5/?url=/jscript5/dir.htm 参考网址二.以下网址列出的类,可以尝试一下,会有意 ...
- P4100-[HEOI2013]钙铁锌硒维生素【矩阵求逆,最大匹配】
正题 题目链接:https://www.luogu.com.cn/problem/P4100 题目大意 给出\(n\)个线性无关的向量\(A_i\),然后给出\(n\)个向量\(B_i\),求一个字典 ...
- es相关监控指标梳理
###################ElasticSearch监控指标梳理########################### #author:lugh1 # #date:2021-09-26 # ...
- WPF实现统计图(饼图仿LiveCharts)
WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织 每日一笑 下班和实习生一起回家,公交站等车,一乞丐把碗推向实习生乞讨.这时,实习生不慌不忙的说了句:&qu ...
- Angular 的性能优化
目录 序言 变更检查机制 性能优化原理 性能优化方案 小结 参考 序言 本文将谈一谈 Angular 的性能优化,并且主要介绍与运行时相关的优化.在谈如何优化之前,首先我们需要明确什么样的页面是存在性 ...
- 【Golang】三个点(...)用法
众所周知,Go语言是严格类型语言,而开发的时候又遇到传入参数不定的情况,怎么办? 这里的三个点(-),就给我们编程人员带来很大的灵活性,具体如下 在Golang中,三个点一共会用在四个地方(话说三个点 ...
- Azure Tips 第一期: Azure 中的安全监视工具,数据存储, 动态数据屏蔽以及资源部署
# 1 Azure 中的安全监视工具 微软 Azure 云提供以下监控工具,可用于观察操作和检测异常行为. Azure 安全中心 Azure 安全中心是一个统一的基础结构安全管理系统,可以增强数据中心 ...
- Java生成6位数验证码
public static String getCode() { return String.valueOf((int) ((Math.random() * 9 + 1) * 100000));} 生 ...
- Flask聚合函数(基本聚合函数、分组聚合函数、去重聚合函数))
Flask聚合函数 1.基本聚合函数(sun/count/max/min/avg) 使用聚合函数先导入:from sqlalchemy import func 使用方法: sun():func.sum ...
- Caterpillar的启动以及自动化启动脚本
Caterpillar的启动以及自动化启动脚本 Caterpillar是基于以太坊的BPMS,建模的BPMN图形可被Caterpillar转化为solidity程序部署到以太坊中. Caterpill ...