应用对象
类别
名称
资源对象
Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaling、Node、Namespace、Service、Ingress、Label、CustomResourceDefinition
存储对象
Volume、PersistentVolume、Secret、ConfigMap
策略对象
SecurityContext、ResourceQuota、LimitRange
身份对象
ServiceAccount、Role、ClusterRole
对象基础
Kubernetes 使用对象去描述整个集群的状态,集群的状态包括了:什么容器化应用在运行以及在哪个Node 上、可以被应用使用的资源、关于应用如何表现的策略,比如重启策略、升级策略,以及容错策略等。一旦创建对象,Kubernetes 系统将持续工作以确保对象存在。通过创建对象,可以有效地告知Kubernetes 系统,所需要的集群工作负载看起来是什么样子的,这就是Kubernetes 集群的期望状态。
API 对象是Kubernetes 集群中的管理操作单元。Kubernetes 集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API 对象,支持对该功能的管理操作。例如副本集Replica Set 对应的API 对象是RS 。每个API 对象都有3 大类属性:元数据metadata 、规范spec 和状态status 。
元数据是用来标识API 对象的,每个对象都至少有3 个元数据:namespace,name 和uid ;除此以外还有各种各样的标签labels 用来标识和匹配不同的对象,例如用户可以用标签env 来标识区分不同的服务部署环境,分别用env=dev 、env=testing、env=production 来标识开发、测试、生产的不同服务。
spec 规范描述了用户期望Kubernetes 集群中的分布式系统达到的理想状态(Desired State) ,例如用户可以通过复制控制器Replication Controller 设置期望的Pod 副本数为3 ;
status 描述了系统实际当前达到的状态(Status) ,例如系统当前实际的Pod 副本数为2 ;那么复制控制器当前的程序逻辑就是自动启动新的Pod ,争取达到副本数为3 。
spec 必须提供,它描述了对象的期望状态,即希望对象所具有的特征,而status 描述了对象的实际状态,它是由Kubernetes 系统提供和更新。在任何时刻,Kubernetes 控制平面一直处于活跃状态,管理着对象的实际状态以与我们所期望的状态相匹配。当创建Kubernetes 对象时,必须提供对象的spec ,用来描述该对象的期望状态,以及关于对象的一些基本信息(例如,名称) 。当使用Kubernetes API 创建对象时(或者直接创建,或者基于kubectl ) ,API 请求必须在请求体中包含JSON 格式的信息。更常用的是,需要在.yaml 文件中为kubectl 提供这些信息。kubectl 在执行API 请求时,将这些信息转换成JSON 格式。这里有一个.yaml 示例文件,展示了Kubernetes Deployment 的必需字段和对象spec :
apiVersion : apps/v1
kind : Deployment
metadata :
name : nginx-deployment
spec :
replicas : 3
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
image : nginx:1.7.9
ports :
- containerPort : 80
资源对象
Basic
Pod
Pod 可谓Kubernetes 中最为基础与重要的概念,Pod 是在Kubernetes 集群中运行部署应用或服务的最小单元,可以支持包含多容器。Pod 的设计理念是支持多个容器在一个Pod 中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。
每个Pod 都包含一个“根容器”(Pause 容器)和多个紧密相关的用户业务容器。每个Pod 都会提供一个独立的Endpoint (Pod IP + Container Port)以供调用方访问。在一组容器作为一个单元的情况下难以对这个“整体”简单进行判断以及进行行动。Pod 内用一个业务无关的容器来代表这个整体的状态。业务容器之间的通信与文件共享问题。Pod 基于虚拟二层网络技术(Flannel)实现任意两个跨主机的Pod 之间可直接通信;同一个Pod 里的容器共享同一个网络命名空间,可以使用localhost 互相通信。Pod 是短暂的,不是持续性实体。
命名空间(Namespace)
命名空间为Kubernetes 集群提供虚拟的隔离作用,Kubernetes 集群初始有两个命名空间,分别是默认命名空间default 和系统命名空间kube-system ,除此以外,管理员可以可以创建新的命名空间满足需要。
节点(Node)
Kubernetes 集群中的计算能力由Node 提供,最初Node 称为服务节点Minion ,后来改名为Node 。Kubernetes 集群中的Node 也就等同于Mesos 集群中的Slave 节点,是所有Pod 运行所在的工作主机,可以是物理机也可以是虚拟机。不论是物理机还是虚拟机,工作主机的统一特征是上面要运行kubelet 管理节点上运行的容器。
Label
一个Label 是attach 到Pod 的一对键/ 值对,用来传递用户定义的属性。比如,你可能创建了一个"tier" 和“app”标签,通过Label (tier=frontend, app=myapp)来标记前端Pod 容器,使用Label (tier=backend, app=myapp)标记后台Pod 。然后可以使用Selectors 选择带有特定Label 的Pod ,并且将Service 或者Replication Controller 应用到上面。
一个Label 是一个key=value 的键值对,由用于自行指定。Label 可以附加到各种Kubernetes 资源上,例如Node 、Pod、Service、RC 等,Label 与资源对象是多对多的关系,其可以在资源对象定义是确定,也可以在资源对象创建后动态添加、删除。Kubernetes 中非常核心重要的功能之一,用于分类、检索资源。重要使用场景有以下几处:
kube-controller 进程通过RC 上定义的Label Selector 来筛选要监控的Pod 副本数量,从而实现Pod 副本数量始终符合预期设定的全自动控制流程。
kube-proxy 进程通过Service 的Label Selector 来选择对应的Pod ,自动建立起每个Service 到对应Pod 的请求转发路由表,从而实现Service 的智能负载均衡机制。
kube-scheduler 基于Pod 的NodeSelector 标签调度策略实现Pod “定向调度”的特性。
Workloads
Pods 通常由更高级的抽象对象进行控制,进行常见的副本、认证、持久化存储、自定义调度、滚动更新等操作。
Deployments (Stateless Applications): replication + rollouts
StatefulSets (Stateful Applications): replication + rollouts + persistent storage + identity
Jobs (Batch Work): run to completion
CronJobs (Scheduled Batch Work): scheduled run to completion
DaemonSets (Per-Machine): per-Node scheduling
RC & RS
副本控制器(Replication Controller,RC)是Kubernetes 集群中最早的保证Pod 高可用的API 对象。通过监控运行中的Pod 来保证集群中运行指定数目的Pod 副本。指定的数目可以是多个也可以是1 个;少于指定数目,RC 就会启动运行新的Pod 副本;多于指定数目,RC 就会杀死多余的Pod 副本。即使在指定数目为1 的情况下,通过RC 运行Pod 也比直接运行Pod 更明智,因为RC 也可以发挥它高可用的能力,保证永远有1 个Pod 在运行。RC 是Kubernetes 较早期的技术概念,只适用于长期伺服型的业务类型。
副本集(Replication Set,RS)是新一代RC ,提供同样的高可用能力,区别主要在于RS 后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为Deployment 的理想状态参数使用。
部署(Deployment)
部署表示用户对Kubernetes 集群的一次更新操作。部署是一个比RS 应用模式更广的API 对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS ,然后逐渐将新RS 中副本数增加到理想状态,将旧RS 中的副本数减小到0 的复合操作;这样一个复合操作用一个RS 是不太好描述的,所以用一个更通用的Deployment 来描述。以Kubernetes 的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment 来管理。
任务(Job)& 定时任务(CronJob)
Job 是Kubernetes 用来控制批处理型任务的API 对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。Job 管理的Pod 根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的spec.completions 策略而不同:单Pod 型任务有一个Pod 成功就标志完成;定数成功型任务保证有N 个任务全部成功;工作队列型任务根据应用确认的全局成功而标志成功。
后台支撑服务集(DaemonSet)
长期伺服型和批处理型服务的核心在业务应用,可能有些节点运行多个同类业务的Pod ,有些节点上又没有这类Pod 运行;而后台支撑型服务的核心关注点在Kubernetes 集群中的节点(物理机或虚拟机) ,要保证每个节点上都有一个此类Pod 运行。节点可能是所有集群节点也可能是通过nodeSelector 选定的一些特定节点。典型的后台支撑型服务包括,存储,日志和监控等在每个节点上支持Kubernetes 集群运行的服务。
有状态服务集(StatefulSet)
RC 和RS 主要是控制提供无状态服务的,其所控制的Pod 的名字是随机设置的,一个Pod 出故障了就被丢弃掉,在另一个地方重启一个新的Pod ,名字变了。名字和启动在哪儿都不重要,重要的只是Pod 总数;而StatefulSet 是用来控制有状态服务,StatefulSet 中的每个Pod 的名字都是事先确定的,不能更改。
对于RC 和RS 中的Pod ,一般不挂载存储或者挂载共享存储,保存的是所有Pod 共享的状态,Pod 像牲畜一样没有分别(这似乎也确实意味着失去了人性特征) ;对于StatefulSet 中的Pod ,每个Pod 挂载自己独立的存储,如果一个Pod 出现故障,从其他节点启动一个同样名字的Pod ,要挂载上原来Pod 的存储继续以它的状态提供服务。
适合于StatefulSet 的业务包括数据库服务MySQL 和PostgreSQL ,集群化管理服务ZooKeeper 、etcd 等有状态服务。StatefulSet 的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。使用StatefulSet ,Pod 仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,StatefulSet 做的只是将确定的Pod 与确定的存储关联起来保证状态的连续性。
服务发现与负载均衡(Service Discovery & Load Balancing)
服务发现与负载均衡往往是由某个Service 对象所管理,Service 听了某个虚拟IP 地址,并且允许以Label 等选择方式将流量重定向到后端的Pods 。
服务(Service)
RC、RS 和Deployment 只是保证了支撑服务的微服务Pod 的数量,但是没有解决如何访问这些服务的问题。如果说Deployment 是负责保证Pod 组的正常运行,那么Service 就是用于保证以合理的网络来连接到该组Pod 。一个Pod 只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP 启动一个新的Pod ,因此不能以确定的IP 和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的的后端服务实例。
在K8 集群中,客户端需要访问的服务就是Service 对象。每个Service 会对应一个集群内部有效的虚拟IP ,集群内部通过虚拟IP 访问一个服务。Service 由kube-proxy 实现软件负载均衡器,负责将对Service 的请求转发到后端的某个Pod 实例上。且Kubernetes 为每个Service 分配了一个全局唯一的虚拟IP 地址(Cluster IP) ,每个服务在Kubernetes 架构上即变成了具备唯一IP 地址的通信节点。Service 有三种类型:
ClusterIP:默认类型,自动分配一个仅Cluster 内部可以访问的虚拟IP 。
NodePort:在ClusterIP 基础上为Service 在每台机器上绑定一个端口,这样就可以通过 <NodeIP>:NodePort
来访问该服务。
LoadBalancer:在NodePort 的基础上,借助Cloud Provider 创建一个外部的负载均衡器,并将请求转发到 <NodeIP>:NodePort
。
基于上述这点,Kubernetes 将Service Name 与Service Cluster IP 做一个DNS 域名映射,优雅的解决了服务发现的问题。Kubernetes 提供了内置的dns 机制和ClusterIP 机制,每个Service 都自动注册域名,分配ClusterIP ,这样服务间的依赖可以从IP 变为name 。DNS server 通过kubernetes api server 来观测是否有新Service 建立,并为其建立对应的dns 记录。如果集群已经enable DNS ,那么Pod 可以自动对Service 做name 解析。
Ingress
Ingress 是从Kubernetes 集群外部访问集群内部服务的入口。Service 虽然解决了服务发现和负载均衡的问题,但它在使用上还是有一些限制,比如对外访问的时候,NodePort 类型需要在外部搭建额外的负载均衡,而LoadBalancer 要求Kubernetes 必须跑在支持的Cloud Provider 上面。
Ingress 就是为了解决这些限制而引入的新资源,主要用来将服务暴露到Cluster 外面,并且可以自定义服务的访问策略。比如想要通过负载均衡器实现不同子域名到不同服务的访问:
foo.bar.com --| |-> foo.bar.com s1:80
| 178.91.123.132 |
bar.foo.com --| |-> bar.foo.com s2:80
存储对象
存储卷(Volume)
Kubernetes 集群中的存储卷跟Docker 的存储卷有些类似,只不过Docker 的存储卷作用范围为一个容器,而Kubernetes 的存储卷的生命周期和作用范围是一个Pod 。每个Pod 中声明的存储卷由Pod 中的所有容器共享。Kubernetes 支持非常多的存储卷类型,特别的,支持多种公有云平台的存储,包括AWS ,Google 和Azure 云;支持多种分布式存储包括GlusterFS 和Ceph ;也支持较容易使用的主机本地目录emptyDir, hostPath 和NFS 。
Kubernetes 还支持使用Persistent Volume Claim 即PVC 这种逻辑存储,使用这种存储,使得存储的使用者可以忽略后台的实际存储技术(例如AWS ,Google 或GlusterFS 和Ceph ) ,而将有关存储实际技术的配置交给存储管理员通过Persistent Volume 来配置。
持久存储卷(Persistent Volume,PV)和持久存储卷声明(Persistent Volume Claim,PVC)
PV 和PVC 使得Kubernetes 集群具备了存储的逻辑抽象能力,使得在配置Pod 的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV 的配置者,即集群的管理者。存储的PV 和PVC 的这种关系,跟计算的Node 和Pod 的关系是非常类似的;PV 和Node 是资源的提供者,根据集群的基础设施变化而变化,由Kubernetes 集群管理员配置;而PVC 和Pod 是资源的使用者,根据业务服务的需求变化而变化,有Kubernetes 集群的使用者即服务的管理员来配置。
配置对象(ConfigMap)
为Pod 提供了非敏感的数据。
密钥对象(Secret)
Secret 是用来保存和传递密码、密钥、认证凭证这些敏感信息的对象。使用Secret 的好处是可以避免把敏感信息明文写在配置文件里。在Kubernetes 集群中配置和使用服务不可避免的要用到各种敏感信息实现登录、认证等功能,例如访问AWS 存储的用户名密码。为了避免将类似的敏感信息明文写在所有需要使用的配置文件中,可以将这些信息存入一个Secret 对象,而在配置文件中通过Secret 对象引用这些敏感信息。这种方式的好处包括:意图明确,避免重复,减少暴漏机会。
身份对象
用户帐户(User Account)和服务帐户(Service Account)
顾名思义,用户帐户为人提供账户标识,而服务账户为计算机进程和Kubernetes 集群中运行的Pod 提供账户标识。用户帐户和服务帐户的一个区别是作用范围;用户帐户对应的是人的身份,人的身份与服务的namespace 无关,所以用户账户是跨namespace 的;而服务帐户对应的是一个运行中程序的身份,与特定namespace 是相关的。
RBAC 访问授权
Kubernetes 在1.3 版本中发布了alpha 版的基于角色的访问控制(Role-based Access Control,RBAC)的授权模式。相对于基于属性的访问控制(Attribute-based Access Control,ABAC) ,RBAC 主要是引入了角色(Role)和角色绑定(RoleBinding)的抽象概念。在ABAC 中,Kubernetes 集群中的访问策略只能跟用户直接关联;而在RBAC 中,访问策略可以跟某个角色关联,具体的用户在跟一个或多个角色相关联。显然,RBAC 像其他新功能一样,每次引入新功能,都会引入新的API 对象,从而引入新的概念抽象,而这一新的概念抽象一定会使集群服务管理和使用更容易扩展和重用。
集群联邦(Federation)
Kubernetes 在1.3 版本里发布了beta 版的Federation 功能。在云计算环境中,服务的作用距离范围从近到远一般可以有:同主机(Host,Node) 、跨主机同可用区(Available Zone) 、跨可用区同地区(Region) 、跨地区同服务商(Cloud Service Provider) 、跨云平台。Kubernetes 的设计定位是单一集群在同一个地域内,因为同一个地区的网络性能才能满足Kubernetes 的调度和计算存储连接要求。而联合集群服务就是为提供跨Region 跨服务商Kubernetes 集群服务而设计的。
每个Kubernetes Federation 有自己的分布式存储、API Server 和Controller Manager 。用户可以通过Federation 的API Server 注册该Federation 的成员Kubernetes Cluster 。当用户通过Federation 的API Server 创建、更改API 对象时,Federation API Server 会在自己所有注册的子Kubernetes Cluster 都创建一份对应的API 对象。在提供业务请求服务时,Kubernetes Federation 会先在自己的各个子Cluster 之间做负载均衡,而对于发送到某个具体Kubernetes Cluster 的业务请求,会依照这个Kubernetes Cluster 独立提供服务时一样的调度模式去做Kubernetes Cluster 内部的负载均衡。而Cluster 之间的负载均衡是通过域名服务的负载均衡来实现的。
Federation V1 的设计是尽量不影响Kubernetes Cluster 现有的工作机制,这样对于每个子Kubernetes 集群来说,并不需要更外层的有一个Kubernetes Federation ,也就是意味着所有现有的Kubernetes 代码和机制不需要因为Federation 功能有任何变化。