【Kubernetes】基本概念和术语 -- 2019-08-11 18:31:04

我的未来我决定 提交于 2019-11-27 00:03:15

原文: http://106.13.73.98/__/206/

命令小结

1.创建

kubectl create -f mysql-xx.yaml

2.查基本信息

kubectl get xx <name>
# xx可以为:rc/rs/pods/deployments/nodes/svc/services/namespaces
可指定 <name> 查询某一个 node/deploy 的基本信息

3.查看详细信息

kubectl describe xx <name>
# xx可以为:node/deploy等
# 可指定 <name> 查询某一个 node/deploy 的详细信息

4.指定命名空间 namespace 查询:

kubectl get xx -n "namespace"  # 或如下
kubectl get xx --namespace="namespace"

@
       Kubernets 中的大部分概念如 NodePodRC(Replication Controller)Service 等都可以看作是一种 “资源对象”,几乎所有的资源对象都可以通过 Kubernetes 提供的 kubectl 工具(或者 API 编程调用)执行增删改查等操作并将其保存在 etcd 中持久化存储。 从这个角度来看,Kubernetes 其实是一个高度自动化的资源控制系统,它通过跟踪对比 etcd 库里保存的 “资源期望状态” 与当前环境中的 “实际资源状态” 的差异来实现自动控制和自动纠错的高级功能。

Master

       Kubernetes 里的 Master 指的是 集群控制节点 ,每个 Kubernetes 集群内都需要有一个 Master 节点来负责整个集群的管理和控制,基本上 Kubernetes 所有的控制命令都是发给它,它来负责具体的执行过程,我们执行的命令基本上都是在 Master 节点上运行的。如果 Master 节点宕机或者不可用,那么我们所有的控制命令都将失效。

Master 节点上的关键进程

  • Kubernetes API Server(Kube-apiserver)
    提供了HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的增删改查等操作的唯一入口,也是集群控制的入口进程。
  • Kubernetes Controller Manager(kube-controller-manager)
    Kubernetes里所有资源对象的自动化控制中心,可以理解为资源对象的“大总管”。
  • Kubernets Scheduler(kube-scheduler)
    负责资源调度(Pod调度)的进程,相当于公交公司的“调度室”。

其实 Master 节点上往往还启动了一个 etcd Server 进程,因为 Kubernetes 里的所有资源对象的数据都是保存在 etcd 中的。

Node

       在 Kubernetes 集群中,除了 Master,其它的机器被称为 Node 节点,在较早的版本中也被称为 Minion,与 Master 一样,Node 节点可以是一台物理主机,也可以是一台虚拟机。Node 节点才是 Kubernetes 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载(Docker 容器),当某个 Node 宕机时,Master 会自动将宕机的 Node 上的工作负载转移到其它节点上去。

相关命令

查集群中所有 Node 的基本信息:

kubectl get nodes

查某个 Node 的详细信息:

kubectl describe node <node_name>

Node 节点上的关键进程

  • kubelet
    负责 Pod 对应的容器的创建、启停等任务,同时与 Master 节点密切协作,实现集群管理的基本功能。
  • kube-proxy
    实现 Kubernetes Service 的通信与负载均衡机制的重要组件。
  • Docker Engine(Docker)
    Docker 引擎,负责本机容器创建和管理工作。

       Node 节点可以在运行期间动态增加到 Kubernetes 集群中,前提是这个节点已经正确安装、配置和启动了上述的关键进程,在默认情况下 kubelet 会向 Master 注册自己,这也是 Kubernetes 推荐的 Node 管理方式,一旦 Node 被纳入集群管理范围,kulelet 进程就会定时向 Master 节点汇报自身的情报,例如操作系统、Docker 版本、机器的CPU和内存情况,以及之前有那些 Pod 在运行等,这样 Master 可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略。而某个 Node 超过指定时间不上报信息时,会被 Master 判定为 “失联”Node 的状态被标记为不可用(NotReady),随后 Master 会触发 “工作负载大转移” 的自动流程。

Pod

       PodKubernetes 的最重要也是最基本的概念,如下图所示的 Pod 组成示意图,我们看到每个 Pod 都有一个特殊的被称为 “根容器”Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器。

