Kubernetes基础


Kubernetes

Kubernetes是由Google开源的,用于自动部署、扩展和管理容器化应用程序的开源系统。 它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。 通常我们会叫它:k8s,这是因为它用8代替8个字符“ubernete”而组成的缩写。Kubernetes的目标是让部署容器化的应用简单并且高效(powerful) 下文将以k8s来代替kubernetes。

背景知识

要了解k8s,首先需要弄清楚几个概念:

  1. 虚拟机
  2. 容器
  3. Docker、rkt

虚拟机

虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。在实体计算机中能够完成的工作在虚拟机中都能够实现。在计算机中创建虚拟机时,需要将实体机的部分硬盘和内存容量作为虚拟机的硬盘和内存容量。每个虚拟机都有独立的CMOS、硬盘和操作系统,可以像使用实体机一样对虚拟机进行操作。

容器

Linux容器是与系统其他部分隔离开的一系列进程。运行这些进程所需的所有文件都由另一个镜像提供,这意味着从开发到测试再到生产的整个过程中,Linux 容器都具有可移植性和一致性。因而,相对于依赖重复传统测试环境的开发渠道,容器的运行速度要快得多。容器比较普遍也易于使用,因此也成了 IT 安全方面的重要组成部分。

容器的隔离可以使用2种机制:一个是Linux的namespace,它使每个进程只看到它自己的系统试图(文件、进程、网络接口、主机名等);另一个是Linux的cgroups,它限制了进程能使用的资源量(CPU、内存、网络带宽等)。

docker & rkt

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

虚拟化和容器化的区别可以参考图: virtualization vs containerization

Docker包含3个核心概念:

  1. 镜像
  2. 镜像仓库
  3. 容器

其中,镜像包含了打包的应用程序和其所依赖的环境。镜像仓库用于存放镜像,以及促进不同的人和不同的电脑之间共享这些镜像。容器通常是指Linux容器,它基于Docker镜像被创建,一个运行中的容器是一个运行在Docker主机上的进程,但它和主机,以及所有运行在主机上的其他进程都是隔离的,该进程的资源是受限的,只能访问和使用分配给它的资源。

在常见的基于Docker的开发流程中,开发流程大致可以分为3步:

  1. 构建一个镜像(docker build);
  2. 将镜像推送到镜像仓库(docker push);
  3. 在指定机器上将镜像拉取下来,并运行镜像,Docker会基于镜像创建一个独立的容器(docker pull && docker run);
限制

容器镜像也有一定的限制性,如果宿主机上运行了一个不匹配的Linux内核版本,或者没有相同的内核模块可用,那么应用就不能在其上运行。

而rkt,它是一个Docker的替代方案。使用OCI(开放容器标准)管理镜像、容器。

k8s核心模块

k8s的集群架构由2部分组成,如图: k8s结构

  1. 控制面板(Control Plane)
  2. 工作节点(Compute Machine,也就是我们常说的Node)

控制面板

控制面板里包括:

  1. API Server
  2. Scheduler
  3. Controller Manager

这3个组件。其中: API Server负责与所有组件进行通信; Scheduler用来给应用分配工作节点,调度应用; Controller Manager用来执行集群级别的功能,比如复制组件、持续跟踪工作节点、处理节点失败等等。

而工作节点(Node)是运行容器化应用的机器,运行、监控、管理应用服务的任务是由其中的组件完成。Docker、rkt或者其他容器类型负责提供容器运行时;Kublet与API Server通信,并管理它所在节点的容器;kube-proxy负责组件之间的负载均衡网络流量。

基本概念

Namespace

Kubernetes支持多个虚拟集群,它们底层依赖于同一个物理集群,这些虚拟集群被称为Namespace。资源的名称需要在Namespace内是唯一的,但不能跨Namespace,Namespace不能相互嵌套,每个 Kubernetes 资源只能在一个Namespace中。大多数 kubernetes 资源(例如 Pod、Service、ReplicaSet等)都位于某些Namespace中。 但是Namespace资源本身并不在Namespace中,而且底层资源,例如节点和持久化卷不属于任何Namespace。 在一些小型的应用场景中,我们可以使用namespace来区分不同的应用环境,实现逻辑上的部署隔离。

部署相关

Pod

Pod可能是k8s中最常出现的概念。官方解释: Pod是可以在k8s中创建和管理的、最小的可部署的计算单元。Pod是一组(一个或多个)容器;这些容器共享存储、网络、以及怎样运行这些容器的声明。Pod中的内容总是并置(colocated)的并且一桶调度,在共享的上下文中运行。

