什么是Kubernetes
Kubernetes 是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes 提供了应用部署,规划,更新,维护的一种机制。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系。 Google 在 2014 年开源了 Kubernetes 项目。 Kubernetes 建立在 Google 大规模运行生产工作负载十几年经验的基础上, 结合了社区中最优秀的想法和实践。
Kubernetes 提供了很多的功能,它可以简化应用程序的工作流,加快开发速度。通常, 一个成功的应用编排系统需要有较强的自动化能力,这也是为什么 Kubernetes 被设计作为构建组件和工具的生态系统平台,以便更轻松地部署、扩展和管理应用程序。
用户可以使用 Label 以自己的方式组织管理资源,还可以使用 Annotation 来自定义资源 的描述信息,比如为管理工具提供状态检查等。
此外,Kubernetes 控制器也是构建在跟开发人员和用户使用的相同的 API 之上。用户还可以编写自己的控制器和调度器,也可以通过各种插件机制扩展系统的功能。 这种设计使得可以方便地在 Kubernetes 之上构建各种应用系统。
为什么使用 Kubernetes
Kubernetes 是谷歌开源的容器集群管理系统,是 Google 多年大规模容器管理技术 Borg 的开源版本,
Kubernetes功能:
-
服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
-
存储编排
Kubernetes 允许你、自动挂载你选择的存储系统,例如本地存储、公共云提供商等。
-
自动部署和回滚
可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。
-
自动完成装箱计算
你为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。
-
自我修复
Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。
-
密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
企业级容器调度平台:
- Apache Mesos
Mesos 是一个分布式调度系统内核,早于 Docker 产生,Mesos 作为资源管理器,从 DC/OS (数据中心操作系统)的角度提供资源视图。主/从结构工作模式,主节点分配任务,并用从节点上的 Executor 负责执行,通过 Zookeeper 给主节点提供服务注册、服务发现功能。通过 Framework Marathon 提供容器调度的能力。
优势:经过时间的检验,作为资源管理器的 Apache Mesos 在容器之前就已经出现很久了,支持运行容器化化和非容器化的工作负载。可以支持应用程序的健康检查,开放的架构。支持多个框架和多个调度器,通过不同的 Framework 可以运行 Haddop/Spark/MPI等多种不同的任务。支持超大型规模的节点管理,模拟测试支持超过 5w+ 节点,在大规模上拥有较大优势。
- Docker Swarm
Docker Swarm 是一个由 Docker 开发的调度框架。由 Docker 自身开发的好处之一就是标准 Docker API 的使用,Swarm 由多个代理(Agent)组成,把这些代理称之为节点(Node)。这些节点就是主机,这些主机在启动 Docker Daemon 的时候就会打开相应的端口,以此支持 Docker 远程 API。这些机器会根据 Swarm 调度器分配给它们的任务,拉取和运行不同的镜像。
优势:从 Docker1.12 版本开始,Swarm 随 Docker 一起默认安装发布。由于随 Docker 引擎一起发布,无需额外安装,配置简单。支持服务注册、服务发现,内置 Overlay Network 以及 Load Balancer。与 Docker CLI 非常类似的操作命令,对熟悉 Docker 的人非常容易上手学习。入门门槛、学习成本较低,使用更便捷,适用于中小型系统。
- Google Kubernetes
Kubernetes 是基于 Google 在过去十五年来大量生产环境中运行工作负载的经验。Kubernetes 的实现参考了 Google 内部的资源调度框架,但并不是 Borg 的内部容器编排系统的开源,而是借鉴 Google 从运行 Borg 获得的经验教训,形成了 Kubernetes 项目。
它使用 Label 和 Pod 的概念来将容器划分为逻辑单元。Pods 是同地协作(co-located)容器的集合,这些容器被共同部署和调度,形成了一个服务,这是 Kubernetes 和其他两个框架的主要区别。相比于基于相似度的容器调度方式(就像 Swarm 和Mesos),这个方法简化了对集群的管理。
优势:最流行等容器编排解决方案框架,基于 Google 庞大的生态圈及社区产生的产品。通过 Pods 这一抽象的概念,解决 Container 之间的依赖于通信问题。Pods,Services,Deployments 是独立部署的部分,可以通过 Selector 提供更多的灵活性。内置服务注册表和负载平衡。适用度更广,功能更强大,相较于 Mesos 来说节点规模较小,
集群组件
组件
Kubernetes分为三种:Master组件、Node组件、附加组件
Master组件
1. kube-apiserver
即API 服务器,该组件负责公开了 Kubernetes API,负责接收所有请求。集群内对集群的任何修改都是通过命令行kubectl、UI 将请求发给 api-server 才能执行的。api-server 是整个集群操作对内、对外的唯一入口,不包含我们后来部署应用暴露端口的方式。
kube-apiserver 设计上考虑了水平扩缩,也就是说,它可通过部署多个实例来进行扩缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。
2. kube-controller-manager
控制管理器。 与 cloud-controller-manager 组成Controller Manager,是 Kubernetes 的大脑,它通过 apiserver 监控整个集群的状态,并确保集群处于预期的工作状态。
kube-controller-manager 由一系列的控制器组成。可有如下分类:
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
- 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
- 端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)
- 服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)
3. cloud-controller-manager
云控制器管理器。允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。
4. kube-scheduler
kube-scheduler 负责分配调度 Pod 到集群内的节点上,它监听 kube-apiserver,查询还未分配 Node 的 Pod,然后根据调度策略为这些 Pod 分配节点。
调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。后面会介绍。
5. etcd
Etcd 是 CoreOS 基于 Raft 开发的分布式 key-value 存储,可用于服务发现、共享配置以及一致性保障(如数据库选主、分布式锁等)。
用作 Kubernetes 所有集群数据的后台数据库。
主要功能
- 基本的 key-value 存储
- 监听机制
- key 的过期及续约机制,用于监控和服务发现
- 原子 CAS 和 CAD,用于分布式锁和 leader 选举
节点组件
1. kubelet
每个Node节点上都运行一个 Kubelet 服务进程,默认监听 10250 端口,接收并执行 Master 发来的指令,管理 Pod 及 Pod 中的容器。kubelet 负责维护容器的生命周期,同时也负责 Volume(CVI)和网络(CNI)的管理;
每个 Kubelet 进程会在 API Server 上注册所在Node节点的信息,定期向 Master 节点汇报该节点的资源使用情况,并通过 cAdvisor 监控节点和容器的资源。
2. kube-proxy
维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
3. container runtime
Container runtime 负责镜像管理以及 Pod 和容器的真正运行(CRI);
Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。
附加组件
1. kube-dns
kube-dns 负责为整个集群提供 DNS 服务
2. Ingress Controller
Ingress Controller 为服务提供外网入口
3. Prometheus
Prometheus 提供资源监控
4. Dashboard
Dashboard 提供 GUI
5. Federation
Federation 提供跨可用区的集群
6. Fluentd-elasticsearch
Fluentd-elasticsearch 提供集群日志采集、存储与查询
核心概念和资源
服务的分类
1.无状态
代表应用:Nginx、Apache
优点:对客户端透明,无依赖关系,可以高效实现扩容、迁移
缺点:不能存储数据,需要额外的数据服务支撑
2.有状态
代表应用:MySQL、Redis
优点:可以独立存储数据,实现数据管理
缺点:集群环境下需要实现主从、数据同步、备份、水平扩容复杂
资源和对象
命名空间级
Container
Container(容器)是一种便携式、轻量级的操作系统级虚拟化技术。它使用 namespace 隔离不同的软件运行环境,并通过镜像自包含软件的运行环境,从而使得容器可以很方便的在任何地方运行。
由于容器体积小且启动快,因此可以在每个容器镜像中打包一个应用程序。这种一对一的应用镜像关系拥有很多好处。使用容器,不需要与外部的基础架构环境绑定, 因为每一个应用程序都不需要外部依赖,更不需要与外部的基础架构环境依赖。完美解决了从开发到生产环境的一致性问题。
容器同样比虚拟机更加透明,这有助于监测和管理。尤其是容器进程的生命周期由基础设施管理,而不是被进程管理器隐藏在容器内部。最后,每个应用程序用容器封装,管理容器部署就等同于管理应用程序部署。
Pod
Pod是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。一个Pod可以放一个容器、也可以放多个容器,但是通常一个Pod对应一个容器。
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod 所建模的是特定于应用的 “逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。 在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。
replicas
“副本”。一个 Pod 可以被复制成多份,每一份可被称之为一个“副本”,这些“副本”除了一些描述性的信息(Pod 的名字、uid 等)不一样以外,其它信息都是一样的,譬如 Pod 内部的容器、容器数量、容器里面运行的应用等的这些信息都是一样的,这些副本提供同样的功能。
Pod 的***“控制器”***通常包含一个名为 “replicas” 的属性。“replicas”属性则指定了特定 Pod 的副本的数量,当当前集群中该 Pod 的数量与该属性指定的值不一致时,k8s 会采取一些策略去使得当前状态满足配置的要求。
控制器-ReplicationController
适用于无状态服务。
ReplicationController(RC),RC 是 Kubernetes 系统中的核心概念之一,简单来说,RC 可以保证在任意时间运行 Pod 的副本数量,能够保证 Pod 总是可用的。如果实际 Pod 数量比指定的多那就结束掉多余的,如果实际数量比指定的少就新启动一些Pod,当 Pod 失败、被删除或者挂掉后,RC 都会去自动创建新的 Pod 来保证副本数量,所以即使只有一个 Pod,我们也应该使用 RC 来管理我们的 Pod。可以说,通过 ReplicationController,Kubernetes 实现了 Pod 的高可用性。
控制器-ReplicaSet
Kubernetes 官方建议使用 RS(ReplicaSet ) 替代 RC (ReplicationController ) 进行部署,RS 跟 RC 没有本质的不同,只是名字不一样,并且 RS 支持集合式的 selector。后面会说Label和Selector。
虽然也 ReplicaSet 可以独立使用,但建议使用 Deployment 来自动管理 ReplicaSet。Deployment后面介绍。
控制器-StatefulSet
适用有状态服务
其应用场景包括
- 稳定的持久化存储,即 Pod 重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现
- 稳定的网络标志,即 Pod 重新调度后其 PodName 和 HostName 不变,基于 Headless Service(即没有 Cluster IP 的 Service)来实现
- 有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依序进行(即从 0 到 N-1,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态),基于 init containers 来实现
- 有序收缩,有序删除(即从 N-1 到 0)
控制器-DaemonSet
适用守护进程
DaemonSet。DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:
- 日志收集,比如 fluentd,logstash 等
- 系统监控,比如 Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond 等
- 系统程序,比如 kube-proxy, kube-dns, glusterd, ceph 等
控制器-Job
适用任务/定时任务,Job 是 Kubernetes 用来控制批处理型任务的 API 对象。有以下两种:
- Job:一次性任务,运行完成后Pod销毁,不再重新启动新容器。
- CronJob:CronJob 是在 Job 基础上加上了定时功能。
Deployment
Deployment 为 Pod 和 Replica Set(下一代 Replication Controller)提供声明式更新。
你只需要在 Deployment 中描述你想要的目标状态是什么,Deployment controller 就会帮你将 Pod 和 Replica Set 的实际状态改变到你的目标状态。你可以定义一个全新的 Deployment,也可以创建一个新的替换旧的 Deployment。
主要功能:
- 创建RS和Pod
- 滚动升级、回滚
- 平滑扩容缩容
- 暂停与恢复Deployemnt
服务发现-Service
“Service” 简写 “svc”。Pod 不能直接提供给外网访问,而是应该使用 service。Service 就是把 Pod 暴露出来提供服务,Service 才是真正的“服务”,它的中文名就叫“服务”。
可以说 Service 是一个应用服务的抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。Service 代理 Pod 集合,对外表现为一个访问入口,访问该入口的请求将经过负载均衡,转发到后端 Pod 中的容器。
服务发现-Ingress
Ingress 可以提供外网访问 Service 的能力。可以把某个请求地址映射、路由到特定的 service。
ingress 需要配合 ingress controller 一起使用才能发挥作用,ingress 只是相当于路由规则的集合而已,真正实现路由功能的,是 Ingress Controller,ingress controller 和其它 k8s 组件一样,也是在 Pod 中运行。
存储-Volume
数据卷,共享 Pod 中容器使用的数据。用来放持久化的数据,比如数据库数据。
存储-CSI
Container Storage Interface 是由来自 Kubernetes、Mesos、Docker 等社区成员联合制定的一个行业标准接口规范,旨在将任意存储系统暴露给容器化应用程序。
CSI 规范定义了存储提供商实现 CSI 兼容的 Volume Plugin 的最小操作集和部署建议。CSI 规范的主要焦点是声明 Volume Plugin 必须实现的接口。
特殊配置-ConfigMap
用来放配置,与 Secret 是类似的,只是 ConfigMap 放的是明文的数据,Secret 是密文存放。
特殊配置-Secret
Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec 中。Secret 可以以 Volume 或者环境变量的方式使用。
Secret 有三种类型:
- Service Account:用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中;
- Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;
- kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
特殊配置-DownwardAPI
downwardAPI 这个模式和其他模式不一样的地方在于它不是为了存放容器的数据也不是用来进行容器和宿主机的数据交换的,而是让 pod 里的容器能够直接获取到这个 pod 对象本身的一些信息。
downwardAPI 提供了两种方式用于将 pod 的信息注入到容器内部:
- 环境变量:用于单个变量,可以将 pod 信息和容器信息直接注入容器内部
- volume 挂载:将 pod 信息生成为文件,直接挂载到容器内部中去
Role
Role 是一组权限的集合,例如 Role 可以包含列出 Pod 权限及列出 Deployment 权限,Role 用于给某个 Namespace 中的资源进行鉴权。
RoleBinding
RoleBinding :将 Subject 绑定到 Role,RoleBinding 使规则在命名空间内生效。
元数据型
HPA
Horizontal Pod Autoscaler(HPA).
Pod 自动扩容:可以根据 CPU 使用率或自定义指标(metrics)自动对 Pod 进行扩/缩容。
- 控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
- 支持三种metrics类型
- 预定义metrics(比如Pod的CPU)以利用率的方式计算
- 自定义的Pod metrics,以原始值(raw value)的方式计算
- 自定义的object metrics
- 支持两种metrics查询方式:Heapster和自定义的REST API
- 支持多metrics
PodTemplate
Pod Template 是关于 Pod 的定义,但是被包含在其他的 Kubernetes 对象中(例如 Deployment、StatefulSet、DaemonSet 等控制器)。控制器通过 Pod Template 信息来创建 Pod。
LimitRange
可以对集群内 Request 和 Limits 的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的 Pod 的资源使用限制。
集群级
Namespace
Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群,这些虚拟集群被称为命名空间。
作用是用于实现多团队/环境的资源隔离。
命名空间 namespace 是 k8s 集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命名空间。
默认 namespace:
- kube-system 主要用于运行系统级资源,存放 k8s 自身的组件
- kube-public 此命名空间是自动创建的,并且可供所有用户(包括未经过身份验证的用户)读取。此命名空间主要用于集群使用,关联的一些资源在集群中是可见的并且可以公开读取。此命名空间的公共方面知识一个约定,但不是非要这么要求。
- default 未指定名称空间的资源就是 default,即你在创建pod 时如果没有指定 namespace,则会默认使用 default
Node
不像其他的资源(如 Pod 和 Namespace),Node 本质上不是Kubernetes 来创建的,Kubernetes 只是管理 Node 上的资源。虽然可以通过 Manifest 创建一个Node对象(如下 json 所示),但 Kubernetes 也只是去检查是否真的是有这么一个 Node,如果检查失败,也不会往上调度 Pod。
ClusterRole
ClusterRole 是一组权限的集合,但与 Role 不同的是,ClusterRole 可以在包括所有 Namespace 和集群级别的资源或非资源类型进行鉴权。
ClusterRoleBinding
ClusterRoleBinding:将 Subject 绑定到 ClusterRole,ClusterRoleBinding 将使规则在所有命名空间中生效。