为何 Kubernetes 会设计出一个全新的 Pod 概念并且 Pod 为何会有这样特殊的组成结构?

       原因之一: 在一组容器作为一个单元的情况下,我们难以对 “整体” 简单地进行判断及有效地进行行动。比如,一个容器死亡了,此时算是整体死亡么?是 N/M 死亡率么?因此,引入与业务无关并且不易死亡的 Pause 容器做为 Pod根容器,以它的状态代表整个容器组的状态,就简单、巧妙地解决了这个难题。
       原因之二: Pod 里的多个业务容器共享 Pause 容器的 IP 共享 Pause 容器挂接的 Volume,这样就简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。

       Kubernetes 为每个 Pod 都分配了一个唯一的 IP 地址,称之为 Pod IP,一个 Pod 里的多个容器共享 Pod IP 地址。Kubernetes 要求底层网络支持集群内任意两个 Pod 之间的 TCP/IP 直接通信,这通常采用虚拟二层网络技术来实现,例如 Flannel、Openvswitch 等,因此我们需要牢记一点:Kubernetes 里,一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通信。

       Pod 有两种类型:普通Pod静态Pod(static Pod),后者比较特殊,它并不存放在 Kubernetesetcd 存储里,而是存放在某个具体的 Node 上的一个具体的文件中,并且只在此 Node 上启动运行。而普通的 Pod 一旦被创建,就会被放入到 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 节点上并进行绑定(Binding),随后该 Pod 被对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。在默认情况下,当 Pod 里的某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod(重启 Pod 里的所有容器),如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其它节点上,Pod、容器 与 Node 的关系如下图。


Kubernetes 里的所有资源对象都可以采用 yaml 或者 JSON 格式的文件来定义或描述。

Label(标签)

       LabelKubernetes 系统中另外一个核心概念。一个 Label 是一个 key=value 的键值对,其中 keyvalue 由用户自己指定。Label 可以附加到各种资源对象上,例如 NodePodServiceRC 等,一个资源对象可以定义任意数量的 Label,同一个 Label 也可以被添加到任意数量的资源对象上去,Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。

       Label 相当于我们熟悉的 “标签”,我们可以通过给指定的资源对象捆绑一个或多个不同的 Label 来实现多维度的资源分组管理功能,以便于灵活、方便地进行资源分配、调度、配置、部署等管理工作。给某个资源对象定义一个 Label,就相当于给它打了一个标签,随后可以通过 Label Selector(标签选择器)查询和筛选拥有某些 Label 的资源对象,Kubernetes 通过这种方式实现了类似 SQL 的简单又通用的对象查询机制。

       Label Selector 可以被类比为 SQL 语句中的 where 查询条件,例如,name=redis-slave 这个 Label Selector 作用于 Pod 时,可以被类比为 select * from pod where pod's name = "redis-slave" 这样的语句。

Label selector Kubernetes 中的重要使用场景有以下几处

  1. kube-controller 进程通过资源对象 RC 上定义的 Label Selector 来筛选要监控的 Pod 副本的数量,从而实现 Pod 副本的数量始终符合预期设定的全自动控制流程。
  2. kube-proxy 进程通过 ServiceLabel Selector 来选择对应的 Pod,自动建立起每个 Service 到对应 Pod 的请求转发路由表,从而实现 Service 的智能负载均衡机制。
  3. 通过对某些 Node 定义特定的 Label,并且在 Pod 定义文件中使用 NodeSelector 这种标签调度策略,kube-scheduler 进程可以实现 Pod “定向调度” 的特性。

       下面让我们看一个例子,假设为 Pod 定义了 3Label:release、env 和 role,不同的 Pod 定义了不同的 Label 值。如下图所示,如果我们设置了 "role=frontend"Label Selector,则会选取到 Node 1Node 2 上的 Pod;如果设置 "release=beta"Label Selector,则会选取到 Node 2Node 3 上的 Pod,且看下图。



       总结: 使用 Label 可以给对象创建多组标签,LabelLabel Selector 共同构成了 Kubernetes 系统中最核心的应用模型,使得被管理对象能够被精细地分组管理,同时实现了整个集群的高可用性。

