Kubernetes 是一个可移植、可扩展的开源平台。用于管理容器化的工作负载和服务,可促进声明式配置和自动化。是谷歌保密了十几年的秘密武器Borg的开源版本,谷歌一直通过Borg系统管理着数量庞大的应用程序集群。由于Kubernetes是基于容器技术的分布式架构方案,所以不局限于任何编程语言。
Kubernetes是一个可插拔的开放式平台,那些默认的解决方案可都是可选的。Kubernetes为构建开发人员平台提供了基础,但是在重要的地方保留了用户的选择权,拥有更高的灵活性。
master节点会为集群做出全局决策,比如资源调度,检测和和响应集群事件,例如:启动或删除pod。
master节点通常不运行任何工作负载。
控制器包括:
Kubernetes中的大部分概念如 Node、Pod、Replication Controller、Service 等都可以被看做一种资源对象,几乎所有资源对象都可以通过Kubernetes提供的kubectl工具(或API编程调用)执行增、删、改、查等操作并将其保存在etcd中持久化存储。
Kubernetes其实是一个高度自动化的资源控制系统,通过跟踪对比etcd库里保存的“资源期望状态”与当前环境的“实际资源状态”的差异来实现自动控制和自动纠错的高级功能。
查看可用的apiversion命令:
kubectl api-versions
k8s官方将apiversion分成了三个大类型,alpha、beta、stable。
Pod 是Kubernetes 最重要的基本概念,是Kubernetes的最小调度单位。每个Pod都有一个特殊的被称为“根容器”的Pause容器。除了Pause跟根容器外,每个Pod还包含了一个或多个紧密相关的用户业务容器。
为什么Kubernetes会这么设计呢?
Kubernetes为每个Pod都分配了唯一的IP地址,称之为Pod IP。一个Pod里的多个容器共享Pod IP地址。
Kubernetes要求底层网络支持集群内任意两个Pod之间的TCP/IP直接通信。例如:flannel、Open vSwitch等。因此,我们需要记住一个pod里的容器与另外主机上的Pod容器能够直接通信。
Pod有两种类型:
另外,对于绝大多数容器来说,一个CPU的资源配额相当大,所以在Kubernetes里通常以千分之一的CPU配额为最小单位,用m来表示。通常一个容器的CPU配个被定义为100 ~ 300m,即占用0.1~0.3个CPU。
spec:
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
通常,Requests被设置为一个较小的值,表示容器平时的工作负载情况下的资源需求,而limits设置为峰值负载情况下资源占用的最大值。
Label(标签)是Kubernetes系统中另外一个核心概念。一个Label是一个key=value的键值对,其中key与value由用户自己指定。Label可以被附加到各种资源对象上,例如:Node、Pod、Service、RC等。
一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上。通过给指定资源对象绑定Label从而实现资源对象的分组管理,方便Kubernetes进行资源分配、调度和部署等工作。
通过给指定的资源对象绑定一个或多个不同的Label来实现多维度的资源分组管理功能,以便灵活、方便地进行资源分配、调度、部署等管理工作。例如:
版本标签:release:stable、release:beta。
环境标签:environment:dev、environment:qa、environment:production。
通过Label为资源对象贴上相对应的标签,随后通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象。当前有两种Label Selector 表达式:
可通过多个Label Selector 表达式的组合实现复杂的条件选择,多个表达式之间用“,”分隔,条件之间是“AND”关系,即同时满足多个条件。
# 该片段表示:选择标签 key值为 app,value值为 myweb的资源
selector:
app: myweb
# 该片段表示:选择标签 key值为 app且value值为 myweb
# 且 key 值为tier 且 value值 in (frontend,backend)
selector:
matchLabels:
app: myweb
matchExpressions:
- {key: tier, operator: In, values: [frontend,backend]}
# 或使用以下写法
- key: tier
operator: In # In, NotIn, Exists and DoesNotExist
values: ["frontend","backend"]
Repliacation Controller (简称RC),RC是Kubernetes核心概念之一。简单的说,RC定义了一个期望的场景,即声明某种Pod的副本数量在任何时刻都符合某一个预期值。所以RC的定义包括:
apiVersion: v1
kind: ReplicationController # 副本控制器 RC
metadata:
name: myhello-rc # RC名称,全局唯一
labels:
name: myhello-rc
spec:
replicas: 5 # Pod副本期待数量
selector:
name: myhello-pod
template:
metadata:
labels:
name: myhello-pod
spec:
containers: # Pod 内容的定义部分
- name: myhello #容器的名称
image: long-xu/hello:1.0.0 #容器对应的 Docker Image
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env: # 注入到容器的环境变量
- name: env1
value: "k8s-env1"
- name: env2
value: "k8s-env2"
我们定义一个RC后,Kubernetes的controller manager组件会定时巡检目标pod的副本数量是否与预期数量一致。当实际副本数量大于预期数量则关闭一些目标pod,当实际副本数量小于预期数量,则通过RC中pod的定义模板创建一些新的目标Pod。
Replica Set 是Kubernetes1.2版本中引入的一个新概念,Replica Set 为RC的升级版本。二者的区别在于:RC的Label Selector 只支持基于等式的表达式,而RS的Label Selector 支持基于集合的表达式;在线编辑RS后,RS会自动更新Pod,而RC的修改不会自动更新现有Pod。
RC(Replica Set)作用:
Deployment 是Kubernetes在1.2版本中引入的概念,用于更好的解决pod的部署、升级、回滚等问题。
Deployment 内部会自动创建RS用于Pod的副本控制。Deployment相较于RC/RS有以下优势:
Horizontal Pod Autoscaler(简称HPA),其主要作用是用于Pod横向自动伸缩。根据追踪和分析指定RC/RS控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数量。
在Kubernetes系统中,Pod的管理对象RC、Deployment、DaemonSet和Job等都是面向无状态的服务。但现实中有很多服务是有状态的,StatefulSet就是用来管理有状态应用的Pod的。和Deployment类似,StatefulSet也是通过Label Selector来管理一组相同定义的Pod。但和Deployment不同的是,StatefulSet为它的每一个Pod都维护了一个唯一的ID。虽然每一个pod都是基于相同的定义文件而创建的,但是它们之间不能相互替换:无论怎么调度,每个pod都有一个永久不变的ID。
哪些情况下应该使用StatefulSet:
有哪些限制:
常见的哪些应用程序是有状态的,例如:MySQL集群、MongoDB集群、kafka集群等。
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。
Service服务也是Kubernetes里的核心资源对象之一,其主要作用是将运行在一组Pods上的应用程序公开为网络服务,这其实就是我们经常提起的微服务。通过service资源对象定义一个service的访问入口地址。前端应用通过访问这个入口,从而访问其背后的一组有Pod副本组成的集群实例。service所针对的目标Pods集合通常通过Label Selector来确定,如下图:
Service 一旦被定义,就被分配了一个不可变更的Cluster IP,在整个Service的生命周期内,该IP地址都不会发生改变。
Job即工作任务,Job 会创建一个或者多个 Pods,来执行工作任务。Job会跟踪记录成功完成的Pod数量,当成功完成的数量达到了指定的成功个数时,Job结束。当执行过程中Pod出现失败的情况,Job会创建新的Pod来替代该Pod。 删除 Job 的操作会清除所创建的全部 Pods。 挂起 Job 的操作会删除 Job的所有活跃 Pod,直到 Job 被再次恢复执行。Job通常为单次任务,如果需要运行定时Job则应该使用CronJob。
Volume 是k8s抽象出来的对象,用于解决Pod中的容器运行时,文件存放的问题以及多容器数据共享的问题。Pod 可以同时使用任意数量的Volume类型。 临时卷类型的生命周期与 Pod 相同,但持久卷的生命周期与Pod无关。 当 Pod 不再存在时,Kubernetes 会销毁临时卷;不过 Kubernetes 不会销毁持久卷。 对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失,也就是说数据卷的生命周期与容器无关。Volume的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的Volume类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。
Volume 支持多种Volume类型,例如:cephfs、configMap、csi、downwardAPI、emptyDir、fc(fibre channel)、gcePersistentDisk、glusterfs、hostPath、iscsi、local、nfs、persistentVolumeClaim、projected、secret、rbd等。
Volume的使用比较简单,通常情况下,我们在Pod上声明一个Volume,然后再容器里引用该Volume并挂载到容器的某个目录上即可,例如:
template:
metadata:
labels:
app: myapp
spec:
volumes:
- name: datavol
emptyDir: {}
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /mydata
name: datavol
持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先供应,或者 使用存储类(Storage Class)来动态供应。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的Volume 一样,也是使用Volume插件来实现的,只是它们拥有独立的生命周期。
Pod通过PersistentVolumeClaim(PVC)来申领PV作为存储卷使用。集群会通过PVC找到其绑定的PV,并将该PV挂载到Pod。
下面是一个NFS类型的PV的一个YAML定义文件,声明了8Gi的存储空间:
apiVersion: v1
kind: PersistentVolume
metadata:
name:pv0001
spec:
capacity:
storage: 8Gi
accessModes:
- ReadWriteOnce
nfs:
path: /somepath
server: 192.168.0.106
PV的accessModes属性:
如果某个Pod需要申请某种类型的PV,则需要先定义一个PersistentVolumeClaim对象:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
然后,在Pod的Volume定义中引用PVC即可:
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
最后说说PV的状态;PV的状态包括以下几种:
Namespace(命名空间)是Kubernetes系统中的另一个非常重要的概念,主要提供资源隔离。通过命名空间可以将同一个集群中的资源划分为相互隔离的组。统一命名空间下的资源名称必须唯一,但是不同命名空间下的资源名称可以一样。命名空间的作用仅针对那些带有命名空间的资源对象,例如:
Deployment,service,pod,rc等。对集群对象不适用,例如:Node,namespace,PV等。
Annotation(注解)与Label类似,也是使用key/value键值对的形式进行定义。不同的是Label 义的是Kubernetes对象的元数据(metadata),并且用于Label Selector。Annotation 则是用户任意定义的附加信息,以便于外部工具查找。
ConfigMap用于将其他资源对象所需要使用的非机密配置项的数据保存在键值对中。
例如:应用程序的配置文件。如此一来,就可以集中管理集群所使用的所有配置项。
Secret与ConfigMap类似,但是Secret是专门用来存储机密数据的。