ReplicationController

ReplicationController确保在任何时候都有特定数量的Pod副本处于运行状态。当Pod数量过多时,ReplicationController会终止多余的Pod,当Pod数量太少时,ReplicationController将会启动新的Pod。与手工创建的Pod不同,由ReplicationController创建的Pod在失败、被删除或者终止时会被k8s自动替换掉。

ReplicaSet

ReplicaSet是新一代的ReplicationController。在未来ReplicationController将会被弃用。ReplicaSet和ReplicationController完全一致。相对于ReplicationController,ReplicaSet在标签选择器的表达能力上更强一些。

DaemonSet

DaemonSet常用来部署守护进程类的应用Pod,例如每个节点上运行日志收集器喝资源控制器,它可以在所有集群节点运行一个指定Pod,也可以指定这些Pod在部分节点运行。

Deployment

Deployment 为 Pods 和 ReplicaSets 提供声明式的更新能力。可以声明式的选择升级策略以及调整滚动升级速度。创建一个Deployment时,会自动创建ReplicaSet,pod是由Deployment创建的ReplicaSet来管理,而不是Deployment直接管理。创建Deployment和创建ReplicaSet类似,都有标签选择器、期望副本数、和pod模版,但是Deployment还有一个新字段来指定部署策略。使用Deployment可以使应用升级过程变得更加便捷,而不用编写命令去逐个的下线和上线pod。

StatefulSet

StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。StatefulSet和ReplicationController、ReplicaSet类似,可以用于管理pod的资源。不同的是,ReplicationController、ReplicaSet管理的是无状态的pod,当其管理的一个pod出现故障会自动创建一个新的pod来进行替换。但是当一个有状态的pod挂掉之后,需要在别的节点重建,新的实例必须与被替换的实例拥有相同的名称、网络标识和状态。StatefulSet 为它们的每个 Pod 维护了一个固定的 ID,这些 Pod 是基于相同的声明来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

访问相关

Service

将运行在一组Pods上的应用程序公开为网络服务的抽象方法,让客户端发现pod并与之通信。Service 在 Kubernetes 中是一个 REST 对象,和 Pod 类似。 像所有的 REST 对象一样,Service 定义可以基于 POST 方式,请求 API server 创建新的实例。服务的默认协议是TCP,也可以使用任何其他受支持的协议,如UDP、HTTP。由于许多服务需要公开多个端口,因此Kubernetes 在服务对象上支持多个端口定义,每个端口定义可以具有相同的protocol,也可以具有不同的协议。

Endpoint

Service并不是和pod直接相连的,有一种资源介于两者之间——Endpoint。Endpoint就是暴露一个服务的IP地址和端口的列表。

Ingress

Ingress是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

存储相关

Volume

容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。 首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建。 其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件, Kubernetes 抽象出 Volume 对象来解决这两个问题。卷的核心是包含一些数据的目录,Pod 中的容器可以访问该目录,特定的卷类型可以决定这个目录如何形成的,并能决定它支持何种介质,以及目录中存放什么内容。Volume是pod的一部分并和pod共享相同的生命周期,在pod启动时创建卷,在pod删除时销毁卷。

Persistent Volume(持久卷)

持久卷是集群中的一块存储,可以由管理员事先供应,或者 使用存储类(Storage Class)来动态供应。 持久卷是集群资源,就像节点也是集群资源一样。Persistent Volume 和普通的 Volume 一样,也是使用卷插件来实现的,只是它们拥有独立于任何Pod 的生命周期。

Persistent Volume Claim(持久卷声明)

Persistent Volume 是集群中的资源,Persistent Volume Claim 是对这些资源的请求。研发人员无需向pod中添加特定类型的卷,而是有集群管理员设置底层的存储,然后通过API Server创建Persistent Volume并注册,在创建Persistent Volume时指定其大小和所支持的访问模式。当集群的用户需要在pod中使用持久化存储时,用户首先创建一个Persistent Volume Claim(简称PVC)清单,指定所需要的最低容量要求和访问模式,然后用户将PVC清单提交给API Server,Kubernetes将找到可匹配的Persistent Volume并将其绑定到Persistent Volume Claim。

配置相关

ConfigMap

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到健值对中。使用时可以用作环境变量、命令行参数或者存储卷中的配置文件。

Secret

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。

其它

Job

Job会创建一个或者多个Pod,并确保指定数量的Pod运行成功。当Pod运行结束之后,Job负责跟踪记录成功完成的Pod个数。当数量达到指定的成功个数阈值时,任务(即Job)结束。删除Job的操作会清除所创建的全部Pods。