每个微服务通过 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入坑之路(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: 独有的功 ...
-
k8s入坑之路(4)kubenetes安装
三种安装方法: 1.kubeadm 2.kubespray 3.二进制安装 kubespray安装kubernetes集群 优点: 1.kuberspray对比kubeadm更加简洁内部集成了kube ...
随机推荐
-
node.js打开浏览器
通过nodejs的child_process识别环境, 用不同的CLI打开默认浏览器: var child_process = require("child_process"); ...
-
R12月末关帐的异常检查和处理
在R12版本中月末关帐时经常会出现关不了的情况,而系统的异常报表的信息太过简单且不完全.结合项目本身发生的情况,做了以下的总结,希望能对公司其他R12项目有所启示. R12月度关帐的要点: 检查SLA ...
-
namenode无法启动(namenode格式化失败)
格式化namenode root@node04 bin]# sudo -u hdfs hdfs namenode –format 16/11/14 10:56:51 INFO namenode.Nam ...
-
ZOJ 3734	 LIKE vs CANDLE
题目意思:(13年长沙站的一道水DP,本人也去了,当时太水笔) 说俩个人竞争选票,每个人可以随机选择支持谁.每个人带有权重不同. 现在已经结束了投票阶段,你一个骇客 支持LIKE 你写了一个软件可以 ...
-
Java基础回顾(3)
数组:用一种数据类型的集合 ★数组元素下标从0开始. 数组的复制.扩容: ①.System.arraycopy(源数组, 源数组的初始下标, 目标数组, 目标数 ...
-
HashMap 、HashTable、TreeMap、WeakHashMap的区别是什么
Java为数据结构中的映射定义了一个接口java.util.Map,它有4个实现类:HashTable.HashMap.TreeMap.WeakHashMap. HashMap和HashTable的区 ...
-
Java相对路径/绝对路径总结
Version:0.9 StartHTML:-1 EndHTML:-1 StartFragment:00000099 EndFragment:00019826 Java相对路径/绝对路径总结(2) 修 ...
-
快速切题 poj2632
Crashing Robots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7799 Accepted: 3388 D ...
-
springmvc注解和参数传递
一.SpringMVC注解入门 1. 创建web项目2. 在springmvc的配置文件中指定注解驱动,配置扫描器 <!-- mvc的注解驱动 --> <mvc:annotation ...
-
redisTemplate 总结
依赖jar包 jackson <dependency> <groupId>com.fasterxml.jackson.core</groupId> <arti ...