Replication Controller(RC)

       RCKubernetes 系统中的核心概念之一,简单哪来说,它其实是定义了一个期望的场景,即声明 Pod 的副本数量在任意时刻都符合某个预期值,所以 RC 的定义包括如下几个部分。

  1. Pod 期待的副本数(replicas)。
  2. 用于筛选目标 PodLabel Selector
  3. Pod 的副本数量小于预期数量的时候,用于创建新的 PodPod 模版(template)。

       当我们定义了一个 RC 并提交到 Kubernetes 集群中以后,Master 节点上的 Controller Manager 组件就得到通知,定期巡检系统中当前存活的目标 Pod,并确保目标 Pod 实例的数量刚好等于此 RC 的期望值,如果有过多的 Pod 副本在运行,系统就会停掉一些 Pod,否则系统就会自动创建一些 Pod。可以说,通过 RCKubernetes 实现了用户集群的高可用性,并且大大减少了系统管理员在传统IT环境中需要完成的许多手工运维的工作(如主机监控脚本、应用监控脚本、故障恢复脚本等)。

       下面我们以 3Node 节点的集群为例,说明 Kubernetes 如何通过 RC 来实现 Pod 副本数量的自动控制的机制。假如我们的 RC 里定义 redis-slave 这个 Pod 需要保持 3 个副本,系统将可能在其中的两个 Node 上创建 Pod 。下图描述了在两个 Node 上创建 redis-slave Pod 的情形。


       假设 Node 2 上的 Pod 2意外终止,根据 RC 定义的 replicas 数量 2Kubernetes 将会自动创建并启动一个新的 Pod,以保证整个集群中始终有两个 redis-slave Pod 在运行。如下图所示,系统可能选择 Node 3 或者 Node 1 来创建一个新的 Pod


       此外,在运行时,我们可以通过修改 RC 的副本数量,来实现 Pod 的动态缩放(Scaling)功能,这可以通过执行 kubectl scale 命令来一键完成:kubectl scale rc redis-slave --replicas=3Scaling 命令的执行结果如下图所示:


       需要注意的是,删除 RC 并不会影响通过该 RC 已经创建好的 Pod ,为了删除所有的 Pod ,可以通过设置 replicas 的值为 0 ,然后更新该 RC 。另外,kubectl 提供了 stopdelete 命令来一次性删除 RCRC 控制的全部 Pod 。关于应用升级请搜索查询 “滚动升级(Rolling Update)”

       由于 Replication ControllerKubernetes 代码中的模块 Replication Controller 同名,同时这个词也无法准确表达它的本意,所以在 Kubernetes 1.2 的时候,它就升级成了另外一个新的概念—— Replica Set , 官方解释为 “下一代的 RC” ,他与 RC 当前存在的唯一区别是:Replica Sets 支持基于集合的 Label selector(Set-based selector) ,而 RC 只支持基于等式的 Label Selector(equality-based selector),这使得 Replica Set 的功能更强。

       kubectl 命令行工具适用于 RC 的绝大部分命令都同样适用于 Replica Set 。此外,当前我们很少单独使用 Replica Set ,它主要被 Deployment 这个更高层的资源对象所使用,从而形成一整套 Pod 创建、删除、更新编排的机制。当我们使用 Deployment 时,无须关心它是如何创建和维护 Replica Set 的,这一切都是自动发生的。

       Replica SetDeployment 这两个重要资源对象逐步替换了之前的 RC 的作用,是 Kubernetes 1.3Pod 自动扩容(伸缩)这个告警功能实现的基础,也将继续在 Kubernetes 未来的版本中发挥重要的作用。

最后我们总结一下关于 RC 的一些特性与作用

  • 在大多数情况下,我们通过定义一个 RC 实现 Pod 的创建过程及副本数量的自动控制。
  • RC 里包括完整的 Pod 定义模版。
  • RC 通过 Label Selector 机制实现对 Pod 副本的自动控制。
  • 通过改变 RC 里的 Pod 副本数量,可以实现 Pod 的扩容或伸缩功能。
  • 通过改变 RCPod 模版中的镜像版本,可以实现 Pod 的滚动升级功能。

Deployment

       DeploymentKubernetes 1.2 引入的新概念,引入的目的是为了更好的解决 Pod 的编排问题。为此,Deployment 在内部使用了 Replica Set 来实现目的,无论从 Deployment 的作用与目的、它的 YAM 定义,还是从它的具体命令行操作来看,我们都可以把它看作 RC 的一次升级,两者的相识度超过 90% 。

       Deployment 相对于 RC 的一个最大升级是我们可以随时知道当前 Pod “部署” 的进度。实际上由于一个 Pod 的创建、调度、绑定节点及在目标 Node 上启动对应的容器这一完整过程需要一定的时间,所以我们期望系统启动 NPod 副本的目标状态,实际上是一个连续变化的 “部署过程” 导致的最终状态。

