Kubernetes笔记之基本概念

时间:2022-07-22
本文章向大家介绍Kubernetes笔记之基本概念,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

入门Kubernetes目前两周时间,对k8s有了一个基础模糊的认识,了解它之后就会觉得这是一门真正高端的技术。

一、 kubernetes概述

什么是Kubernetes(K8S)? 它是一个基于容器技术的分布式架构领域解决方案,K8s提供了强大的分布式服务的自动管理机制,它是一个适用于任何语言的完备的分布式系统开发和支撑平台,具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户支撑能力(暂时未理解),透明的服务注册和发现能力,可拓展的资源自动调度能力和在线扩容能力。涵盖从开发到服务部署运维的全过程工具。

为什么使用K8S? 这么多功能,能够让开发测试运维都简化工作,用起来不香么。

二、kubernetes基础概念

K8S入门基础概念包括这些:Node,Pod,Label,RC,Deployment,HPA,Service、Volume、NameSpace、Annotation 接下来详细说明每一个概念。

1. Node

k8s集群中用于执行工作任务的机器,可以是物理机器,当然也可以是虚拟机。Node中有一种特殊的Node称之为Master,Master指的是集群中的控制节点,每个K8s集群中都至少需要一台Master来负责整个集群的管理和控制,基本上上有的K8s控制命令都会发给它,它相当于是整个集群的“首脑”,一旦宕机则集群不可用。 除了Master之外其他Node都是由Master控制并分配工作。当某个Node宕机事时,其上的工作负载由Master转移至其他Node。

每个Node上运行着一组关键进程

1. kubelet:负责Pod对应的容器的创建、启停等任务,与Master节点密切协作,实现集群管理的基本功能; 2. kube-proxy:实现Kubernetes Service的通信与负载均衡机制; 3. Docker Engine:Docker引擎,负责本机的容器创建和管理工作。Node上安装并启动这些核心进程后,可在集群运行中动态的添加入集群。主要实现是kebulet会主动向集群master注册自己。

2. Pod

Pod是K8s中最重要最基础的概念,它由一个根容器“Pause容器”+ 一组容器组成的容器组。Pause容器作为Pod的根容器,它与业务无关并且不易死亡,所以用它来代表整个容器组的生命状态。Pod里的多个业务容器共享Pause容器的IP,共享容器Pause挂在的Volume以此来解决多个Pod之间的网络通信问题和文件共享问题。k8s支持集群内任何两个节点上的Pod的进行通信。

Pod中也有一类特殊的,称之为静态Pod。我们先说普通Pod的加载过程(Node,Pod关系图见下),普通Pod创建后会存储到etcd中,随后会被Master调度绑定到具体的Node上,由Node上的kubelet和docker engine实例化创建对应的容器并启动执行。而静态Pod创建后会存放到某个Node上的文件中去并在该Node上执行。 k8s会为每个Pod分配唯一IP就是前面我们所说的Pause容器上绑定的IP,该IP与Pod中容器的端口的组成称为“EndPoint”代表着一个服务进程的对外通信地址。每个Pod可以自定义的设置其占用服务器上的资源(CPU和内存)限额,CPU通常以千分之一为最小单元单位(m)比如设置100~300m,意味着Pod占用服务器CPU资源最小0.1,最大0.3个cpu,该值是一个绝对值不是相对值。内存限额也分request和limit,request表示执行Pod需要的最小内存值,limit表示内存最大使用,如果超过该值会被kill掉然后重启。

Pod组成
Node、Pod、容器关系图

3. Label

Label概念很好理解,由键值对key=value组成的标签,可以附加到各种资源对象上,一个资源可以有很多个label,一个label也可以附加到多个资源上。通过给资源对象捆绑一个或多个不同的Label来实现资源的分组管理功能。在为资源绑定标签后,可以通过Label Selector(标签选择器)进行查询和筛选资源。如下是Label Selector 的用法示例:

labels:
   app: app-name
   key: value
selector:
    matchLabels:
      tier: frontend
    matchExpressions:
    - {key:tier,operator: In,values:[frontend]}

4. RC

Replication Controller用于声明某种Pod的副本数量在任意时刻符合指定的预期值。RC的组成包括:

