【k8s学习】Kubernetes学习——核心组件和架构

【本文内容】文章主要分三章:

第一章简单的介绍了Kubernetes的特点。
第二章介绍了Kubernetes的核心组件,包括:

  • Abstraction of containersPod:部署的最小单位,Container的抽象。
  • CommunicationService,便于更好的通信。
  • Route traffic into clusterIngress,基于名称的虚拟托管。
  • External ConfigurationConfigMapSecret,管理配置。
  • Data persistanceVolumes,存储数据。
  • Pod blueprintDeploymentStatefulSet,用来定义Pod和ReplicaSet。

第三章介绍了Kubernetes的架构,包括:

  • Worker Node上的3个组件:container runtimekubeletkebe-proxy
  • Master Node上的4个组件:Api ServerSchedulerController manageretcd

1. Kubernetes的特点:

  • 高可用(high availibility),意味着需要对外提供可持续访问的服务(比如我们24小时都可以访问淘宝网首页一样)。
  • 高性能(high performance),当用户访问服务的时候,响应速度很快。
  • 灾难恢复(disaster recover):提供有效的备份和恢复功能。

2. Kubernetes Components(重要的组件介绍)

比如我们想在部署以下服务:

  • Java project: my-app
  • DB: mongo-db
2.1 Pod

官网:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/

  • Smallest unit of k8s:k8s上最小的可部署的单位。
  • Abstraction over container:pod是容器(Container)的抽象,个人理解是在k8s上,我们对底层容器是透明的(不管实现是docker还是其它的容器技术),我们只会和pod打交道。
  • Usually 1 application per Pod:虽然pod可以运行多个container,但在实现应用中,通常一个pod只会运行一个container。
  • Each Pod gets its own IP address:每个Pod都会拥有自己的ip地址(内部地址,Pod相互之前可通过这个内部IP进行访问),所以上述的my-app这个项目可以通过内部IP访问到另一个Pod,即db。
  • New IP address on recreation:在kubernetes中,Pod 被设计成了相对临时性的、用后即抛的一次性实体,比如运行db的Pod挂了,新的db Pod启动来代替之前不能work的Pod的工作,那么这时候启动的Pod不再是原来的IP了。这也导致一个棘手的问题,就是我们的my-app项目,不能像传统项目那样直接配置IP地址的db连接。
2.2 Service and Ingress

Service:
官网:https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

针对上述Pod的地址不是固定的问题,Service组件可以帮助解决这个问题:

  • Permanent IP address:Service的IP是固定的。比如my-app有自己的service,db Pod也有自己的service,于是在my-app中可以通过固定的IP访问db Pod了。
  • Lifecycle of Pod and Service NOT connected:Pod的生命周期和Service的生命周期互不干扰,这意味着就算Pod挂了,Service还是在的,IP也不会变。

我们想要把my-app服务暴露给外部以便可以通过浏览器被访问到,例如:http://my-app-service-ip:port,这种Service叫External Service,表示可以被外部访问到。
另一种像db的Service,我们并不希望暴露给外部,只要my-app服务能找到即可,这种Service叫Internal Service

Service解决了Pod的网络问题,但它本身还是有缺陷的,比如我们的my-app项目,最终的地址是:http://123.1.1.1:8080,这样的访问方式可能适合测试,但对于最终的网站,我们希望用的是https://my-app.com,这时候就需要用另外一个组件了,叫Ingress

Ingress
官网:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/

外部的请求会先发送给Ingress,然后通过Ingress再转发给相应的Service。

2.3 ConfigMap and Secret

官网:https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/

Pod间相互交流依赖于Service(原因上述讲过了,在Kubernetes中,Pod被设计成相对临时的实体,一个Pod down后,因为高可用的前提下,Kubernetes会保证再新起一个Pod,那么IP就会变了,Serivce中的IP是固定的)。

正因为此,我们上述的例子Java项目my-app如果想要用mongo-db,那么它会在自己的配置文件中配置db connection url:mongo-db-service。
这个配置可能会在my-app项目中的application.properies中,或是某种外部环境变量之类的。但通常情况下,Database URL的改动,可能会引起项目的镜像重新生成,再上传到repository,在Kubernetes中再pull到Pod中。一个DB的URL的小小改动,需要重新做CI/CD,好像有点太过复杂,基于此,Kubernetes引入了新的组件,叫ConfigMap

  • External configuration of your application:ConfigMap 将你的环境配置信息和容器镜像解耦,便于应用配置的修改。比如我们可以把Database URL放到ConfigMap中,这样如果URL要从mongo-db-service改到abc-mongo,就可以不用重新布署项目了。
  • Don't put credentials into ConfigMap:ConfigMap并不提供加密功能,想要有加密功能,要用另外一个组件,叫Secret

