一、什么是Kubernetes?
Kubernetes(k8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展。如果你曾经用过 Docker 容器技术部署容器,那么可以将 Docker 看成 Kubernetes 内部使用的低级别组件。Kubernetes 不仅仅支持 Docker,还支持 Rocket,这是另一种容器技术。
使用 Kubernetes 可以:
- 自动化容器的部署和复制
- 随时扩展或收缩容器规模
- 将容器组织成组,并且提供容器间的负载均衡
- 很容易地升级应用程序容器的新版本
- 提供容器弹性,如果容器失效就替换它,等等...
实际上,使用 Kubernetes 只需一个部署文件,使用一条命令就可以部署多层容器(前端,后台等)的完整集群:
$ kubectl apply -f single-config-file.yaml
kubectl 是和 Kubernetes API 交互的命令行程序。现在介绍一些核心概念。
二、集群组件
集群是一组节点,这些节点可以是物理服务器或者虚拟机,之上安装了 Kubernetes 平台。下图展示这样的集群。注意该图为了强调核心概念有所简化。这里可以看到一个典型的 Kubernetes 架构图。
集群由多个节点构成,这些节点大致可以分为两类,管理节点 Master 和工作节点 node。
Kubernetes Master 运行的组件有:
- API Server
API Server 的核心功能是提供了 Kubernetes 各类资源对象的增、删、改、查及 Watch 等 HTTP Rest 接口,成为集群内各个功能模块之间数据交互和通信的中心枢纽,是整个系统的数据总线和数据中心。除此之外,它还有以下一些功能特性:
- 是集群管理的 API 入口。
- 是资源配额控制的入口。
- 提供了完备的集群安全机制。
- Controller Manager
Controller Manager 作为集群内部的管理控制中心,负责集群内的 Node、Pod 副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个 Node 意外宕机时,Controller Manager 会及时发现此故障并执行自动化修复流程,确保集群始终处于预期的工作状态。Controller Manager 内部包含多种 Controller,每种 Controller 都负责一种具体的控制流程,而 Controller Manager 正是这些 Controller 的核心,每个 Controller 通过 API Server 提供的接口实时监控整个集群的每个资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试着将系统状态从 "现有状态" 修正到 "期望状态",常见的 Controller 有:
- Replication Controller
- Node Controller
- ResourceQuota Controller
- Namespace Controller
- ServiceAccount Controller
- Token Controller
- Service Controller
- Endpoint Controller
- Scheduler
Scheduler 在整个系统中承担了 "承上启下" 的重要功能。承上,是指它负责接收 Controller Manager 创建的新 Pod,为其安排目标 Node。启下,是指安置工作完成后,目标 Node 上的 kubelet 服务进程接管后继工作,负责 Pod 生命周期中的 "下半生" 。具体来说,k8s Scheduler 的作用是将待调度的 Pod(API 新创建的 Pod、Controller Manager 为补足副本而创建的Pod 等)按照特定的调度算法和调度策略绑定到集群中的某个合适的 Node 上,并将绑定信息写入 etcd 中。
- etcd
etcd 是一个分布式 key-value 存储库,k8s 集群中所有数据的存储以及操作记录都在 etcd 中进行存储。
而 Node 节点运行的组件有:
- Kube-proxy
Kube-proxy 作用主要是负责 service 的实现,实现了内部从 pod 到 service 外部 node port 向 service 的访问。
- Kubelet
Kubelet 运行在每个 Node 节点上,负责接收并执行 Kubernetes Master 发来的指令,管理 pod 及 pod 中的容器,每个 Kubele 进程会在 API Server 上注册节点自身信息,并定期向 Kubernetes Master 汇报节点资源使用情况。
- Docker
Docker 作为容器的运行组件存在于 k8s 集群当中。
三、Pod
Pod 是 kubernetes 中你可以创建和部署的最小的单位。一个 Pod 代表着集群中运行的一个进程。
Pod 安排在节点上,包含一组容器和卷。同一个 Pod 里的容器共享同一个网络命名空间,可以使用 localhost 互相通信。Pod 是短暂的,不是持续性实体。你可能会有这些问题:
- 如果 Pod 是短暂的,那么我怎么才能持久化容器数据使其能够跨重启而存在呢?
Kubernetes 支持卷的概念,因此可以使用持久化的卷类型。
- 是否手动创建 Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么?
可以手动创建单个 Pod,但是也可以使用 Replication Controller 使用 Pod 模板创建出多份拷贝。
- 如果 Pod 是短暂的,那么重启时 IP 地址可能会改变,那么怎么才能从前端容器正确可靠地指向后台容器呢?
可以使用 Service。
四、Lable
如上图所示,一些 Pod 有 Label()。
一个 Label 是 attach 到 Pod 的一对键/值对,用来传递用户定义的属性。比如,你可能创建了一个 "tier" 和 "app" 标签,通过Label(tier=frontend, app=myapp)来标记前端 Pod 容器,使用 Label(tier=backend, app=myapp)标记后台 Pod。然后可以使用 Selectors 选择带有特定 Label 的 Pod,并且将 Service 或者 Replication Controller 应用到上面。
五、Replication Controller
是否手动创建 Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么,能否将 Pods 划到逻辑组里?
Replication Controller 确保任意时间都有指定数量的 Pod 副本在运行。如果为某个 Pod 创建了 Replication Controller 并且指定3个副本,它会创建3个 Pod,并且持续监控它们。如果某个 Pod 不响应,那么 Replication Controller 会替换它,保持总数为3。如下面的动画所示:
如果之前不响应的 Pod 恢复了,现在就有4个 Pod 了,那么 Replication Controller 会将其中一个终止保持总数为3。如果在运行中将副本总数改为5,Replication Controller 会立刻启动2个新 Pod,保证总数为5。还可以按照这样的方式缩小 Pod,这个特性在执行滚动升级时很有用。
当创建 Replication Controller 时,需要指定两个东西:
- Pod 模板:用来创建 Pod 副本的模板
- Label:Replication Controller 需要监控的 Pod 的标签。
现在已经创建了 Pod 的一些副本,那么在这些副本上如何均衡负载呢?我们需要的是 Service。
六、Service
如果 Pods 是短暂的,那么重启时 IP 地址可能会改变,怎么才能从前端容器正确可靠地指向后台容器呢?
Service 是定义一系列 Pod 以及访问这些 Pod 的策略的一层抽象。Service 通过 Label 找到 Pod 组。因为 Service 是抽象的,所以在图表里通常看不到它们的存在,这也就让这一概念更难以理解。
现在,假定有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 Service,称为 'LoadBalancer',作为外部负载均衡器使用,在一定数量的 Pod 之间均衡流量。比如,对于负载均衡 Web 流量很有用。