Deployment 的典型使用场景有以下几个

  • 创建一个 Deployment 对象来生成对应的 Replica Set 并完成 Pod 副本的创建过程。
  • 检查 Deployment 的状态来看部署动作是否完成( Pod 副本数量是否达到预期的值)。
  • 更新 Deployment 以创建新的 Pod(比如镜像升级)。
  • 如果当前 Deployment 不稳定,则回滚到一个早先的 Deployment 版本。
  • 挂起或者恢复一个 Deployment

Deployment 的定义与 Replica Set 定义很类似,除了 API 声明与 Kind 类型等有所区别:

------------⬇️
下面我们通过运行一些例子来一起直观地感受这个新概念。首先创建一个名为 tomcat-deployment.yamlDeployment 描述文件,内容如下:

apiVersion: extensions/v1betal
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
        timr: frontend
    spec:
      containers:
        - name: tomcat-demo
          image: tomcat
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 8080

运行下述命令创建 Deployment

kubectl create -f tomcat-deployment.yaml

运行下述命令查看 Deployment 的信息:

kubectl get deployments


对上述输出中涉及的数量解释如下:

  • DESIRED
    Pod 副本数量的期望值,即 Deployment 里定义的 Replica 。
  • CURRENT
    当前 Replica 的值,实际上是 Deployment 所创建的 Replica Set 里的 Replica 值,这个值不断增加,直到达到 DESIRED 为止,表明整个部署过程完成。
  • UP-TO-DATE
    最新版本的 Pod 副本数量,用于指示在滚动升级的过程中,有多少个 Pod 副本已经成功升级。
  • AVAILABLE
    当前集群中可用的 Pod 副本数量,即集群中当前存活的 Pod 数量。

运行下述命令查看对应的 Replica Set ,我们看到它的命名跟 Deployment 的名字有关系:

运行下述命令查看创建的 Pod ,我们发现 Pod 的命名以 Deployment 对应的 Replica Set 名字为前缀,这种命名清晰地表明了一个 Replica Set 创建了那些 Pod ,对于 Pod 滚动升级这种复杂的过程来说,很容易排查错误:

运行 kubectl describe deployments ,可以清楚地看到 Deployment 控制的 Pod 的水平扩展过程。
------------⬆️

Horizontal Pod Autoscaler(HPA)

       通过手工执行 kubectl scale 命令,我们可以实现 Pod 扩容或缩容。如果仅仅到此为止,显然不符合谷歌对 Kubernetes 的定位目标——自动化、智能化。在谷歌看来,分布式系统要能够根据当前负载的变化情况自动触发水平扩展或缩容的行为,因为这一过程可能是频繁发生的、不可预料的,所以手动控制的方式是不现实的。

       因此,Kubernetes 1.0 的版本实现后,这帮大牛们就已经在默默研究 Pod 智能扩容的特性了,并在 Kubernetes 1.1 的版本中首次发布这一重量级新特性—— Horizontal Pod Autoscaling 。随后的 1.2 版本中 HPA 被升级为稳定版本(apiVersion:autoscaling/v1),但同时仍然保留旧版本(apiVersion:extensions/v1beta1),官方的计划是在 1.3 版本里先移除旧版本,并且会在 1.4 版本里彻底移除旧版本的支持。

       Horizontal Pod Autoscaling 简称 HPA ,意思是 Pod 横向自动扩容 ,与之前的 RCDeployment 一样,也属于一种 Kubernetes 资源对象。通过追踪分析 RC 控制的所有目标 Pod 的负载变化情况,来确定是否需要针对性地调整目标 Pod 的副本数,这是 HPA 的实现原理。当前,HPA 可以通过 CPUUtilizationPercentage(下面有详细描述) 或 应用程序自定义的度量指标(比如服务在每秒内的响应的请求数 TPS或QPS) 两种方式作为 Pod 负载的重量指标。