1. Pod期待的副本数量

2. 用于筛选目标Pod的Label Selector

3. 当Pod的副本少于预期数量时,用于创建新的Pod的Pod template

当我们定义了一个RC并提交到k8s集群中以后,Master节点上的Controller Manager组件得到通知,定期巡检系统中当前存活的目标Pod,并确保目标Pod的存活数量当好等于RC期望值。多了则kill,少了则create。需要注意的是直接删除RC并不能删除RC创建的Pod可以通过设置replicas=0来删除Pod之后删除RC。

为了便于理解这里贴上创建RC的yaml代码:

apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
spec:
  replicas:1
  selector:
    tier:frontend
  template:
    metadata:
       labels:
         app: app-demo
         tier:frontend
  spec:
    containers:
    - name:tomcat-demo
      image:tomcat
      imagePullPolicy:IfNotPresent
      env:
      - name: GET_HOST_FROM
        value:dns
      ports:
      -containerPort: 80

5. Deployment和Replica Set:

可以说Deployment是RC的一个升级版,Deployment通过使用Replica Set来实现与RC相同的Pod副本数量自动管理功能。Replica Set相比于RC在使用Label Selector更高级一点,RC仅支持基于等式的Label Selector而Replica Set支持集合式的LS,可用如下代码和上面RC进行对比体验。

apiVersion: v1
kind: ReplicaSet
metadata:
  name: frontend
spec: 
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
    - {key:tier,operator: In,values:[frontend]}
  template:
    .....

Deployment 相对与RC而言最大的特点在于,它能够随时知道当前Pod的部署进度,假设Deployment中设置Replicas=N,系统在启动N个副本的是一个长的过程,Deployment支持开发者查询当前部署的状态。如下代码是创建Deployment的示例

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas:1
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
    - {key:tier,operator: In,values:[frontend]}
  template:
    metadata:
       labels:
         app: app-demo
         tier:frontend
    spec:
     containers:
    - name:tomcat-demo
      image:tomcat
      imagePullPolicy:IfNotPresent
      ports:
      -containerPort: 8080

6. HPA

Horizontal Pod Autoscaler,Pod横向自动扩容。我们先来看看前面的RC和Deployment实现自动控制Replicas时需要指定副本数量,在Pod使用前这是一个预估值,准不准并不知道,假如Pod执行过程中发现CPU占用特别高,意味着副本数量预估少了,每个Pod的负载过高,此时我们需要手动执行kubectl命令去添加Replicas,加多少呢,只能不断加不断看系统CPU情况。这种方式完全不是我们想要的自动化。HPA便因此诞生。

HPA支持配置minReplicas和maxReplicas,具体Pod的副本数量应该是多少,取决于HPA的Pod负载度量指标:

  • CPUUtilizationPercentage
  • 应用程序自定义度量指标:比如服务在每秒内的相应请求数(TPS或QPS)

CPUUtilizationPercentage是目标Pod所有副本CPU利用率的平均值,HPA便根据这个值来在minReplicas~maxReplicas之间进行副本数的自动扩容和缩减。当然创建和删除Pod也是由指定的RC或者Deployment来实现的。

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
   kind: Deployment
   name: php-apache
   targetCPUUtilizationPercentage: 90

7. Service

Kubernetes里的每个service就是经常提起的微服务架构中的一个服务,Kubernetes的service定义了一个服务的访问入口,外部请求通过这个入口地址访问其背后的一组由Pod副本组成的集群实例。Service与其后端的Pod副本集群之间则是通过Label Selector来实现无缝对接。kubernetes通过分析、识别并建模系统中的所有服务为微服务,通过集群中的一系列微服务相互配合实现我们需要的业务。微服务Service之间是彼此独立的单元,服务之间通过TCP/IP通信。通常一个Service后端是由多副本的Pod实现,一个Service的请求去访问哪一个Pod的endpoint呢? 一般的做法是部署负载均衡器来进行Pod选择和请求转发。篇幅有限,就不在详细描述Kubernetes中的负载均衡器的实现,后面会有文章详细说Service。

Service、RC、Pod关系图
请求通过LB到Pod过程

