固定链接 从头开始学习 Kubernetes 核心原理和术语

从头开始学习 Kubernetes 核心原理和术语

从头开始学习 Kubernetes 核心原理和术语

前言

近年来 Kubernetes(k8s)的热度越来越高,反映了k8s 已经成为一个领先的自动化容器操作的开源平台。也许,再过两年大部分的服务都会运行在 k8s 集群上面,掌握 k8s 就如同程序员需要掌握基本的 Llinux 操作命令一样基础。

在现在这个信息发达的社会下,谁能比别人领先一步掌握新技术,谁就在竞争中赢得了先机。 然而,在了解一个大的系统时,应该尽量先了解其基本概念、术语及核心原理。本文将和大家一起学习 Kubernetes 的基本概念、术语及核心原理。

基本概念和术语

k8s 中的大部分概念如 Node、Pod、Volume、Replication Controller、 Service 等都可以理解为资源对象,几乎所有的资源对象都可以通过 kubectl 工具(或者 API 调用)执行 CRUD 等操作。所以也可以把 k8s 理解为一个自动化容器资源的管理和调度平台。

下图展示了一个典型的 Kubernetes 架构图,现在来一起学习:

1. Master

Master 指的是集群的控制节点,每个 k8s 集群里至少需要一个 Master 节点来负责整个集群的管理和控制,所有控制命令都是发给它,它来负责具体的调度和执行。

Master 上面一般运行着下面这些关键进程:

  • Kubernetes API Server(kube-apiserver): 为集群提供了 HTTP Rest 接口,是 k8s 集群集群操作和资源操作的唯一入口。
  • Kubernetes Controller Manager(kube-controller-manager): k8s 里资源对象的自动化控制中心。
  • Kubernetes Scheduler(kube-scheduler): 资源的调度进程。

2. Node

Node 是 k8s 集群中用于运行 Pod 的机器,Node 为整个集群提供可用的集群资源,比如用于保持数据、运行作业、创建网络路由等。如果某个 Node节点宕机,其上的工作负载会被 Master 自动转移到其它节点上去。

Node 节点上面会运行以下关键进程:

  • kubelet:与 Master 协作管理当前 node 节点,从而实现集群管理的基本功能,比如负责 Pod 的创建、启停等任务。
  • kube-proxy:负责 Service 的通信与负载均衡。
  • Docker Engine(docker):Docker 引擎,负责本机的容器管理工作。

Node 节点加入到集群后,kubelet 进程就会定期向 Master 节点上报自身的情况,例如 Docker 版本、CPU、内存、Pod 运行情况等,这样 Master 就可以获得每个节点的资源使用情况的,并实现高效均衡的资源调度策略。

3. Pod

Pod 是一组容器和卷的集合,同一个Pod里的容器共享同一个网络命名空间,可以使用 localhost 互相通信。

Pod是短暂的,不是持续性实体。k8s 会为每一个 pod 分配一个唯一的 IP 地址,称之为 Pod IP 。k8s 要求底层网络支持集群内任意两个 Pod 之间的网络通信,这通常采用虚拟二层网络技术来实现,例如 Flannel、Open vSwitch 等。

Pod 有两种类类型:普通的 Pod 和静态 Pod(Static Pod):

  • 普通的 Pod:创建后会放入 ETCD 中存储,随后会被 Master 调度到某个具体的 Node 上面运行。默认情况与当 Pod 里的某个容器停止时,k8s 会自动检测到并重启这个Pod,如果 Pod 所在的 Nod 宕机,则会将这个 Nod 上的所有 Pod 调度到其它节点上运行。
  • 静态 Pod:静态 Pod 比较特殊,它不会存放到 etcd 中,而是存放在某个具体的 Node 上的一个具体文件中,并且只在此 Node 上面启动运行。他们不能通过 API Server 进行管理,无法与 ReplicationController、Deployment 等进行关联,并且 kubelet 也不会对其进行健康检查。

4. Replication Controller

ReplicationController(简称为 RC)。

在旧版本中,只有 ReplicationController 对象,它的主要作用是确保 Pod 以你指定的副本数运行,即如果有容器异常退出,会自动创建新的 Pod 来替代,如下图所示。而异常多出来的容器也会自动回收,RC 跨多个 Node 节点监视多个 Pod。可以说 k8s 通过 RC 实现了集群的高可用性。

在运行时,我们也可以通过修改 RC 来修改副本的数量,从而实现 Pod 的动态缩放功能。但是删除 RC 并不会删除通过该 RC 已经创建好的 Pod。