CPUUtilizationPercentage

       CPUUtilizationPercentage 是一个算术平均值,即目标 Pod 所有副本自身的 CPU 利用率的平局值。一个 Pod 自身的 CPU 利用率是该 Pod 当前 CPU 的使用量除以它的 Pod Request 的值,比如我们定义一个 Pod 的 Pod Request 为 0.4,而当前的 Pod 的 CPU 使用量为 0.2,则它的 CPU 使用率为 50%,如此一来,我们就可以计算出一个 RC 控制的所有 Pod 副本的 CPU 利用率的算术平局值了。如果某一时刻 CPUUitilizationPercentage 的值超过 80%,则意味着当前的 Pod 副本数很可能不足以支撑接下来更多的请求,需要进行动态扩容,而当请求高峰时段过去后,Pod 的 CPU 利用率又会降下来,此时对应的 Pod 副本数应该自动减少到一个合理的水平。

       CPUUtilizationPercentage 计算过程中使用到的 Pod 的 CPU 使用量通常是 1 分钟内的平均值,目前通过查询 Heapster 扩展组件来得到这个值,所以需要安装部署 Heapster,这样一来便增加了系统的复杂度和实施 HPA 特性的复杂度,因此,未来的计划是 Kubernetes 自身实现一个基础性能数据采集模块,从而更好的支持 HPA 和其它需要用到基础性能数据的功能模块。另外,我们也看到,如果目标 Pod 没有定义 Pod Request 的值,则无法使用 CPUUtilizationPercentage 来实现 Pod 横向自动扩容的能力。除了使用 CPUUtilizationPerecentage,Kubernetes 从 1.2 版本开始,尝试支持应用程序自定义的度量指标 ,目前仍然为实现特性,不建议在生产环境中使用。

Service(服务)

       Service 也是 Kubernetes 里的最核心的资源对象之一,Kubernetes 里的每个 Service 其实就是我们经常提起的微服务框架中的一个 “微服务” ,之前我们所说的 PodRC 等资源对象其实都是为这节所说的“服务”—— Kubernetes Service 做“嫁衣”的,下图显示了 PodRCService 的逻辑关系。


       从上图中我们看到,KubernetesService 定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由 Pod 副本组成的集群实例,Service 与其后端 Pod 副本集群之间则是通过 Label Selector 来实现 “无缝对接”的。而 RC 的作用实际上是保证 Service 的服务能力和服务质量始终处于预期的标准。

       通过分析、识别并建模系统中的所有服务为微服务—— Kubernetes Service ,最终我们的系统由多个提供不同业务能力而又彼此独立的微服务单元所组成,服务之间通过 TCP/IP 进行通信,从而形成了我们强大而又灵活的弹性网络,拥有了强大的分布式能力、弹性扩展能力、容错能力,与此同时,我们的程序架构也变得简单和直观许多,如下图所示。


       既然每个 Pod 都会被分配一个单独的 IP地址,而且每个 Pod 都提供一个独立的 Endpoint(Pod IP+ContainerPort)以被客户端访问,现在多个 Pod 副本组成了一个集群来提供服务,那么客户端如何来访问它们呢?一般的做法是部署一个负载均衡器(软件或硬件),为这组 Pod 开启一个对外的服务端口如 8000 端口,并且将这些 PodEndpoint 列表加入 8000 端口的转发列表中,客户端就可以通过负载均衡器的对外 IP地址+服务端口来访问此服务,而客户端的请求最后会被转发到哪个 Pod ,则由负载均衡器的算法所决定。

       Kubernetes也遵循了上述常规做法,运行在每个 Node 上的 kube-proxy 进程其实就是一个智能的软件负载均衡器,它负责对 Service 的请求转发到后端的某个 Pod 实例上,并在内部实现服务的负载均衡与会话保持机制。但 Kubernetes 发明了一个 全局唯一虚拟IP 地址,这个 虚拟IP 被称为 Cluster IP 。这样一来,每个服务就变成了具备唯一IP地址的“通信节点”,服务调用就变成了最基础的 TCP 网络通信问题。

Volume(存储卷)

Persistent Volume

Namespace(命名空间)

       Namespace(命名空间)是 Kubernetes 系统中的另一个非常重要的概念,Namespace 在很多情况下用于实现多租户的资源隔离。Namespace 通过将集群内部的资源对象 “分配” 到不同的 Namespace 中,形成逻辑分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。

       Kubernetes 集群在启动后,会创建一个名为 “default”Namespace ,通过 kubectl 可以查看:kubectl get namespaces=xx

Annotation(注解)

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

原文: http://106.13.73.98/__/206/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!