目录
1、K8s结构
1.1、主节点
1.2、工作节点
1.2.1、kubelet
1.2.2、Container Runtime
1.2.3、Pod
1.2.4、kube-proxy
2、K8s核心概念详述
2.1 Pod
2.2 Service
2.3 Label
2.4 Replica Set
3、实例
1、K8s结构
K8s 采用Master / Work Node(最初称为Minion,后改名Node) 的结构,Master Node(主节点)控制整个集群,Work Node(从节点)为集群提供计算能力。使用者可以通过命令行或者 Web 控制台页面的方式来操作集群。
下图可以清楚地表示出 K8s 的整体架构
了解到 K8s 由主节点、工作节点两大部分组成后,接下来我们逐一展开,看看主节点和工作节点分别由哪些组件构成。
1.1、主节点
Master 节点是 K8s 集群的大脑,负责向外开放集群的 API,调度和管理整个集群。集群至少要有一个Master节点,如果在生产环境中要达到高可用,还需要配置 Master 集群。
下面这张图,描绘出了主节点内部的结构。
Master主要包含 API Server
、Scheduler
、Controllers
三个组成部分, 以及用作存储的 etcd
,它用来储存整个集群的状态。
- etcd: 由CoreOS开发,是一个高可用、强一致性的键值存储,为Kubernetes集群提供储存服务,类似于zookeper。 它会存储集群的整个配置和状态。主节点通过查询 etcd 以检查节点,容器的现状。
- API Server: kubernetes最重要的核心元件之一,提供资源操作的唯一入口(其他模块通过API Server查询或修改资源对象,只有API Server才能直接操作etcd),并提供认证、授权、访问控制、API注册和发现等机制。
- Scheduler: 负责资源的调度,按照预定的调度策略将 Pod(k8s中调度的基本单位)调度到相应的Node上,这里说的 Node 就是Work Node,当然如果是只有一个节点的集群,Master 也会同时作为 Work Node。
- Controllers: 通过 API Server 查询要控制的资源对象的预期状态,它检查其管控的对象的当前状态,确保它们始终处于预期的工作状态,它们的工作包括比如故障检测、自动扩充、减少、滚动更新等。
我们能接触到的控制器有,下面这些:
- Deployment
- StatuefulSet
- Service
- DaemonSet
- Ingress
具体干什么的,放到下篇文章—K8s面向对象再详细介绍,没错想用K8s你也得面向对象,可怕不。到时候会结合着例子一块看。
我们继续看K8s 的工作节点的内部结构。
1.2、工作节点
K8s 集群的工作节点,可以是物理机也可以是虚拟机器。Node 上运行的主要 K8s 组件有kubelet、kube-proxy、Container Runtime 、Pod 等。
1.2.1、kubelet
K8s 集群的每个工作节点上都会运行一个 kubelet 程序 维护容器的生命周期,它叫接收并执行Master 节点发来的指令,管理节点上的 Pod 及 Pod 中的容器。同时也负责Volume(CVI)和网络(CNI)的管理。
每个 kubelet 程序会在 API Server 上注册节点自身的信息,定期向Master节点汇报自身节点的资源使用情况,并通过cAdvisor监控节点和容器的资源。通过运行 kubelet,节点将自身的 CPU,RAM 和存储等计算机资源编程集群的一部分,相当于是放进了集群统一的资源管理池中,交由 Master 统一调配。
1.2.2、Container Runtime
容器运行时负责与容器实现进行通信,完成像容器镜像库中拉取镜像,然后启动和停止容器等操作, 引入容器运行时另外一个原因是让 K8s 的架构与具体的某一个容器实现解耦,不光是 Docker 能运行在 K8s 之上,同样也让K8s 的发展按自己的节奏进行。
想要运行在我的生态里的容器,请实现我的CRI (Container Runtime Interface),Container Runtime 只负责调用CRI 里定义的方法完成容器管理,不单独执行 docker run 之类的操作。这个也是K8s 发现Docker 制约了它的发展在 1.5 后引入的。
1.2.3、Pod
Pod 是 K8s 中的最小调度单元。我们的应用程序运行在容器里,而容器又被分装在 Pod 里。 一个 Pod 里可以有多个容器,也可以有多个容器。没有统一的标准,是单个还是多个,看要运行的应用程序的性质。 不过一个 Pod 里只有一个主容器,剩下的都是辅助主容器工作的。
比如做服务网格 Istio 的 Envoy 网关,就是放在Pod的辅助容器运行来实现流量控制的。 这就是 K8s 的容器设计模式里最常用的一种模式:sidecar。顾名思义,sidecar 指的就是我们可以在一个Pod中,启动一个辅助容器,来完成一些独立于主进程(主容器)之外的工作。
1.2.4、kube-proxy
为集群提供内部的服务发现和负载均衡,监听 API Server 中 Service 控制器和它后面挂的 endpoint 的变化情况,并通过 iptables 等方式来为 Service 的虚拟IP、访问规则、负载均衡。
2、K8s核心概念详述
2.1 Pod
一个Pod中可以运行一个或者多个容器。在一个集群中,K8S会为每个Pod都分配一个集群内唯一的IP地址,pod(容器组)中的 container(容器)共享该IP地址。因为K8S要求底层网络支持集群内的任意节点之间的两个Pod能够直接通信。这些容器共享当前Pod的文件系统和网络。而这些容器之所以能够共享,是因为Pod中有一个叫Pause的根容器,其余的用户业务容器都是共享这个根容器的IP和Volume。所以这些容器之间都可以通过localhost进行通信。
针对同一个服务我们一般会部署2个或者更多个实例。在K8S中,则是会部署多个Pod副本,组成一个Pod集群来对外提供服务。
Pod总是在node上运行,node是k8s集群中的计算机,可以是虚拟机或者物理机。每个node节点上都由master管理。一个node上可以有多个pod,k8s master会根据每个node上的资源情况,自动调度pod到最佳的node上。
而我们前面提过,K8S会为每一个Pod提供一个唯一的IP地址,客户端就需要通过每个Pod的唯一IP+容器端口来访问到具体的Pod,这样一来,如果客户端把调用地址写死,服务器就没有办法做负载均衡,而且,Pod重启之后IP地址是会变的,难道每次重启都要通知客户端IP变更吗?
为了解决这个问题,就要引出Service的概念了。
2.2 Service
Service是K8S中最核心的资源对象之一,就是用于解决上面提到的问题。我个人认为与Swarm中的Service概念没有太大的区别。
一旦Service被创建,K8S会为其分配一个集群内唯一的IP,叫做ClusterIP,而且在Service的整个生命周期中,ClusterIP不会发生变更,这样一来,就可以用与Docker Swarm类似的操作,建立一个ClusterIP到服务名的DNS域名映射即可。
值得注意的是,ClusterIP是一个虚拟的IP地址,无法被Ping,仅仅只限于在K8S的集群内使用。
而Service对客户端,屏蔽了底层Pod的寻址的过程。并且由kube-proxy进程将对Service的请求转发到具体的Pod上,具体到哪一个,由具体的调度算法决定。这样以来,就实现了负载均衡。
而Service是怎么找到Pod的呢?这就需要继续引入另外一个核心概念Label了。
2.3 Label
Lable本质上是一个键值对,具体的值由用户决定。Lable就是标签,可以打在Pod上,也可以打到Service上。总结来说,Label与被标记的资源是一个一对多的关系。
例如,我们给上面所描述的Pod打上了role=serviceA
的标签,那么只需要在Service中的Label Selector中加入刚刚那个标签,这样一来,Service就可以通过Label Selector找到打了同一Label的Pod副本集了。
接下来,再简单的介绍一下其他的K8S核心概念。
2.4 Replica Set
上面提到过部署多个Pod,是怎么一回事呢?K8S最开始有一个概念叫Replication Controller,不过现在已经慢慢的被Replica Set所替代,RS也叫下一代的RC。简单来说Replica Set定义了一种期望的场景,即让任何时候集群内的Pod副本数量都符合预期的值。
一旦被创建,集群就会定期的检测当前存活的Pod数量,如果多了,集群就会停掉一些Pod。相反,如果少了就会创建一些Pod。这样一来可以避免什么问题呢?假设某个服务有两个实例在运行,其中一个意外挂掉了,如果我们设置了副本数量是2,那么集群就会自动创建一个Pod,以保证集群内始终有两个Pod在运行。
3、实例
例如一个room服务有100个节点,即100个pod,每个pod内部都有几个容器(主容器、缓存代理容器、数据库代理容器等),这100个pod可能分布在不同的workNode上,但是label是一样的。