在 k8s V1.2时,RC 升级成了 Replica Set(RS),RS 和 RC 之间的唯一区别是对选择器的支持。RS 支持基本集合的 Label Selector, 而 RC 只支持基本等式的的 Label Selector。我们不需要直接使用 RC 或者 RS,我们要使用 Deployment 来间接使用。

下面我们看看 Deployment 的概念。

5. Deployment

Deployment 的引入更好的解决了 Pod 的编排问题,Deployment 内部使用 RS 来实现,可以把 Deployment 理解为 RC 的升级版本。

由于 Pod 的创建、调度、绑定到节点及在目标节点上面启动都需要一定的时间,整个过程是一个连续变化的“部署过程”,所以使用 Deployment 来描述这个过程再好不过了。

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

  • 创建一个 Deployment 对象来生成对应的 RS 并完成 Pod 副本的创建
  • 通过 Deployment 的状态来看部署动作是否完成
  • 更新 Deployment 以创建新的 Pod(比如应用升级)
  • 回滚升级
  • 暂停 Deployment 以便于一次性修改多个 PodTemplateSpec 的配置项,之后再恢复Deployment,进行新的发布
  • 扩容

6. Lable

Label 可以理解为给资源打的标签。 一个 Lable 是一个 Key=Value 的键值对。Label 可以附加到所有资源上面,一个资源可以定义任意数量的 Lable,同一个 Lable 也可以被添加到任意资源对象上。我们可以通过 Lable Selector(标签选择器)查询和筛选拥有某些 Label 的资源对象,k8s 通过这种方式实现了类似 SQL 的对象查询机制。

例如,给系统中所有 Worker Pod 打上标签:app=worker,之后即可在 kubectl 或 k8s API 中使用– Selector 字段对其进行选择。

7. Service

Service 是定义一系列 Pod 以及访问这些 Pod 的策略的一层抽象。Service 通过 Label 找到 Pod 组。k8s 里的每个 Service 可以理解为我们微服务架构中的一个“微服务”,每个 Service 都有一个唯一的 Cluster IP 及唯一的名字,名字由开发者定义,服务间的调用可以直接调用 Cluster IP+端口 或者服务名+端口的方式调用。

假定有 2 个后台 Pod,并且定义后台 Service 的名称为‘backend-service’,Lable 选择器为(tier=backend, app=myapp)。

backend-service 的 Service 会完成如下两件重要的事情:

  • 会为 Service 创建一个本地集群的 DNS 入口,因此前端 Pod 只需要 DNS 查找主机名为 ‘backend-service’,就能够解析出前端应用程序可用的 IP 地址。
  • 现在前端已经得到了后台服务的 IP 地址,但是它应该访问 2 个后台 Pod 的哪一个呢?
    Service 在这 2 个后台 Pod 之间提供透明的负载均衡,会将请求分发给其中的任意一个(如下面的动画所示)。通过每个 Node 上运行的代理(kube-proxy)完成。

下图简单地展示了 Service 的功能:

Kubernetes ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型。

Type 的取值以及行为如下:

  • ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType。
  • NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 <NodeIP>:<NodePort>,可以从集群的外部访问一个 NodePort 服务。
  • LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
  • ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。 没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。

8. Volume

Volume 是 Pod 中能够被多个容器访问的共享目录。

k8s 的 Volume 的概念、用途和目的与 Docker 的 Volume 比较类似,但是不完全一样。k8s 中的 Volume 定义在 Pod 上,然后被 Pod 里面的多个容器挂载到具体的文件目录下,其生命周期与 pod 相同。

k8s 支持的 volume 类型比较丰富,例如 emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、cephFs……

9. Persistent Volume

与 Volume 对应的是 Persistent Volume。

Persistent Volume(简称 PV):可以理解成 k8s 集群中的某个网络存储中对应的一块存储。它与 Volume 有以下区别:

  • PV 只能是网络存储,不属于任何 Node,但是可以在每个 Node 上访问
  • PV 是独立定义于 Pod 之外的

PV 支持的类型也比较丰富,例如:gcePersistentDisk、awsElasticBlockStore、cephFs、NFS……

10. Namespace

Namespace(命名空间):主要用于实现多个租户的资源隔离,属于逻辑上的隔离,多个命名空间中的资源其实还是可以相互访问及操作的(这是 k8s 的缺点)。

本文作者:汪伟

您的留言将激励我们越做越好