Secret
官网:https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

  • Used to store secret data:Secret 类似于ConfigMap,但专门用于保存机密数据。
  • based64 encoded:data 字段中所有键值都必须是base64编码的字符串。
  • The build-in security mechanism is not enabled by default!

怎么使用ConfigMap和Secret,可以在项目中当作环境变量来使用,或者在properties文件中引用。

2.4 Volumes

官网:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/

Kubernetes是如何存储数据(data storage)的呢?

基于上述的例子,我们有一个mongo-db的Pod,假设我们的项目my-app,有一个add的功能,只要submit了,就会往mongo-db里存放数据。如果这时候db Pod重启了,那么之前存放的表单数据就没了(Container 中的文件在磁盘上是临时存放的)。这显然是不能接受的。我们希望存放在mongo-db中的数据是可靠的,并不会随意丢失的。Kubernetes通过组件Volumes来解决数据存储的问题。

卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 目录可以是:

  • Storage on local machine:和Pod一起在同一个机器上。
  • Remote:远程,即不在Kubernetes集群中(如另一个云存储或是个人私有的存储)。

以上这些Storage,并不是Kubernetes自己管理的存储,因为k8s doesn't manage data persistance!,可以把上述这些Storage想象成:Kubernetes集群中的外部硬件设备插件。(External hard drive plugin into the Kubernetes cluster)。这意味着用户需要自己保证数据的备份以及管理,以及存放在正确的地方。

到目前为止,上述的Kubernetes组件,可以很好让我的项目my-app运行起来,也能够读取并安全的存储数据到mondo db,并且用户可以在外部通过https://my-app.com来访问项目。

my-app在Kubernetes上的架构

2.5 Deployment And StatefulSet

上述的架构有个问题,如果my-app项目down了呢?一般来说可以人为重启Pod即可,但这样会造成一个问题,那就是在down掉的这段时间里,my-app网页会显示404,对客户来说很不友好。

如何解决呢?Kubernetes中的设计是Replicate everything,即一切都是可复制的,所以我们会再部署一个Node(之前的是Node1的话,那么这个Node2),然后在Node2上布署和Node1一模一样的Pod,Node2上的Pod和Node2连接的是同一个Service1。

node1+node2.png

Service的主要特点就是:IP固定,并且有Load Balance的功能。所以当Node1中的my-app Pod挂了后,外部请求就会通过Service1转发到Node2上的my-app Pod,即实现了网站的高可用。

**这里引入了另一个概念,即我们经常定义并启动Pod,应该要为Pod提供一个设计蓝图(define blueprint of Pods),即定义Pod并声明有几份ReplicaSet,由此引出Kubernetes里另一个重要的组件,叫Deployment

Deployment
官网:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/

  • Blueprint for my-app Pod:Deployment组件可以理解为我们的项目My-app的设计蓝图。
  • You create Deployments:在实践过程中,我们很少直接创建Pod,通常都是创建Deployment,通过它来创建Pod,好处是Deployment可以声明ReplicaSet(副本数),比如定义了ReplicaSet=1,那么就算当前的my-app Pod挂了,Deployment也会立马重新创建并启动新的Pod。除此之前,也可以动态的增加或减少副本数。
  • Abstraction of Pods:Deployment为Pod提供声明式的更新能力。

至此,我们解决了my-app Pod挂了后,网站处于404的问题(即创建Deployment,定义Pod和ReplicaSet,Pod down后,Kubernetes会跟据副本数立马启动新的Pod)。

但是,既然my-app Pod可能会down,毫无疑问,mongo-db Pod也可能会down。但是我们不能像my-app一样,用Deployment来定义Pod,原因是因为它有数据,比如使用同一份Storage,那么同时读写可能会造成数据的不一致。针对Stateful(有状态的)Pod,我们需要使用另一个组件来定义,叫StatefulSet

Stateful Set
官网:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/

  • For STATEFUL apps:像elastic, mongoDB, MySQL都属于Stateful。
  • Deployment for stateLESS Apps, StatefulSet for stateFUL Apps or Databases:使用Deployment来定义无状态的App,StatefulSet定义有状态的App或是DB。
  • Deploying StatefulSet not easy:定义StatefulSet并没有像Deployment那样方便,所以我们也可以把这些Stateful的服务放到Kubernetes集群外。

3. Kubernetes架构

3.1 Worker Node

Node,即节点,可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行Pod所需的服务。

  • Each Node has multiple Pods on it:每个Node可以运行多个Pod,比如上述的例子,Node1上运行了两个Pod:my-app和mondo-db。
  • 3 processes must be installed on every Node:节点上必须要安装的3个组件。
  • Worker Nodes do the actual work:所以有时候会把节点叫做Worker节点。