8. Stateful Set

在Kubernetes系统中,Pod的管理对象RC、Deployment都是面向无状态的(这里的状态暂时没有理解)。但现实中有很多服务是有状态的,特别是复杂的中间件集群,例如:Mysql,MongoDB、ZooKeeper集群等,他们有如下特点:

每个节点都是有固定身份ID,通过这个ID,集群中的成员可以互相发现并且通信;

集群规模比较固定,集群规模不能随意变动;

集群里的每个节点都是有状态的,需要持久化数据到永久存储中;

如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。

我们发现使用RC/Deployment管理的Pod无法满足这些场景,RC/Deployment控制的Pod的名字是随机的,IP是变动的,并且这中有状态的集群需要多个Pod使用共享存储用于数据持久化。因此Stateful Set为解决这种问题而诞生。Stateful Set可以看作RC/Deployment的变种,它具有如下特征:

StatefulSet里的每个Pod都有稳定,唯一的网络标识,可以用于发现集群内的其他成员;

StatefulSet控制的Pod副本的启停是受控的,操作第n个Pod时,前n-1个Pod已经运行好的状态;

StatefulSet里的Pod采用稳定的持久化存储卷(Volume),通过PV/PVC(Volume的持久化实现类型)来实现,删除Pod时默认不会删除与StatefulSet相关的Volume

9. Volume

Volume是Pod中能够被多个容器访问的共享目录,Kubernetes中的Volume定义在Pod上,被一个Pod里的多个容器挂在到具体的文件目录下,与Pod具有相同的生命周期,但与容器的生命周期无关,当容器终止或者重启时,Volume中的数据不会丢失。Volume的使用也包括两部分,声明Volume,引用Volume并Mount到容器的目录上。

template:
    metadata:
       labels:
         app: app-demo
         tier:frontend
    spec:
     volumes:
       - name: datavol
         emptyDir: { }
     containers:
    - name:tomcat-demo
      image:tomcat
      volumeMounts:
         - mountPath: /mydata-data
            name: datavol
      imagePullPolicy:IfNotPresent
      ports:
      -containerPort: 8080

10. Annotation

Annotation与label类似,也适用key/value键值对的形式进行定义。不同的是Label具有严格的命名规则,他定义的是Kubernetes对象的元数据(Metadata),并且用于Label Selector。而Annotation则是用户任意定义的“附加信息”以便于外部工具进行查找,很多时候,kubernetes的模块自身会通过Annotation的方式标记资源对象的一些特殊信息。通常来说,用Annotation来记录的信息如下:

  • build信息、release信息、Docker镜像信息等,例如时间戳、release id号、镜像Hash值、docker registry地址等。
  • 日志库、监控库、分析库等资源库的地址信息。
  • 程序调式信息、例如工具名称、版本号等。
  • 团队的联系信息等

11. Namespace

Namespace(命名空间)是Kubernetes系统中用于实现多租户的资源隔离。Namespace通过将集群内部的资源对象分配到不同的Namepace中,形成逻辑上的分组的不同项目、小组或用户组,便于不同的项目分组使用同一集群的资源的同时能够分组管理。Kubernetes在启动后,会创建一个名叫“default”的默认Namespace,创建Service、Pod、RC等资源时如果不指定Namespace就会被分配到默认空间去。创建Namespace的yaml定义如下:

apiVersion: v1
kind: Namespace
metadata:
  name:dev

创建好Namespace之后创建Pod时就可以指定Namespace

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace:dev
    ......

当我们给每个租户创建一个Namespace来实现多租户隔离市,还能结合Kubernetes的资源配额管理,限定不同租户能占用的资源,例如CPU使用量、内存使用量等。

总结:本篇文章简单的描述了Kubernetes中的一些核心概念,便于日后继续学习kubernetes过程中理解。对于一些稍微复杂的概念也是总结性的说明了一下,比如Service、Volume等,Service外部访问过程,kubernetes的LB实现过程,Volume的分类在后面学习笔记会进行详细补充。欢迎读者点评指正。

说明:本文内容文字及图片大部分来源于《Kubernetes权威指南》,我只是知识的搬运工。