节点的组件:

  • container runtime:用来提供容器运行时的环境,只有安装了这件组件,Pod才可以运行在节点上。
  • kubeletinteracts with both - the container and nodeKubelet starts the pod with a container inside,kubelet用来帮助Pod中的容器和节点交互的,用它来创建Pod中的容器
  • kube-proxyKube Proxy forwards the requests,节点上的网络代理。另外kube-proxy也提供了类似的功能:比如Node1和Node2都有my-app和mongo-db,一个请求进入了Node1的my-app,通过Service的转发,kube-proxy会优先转回到Node1的mondo-db(即同一台节点上的),而不是Node2。

介绍完单个节点的组件,那么接下来的问题就是作为管理员如何和这个节点进行交互呢?比如:schedule pod? monitor? re-schedule/re-start pod? join a new Node?
答案是:以上这些都为由Master Node进行管理。

3.2 Master Node

4 processes run on every master node!:不同于Worker Node需要安装3个组件,Master Node需要安装4个组件。

  • 1. Api Server:如果你作为管理员,想要部署一个新的app到Kubernetes集群中,打交道的就是Api Server(比如通过Kubernetes Dashboard,或是命令行工具如kubelet,或是Kubernetes API)。Api Server就像是cluster gateway, 是操作节点的请求最先到达的地方。另外,Api Server acts as a gatekeeper for authentication!,也就是它还提供安全校验的功能,只有拥有合法权限的请求才能通过。

    • 整个过程Some request --> Api Server --> validates request--> forward to other processes(组件) --> schedule pod or create service
    • 或者想要知道Worker Node的健康状态,也需要通过Api Server来查询。
    • Only 1 entrypoint into the cluster,即Kubernetes的集群只有Api Service这一个方式对外,安全得到了保证。
  • 2. Scheduler:比如需要创建一个Pod,那么请求首先发送到上述的Api Server,然后再转发到Scheduler组件上,再通过这个组件在具体的某台Node上创建Pod。这个过程中,Scheduler需要做决定:这个Pod要在哪个节点上创建(会权衡每台Worker Node的资源情况)。比如Node1的资源(如CPU使用情况)已经使用了30%,Node2的资源已经使用了60%,那么新的Pod就可以被Scheduler组件分到了Node1上。
    这里需要注意的是,Scheduler只会做决定——Pod将在哪个Worker节点上被创建,具体的创建工作,还是要交给Worker Node上的组件:kubelet

  • 3. Controller manager:当某个Pod挂了,Master需要知道这个消息以便及时的对这个Pod进行re-schedule,这时候就要用到Controller manager组件了。即:detects cluster state change
    整个过程Controller manager捕获到了Pod down了 --> 通知Scheduler组件 --> Scheduler决定在哪台Worker Node上重新创建Pod --> 目标Worker Node上的kubelet组件执行创建Pod的请求

  • 4. etcd:key-value的存储结构,用来存储集群的基本信息。etcd is the cluster brain!——可以想象成etcd是Kubernetes集群的大脑。集群里的每一次改动(比如上述的例子,Pod挂了,新的Pod被Scheduled),都会以key-value的形式存到etcd中。
    正因为有了这些信息,Scheduler组件才能决定需要把新的Pod放在哪台Worker Node上,Controller manager组件才会知道某个Worker Node的Pod挂了。或者Api Server想要返回Worker Node的健康状况时,也需要用到etcd。

在实际的Kubernetes集群中,可能会不止一台Master节点,比如会有Master1,Master2,当然组件Api Server会是Load Balance,etcd存储会是分布式的。

3.3 例子

假设我们设计的集群中,有:

  • 2个Master Nodes
  • 3个Worker Nodes

因为Master Node上没有Pod运行在上面,所以一般来说,它所需要的资源,可以比Worker Node少——less resources。这里的资源包括CPU、内存以及存储空间。

想要加入更多的Master Node或是Worker Node,也比较容易,比如想要创建新的Master Node

  • 我们只需要准备一台Server
  • 再安装好上述的4个Master所需的组件(Api Service,Scheduler,Controller manager,etcd)。
  • 最后把它加到Kubernetes集群中。

Worker Node同理,需要安装的是上述的3个组件:container runtime,kubelet,kube-proxy。


参考:https://kubernetes.io/zh-cn/docs/home/
参考:https://www.youtube.com/watch?v=X48VuDVv0do

你可能感兴趣的:(【k8s学习】Kubernetes学习——核心组件和架构)