一.kubernetes简介
kubernetes,简称K8s,是用8代替8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更“透明”,这更便于监控和管理
Pod,Label,Volume,Service,Deployment是kubernetes工作过程中重要的几个概念
二.Pod
Pod是Kubernetes的最重要概念,每一个Pod都有一个特殊的被称为”根容器“的Pause容器。Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器。
2.1 创建Pod
在kubernetes中,使用下面的yaml文件定义的Pod的完整内容
apiVersion: v1 //版本
kind: Pod //类型,pod
metadata: //元数据
name: string //元数据,pod的名字
namespace: string //元数据,pod的命名空间
labels: //元数据,标签列表
- name: string //元数据,标签的名字
annotations: //元数据,自定义注解列表
- name: string //元数据,自定义注解名字
spec: //pod中容器的详细定义
containers: //pod中的容器列表,可以有多个容器
- name: string //容器的名称
image: string //容器中的镜像
imagesPullPolicy: [Always|Never|IfNotPresent]//获取镜像的策略,默认值为Always,每次都尝试重新下
载镜像
command: [string] //容器的启动命令列表(不配置的话使用镜像内部的命令)
args: [string] //启动参数列表
workingDir: string //容器的工作目录
volumeMounts: //挂载到到容器内部的存储卷设置
- name: string
mountPath: string //存储卷在容器内部Mount的绝对路径
readOnly: boolean //默认值为读写
ports: //容器需要暴露的端口号列表
- name: string
containerPort: int //容器要暴露的端口
hostPort: int //容器所在主机监听的端口(容器暴露端口映射到宿主机的端口,设置hostPort时同一
台宿主机将不能再启动该容器的第2份副本)
protocol: string //TCP和UDP,默认值为TCP
env: //容器运行前要设置的环境列表
- name: string
value: string
resources:
limits: //资源限制,容器的最大可用资源数量
cpu: Srting
memory: string
requeste: //资源限制,容器启动的初始可用资源数量
cpu: string
memory: string
livenessProbe: //pod内容器健康检查的设置
exec:
command: [string] //exec方式需要指定的命令或脚本
httpGet: //通过httpget检查健康
path: string
port: number
host: string
scheme: Srtring
httpHeaders:
- name: Stirng
value: string
tcpSocket: //通过tcpSocket检查健康
port: number
initialDelaySeconds: 0//首次检查时间
timeoutSeconds: 0 //检查超时时间
periodSeconds: 0 //检查间隔时间
successThreshold: 0
failureThreshold: 0
securityContext: //安全配置
privileged: falae
restartPolicy: [Always|Never|OnFailure]//重启策略,默认值为Always
nodeSelector: object //节点选择,表示将该Pod调度到包含这些label的Node上,以key:value格式指定
imagePullSecrets:
- name: string
hostNetwork: false //是否使用主机网络模式,弃用Docker网桥,默认否
volumes: //在该pod上定义共享存储卷列表
- name: string
emptyDir: {} //是一种与Pod同生命周期的存储卷,是一个临时目录,内容为空
hostPath: //Pod所在主机上的目录,将被用于容器中mount的目录
path: string
secret: //类型为secret的存储卷
secretName: string
item:
- key: string
path: string
configMap: //类型为configMap的存储卷
name: string
items:
- key: string
path: string
2.2 Pod使用方法
在kubernetes中对运行容器的要求为:容器的主程序需要一直在前台运行,而不是后台运行。应用需要改造成前台运行的方式。如果我们创建的Docker镜像的启动命令是后台执行程序,则在kubelet创建包含这个容器的pod之后运行完该命令,即认为Pod已经结束,将立刻销毁该Pod。如果为该Pod定义了RC,则创建、销毁会陷入一个无限循环的过程中。
Pod可以由1个或多个容器组合而成
由一个容器组成的Pod,其yaml文件:
apiVersion: v1
kind: Pod
metadata:
name: mytomcat
labels:
name: mytomcat
spec:
containers:
- name: mytomcat
image: tomcat
ports:
- containerPort: 8000
由两个为紧耦合的容器组成的Pod的yaml文件:
apiVersion: v1
kind: Pod
metadata:
name: myweb
labels:
name: tomcat-redis
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containerPort: 8080
- name: redis
image: redis
ports:
- containerPort: 6379
使用yaml文件创建Pod
kubectl create -f xxx.yaml
查看Pod详细信息命令
kubectl get pod/po <Pod_name>
kubectl get pod/po <Pod_name> -o wide
kubectl describe pod/po <Pod_name>
删除Pod命令
kubectl delete -f pod pod_name.yaml
kubectl delete pod --all/[pod_name]
2.3 静态Pod和普通Pod
Pod有两种类型,一种是静态Pod,另一种是普通Pod
普通Pod
普通Pod一旦被创建,就会被放入到etcd中存储,随后会被Kubernetes Master调度到某个具体的Node上并进行绑定,随后该Pod对应的Node上的kubelet进程实例化成一组相关的Docker容器并启动起来。在默认情况下,当Pod里某个容器停止时,Kubernetes会自动检测到这个问题并且重新启动这个Pod里某所有容器,如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其它节点上
静态Pod
静态Pod是由kubelet进行管理的仅存在于特定Node上的Pod,它们不能通过 API Server进行管理,无法与ReplicationController、Deployment或DaemonSet进行关联,并且kubelet也无法对它们进行健康检查
静态Pod由于管理非常不方便所以很少使用,日常运维和开发中常用的Pod都是普通Pod
2.4 Pod的生命周期和重启策略
Pod的状态
状态值 | 说明 |
Pending | API Server已经创建了该Pod,但Pod中的一个或多个容器的镜像还没有创建,包括镜像下载过程 |
Running | Pod内所有容器已创建,且至少一个容器处于运行状态、正在启动状态或正在重启状态 |
Completed | Pod内所有容器均成功执行退出,且不会再重启 |
Failed | Pod内所有容器均已退出,但至少一个容器退出失败 |
Unknown | 由于某种原因无法获取Pod状态,例如网络通信不畅 |
Pod重启策略
Pod的重启策略包括Always、OnFailure和Never,默认值是Always
重启策略 | 说明 |
Always | 当容器失效时,由kubelet自动重启该容器 |
OnFailure | 当容器终止运行且退出码不为0时,由kubelet自动重启该容器 |
Never | 不论容器运行状态如何,kubelet都不会重启该容器 |
Pod常见状态转换
Pod包含的容器数 | Pod当前的状态 | 发生事件 | Pod的结果状态 | ||
RestartPolicy=Always | RestartPolicy=OnFailure | RestartPolicy=Never | |||
包含一个容器 | Running | 容器成功退出 | Running | Succeeded | Succeeded |
包含一个容器 | Running | 容器失败退出 | Running | Running | Failure |
包含两个容器 | Running | 1个容器失败退出 | Running | Running | Running |
包含两个容器 | Running | 容器被OOM杀掉 | Running | Running | Failure |
2.5 Pod资源配置
每个Pod都可以对其能使用的服务器上的计算资源设置限额,Kubernetes中可以设置限额的计算资源有CPU与
Memory两种,其中CPU的资源单位为CPU数量,是一个绝对值而非相对值。Memory配额也是一个绝对值,它的单
位是内存字节数。
Kubernetes里,一个计算资源进行配额限定需要设定以下两个参数:
- Requests 该资源最小申请数量,系统必须满足要求
- Limits 该资源最大允许使用的量,不能突破,当容器试图使用超过这个量的资源时,可能会被KubernetesKill并重启
sepc
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
上述代码表明MySQL容器申请最少0.25个CPU以及64MiB内存,在运行过程中容器所能使用的资源配额为0.5个CPU以及128MiB内存。
三.Label
Label是Kubernetes系统中另一个核心概念。一个Label是一个key=value的键值对,其中key与value由用户自己指定。Label可以附加到各种资源对象上,如Node、Pod、Service、RC,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上,Label通常在资源对象定义时确定,也可以在对象创建后动态添加或删除。
Label的最常见的用法是使用metadata.labels字段,来为对象添加Label,通过spec.selector来引用对象
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
-------------------------------------
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: NodePort
ports:
- port: 80
nodePort: 3333
selector:
app: nginx
Label附加到Kubernetes集群中的各种资源对象上,目的就是对这些资源对象进行分组管理,而分组管理的核心就是Label Selector。Label与Label Selector都是不能单独定义,必须附加在一些资源对象的定义文件上,一般附加在RC和Service的资源定义文件中。
四.Replication Controller
Replication Controller(RC)是Kubernetes系统中核心概念之一,当我们定义了一个RC并提交到Kubernetes集群中以后,Master节点上的Controller Manager组件就得到通知,定期检查系统中存活的Pod,并确保目标Pod实例的数量刚好等于RC的预期值,如果有过多或过少的Pod运行,系统就会停掉或创建一些Pod.此外我们也可以通过修改RC的副本数量,来实现Pod的动态缩放功能
kubectl scale rc nginx --replicas=5
由于Replication Controller与Kubernetes代码中的模块Replication Controller同名,所以在Kubernetes v1.2时,它就升级成了另外一个新的概念Replica Sets,官方解释为下一代的RC,它与RC区别是:Replica Sets支援基于集合的Label selector,而RC只支持基于等式的Label Selector。我们很少单独使用Replica Set,它主要被Deployment这个更高层面的资源对象所使用,从而形成一整套Pod创建、删除、更新的编排机制。最好不要越过RC直接创建Pod,因为Replication Controller会通过RC管理Pod副本,实现自动创建、补足、替换、删除Pod副本,这样就能提高应用的容灾能力,减少由于节点崩溃等意外状况造成的损失。即使应用程序只有一个Pod副本,也强烈建议使用RC来定义Pod
五.Replica Set
ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的selector(ReplicationController 仅支持等式)。Kubernetes官方强烈建议避免直接使用ReplicaSet,而应该通过Deployment来创建RS和Pod。由于ReplicaSet是ReplicationController的代替物,因此用法基本相同,唯一的区别在于ReplicatSet支持集合式的selector。
六.Deployment
Deployment是Kubenetes v1.2引入的新概念,引入的目的是为了更好的解决Pod的编排问题,Deployment内部使用了Replica Set来实现。Deployment的定义与Replica Set的定义很类似,除了API声明与Kind类型有所区别:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-demo
image: tomcat
ports:
- containerPort: 8080
七.Horizontal Pod Autoscaler
Horizontal Pod Autoscal(Pod横向扩容 简称HPA)与RC、Deployment一样,也属于一种Kubernetes资源对象。通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理。
Kubernetes对Pod扩容与缩容提供了手动和自动两种模式,手动模式通过kubectl scale命令对一个
Deployment/RC进行Pod副本数量的设置。自动模式则需要用户根据某个性能指标或者自定义业务指标,并指定Pod副本数量的范围,系统将自动在这个范围内根据性能指标的变化进行调整。
八.Volume
Volume是Pod中能够被多个容器访问的共享目录。Kubernetes的Volume定义在Pod上,它被一个Pod中的多个容器挂载到具体的文件目录下。Volume与Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或重启时,Volume中的数据也不会丢失。要使用volume,pod需要指定volume的类型和内容( spec.volumes 字段),和映射到容器的位置( spec.containers.volumeMounts 字段)。 Kubernetes支持多种类型的Volume,包括:emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、nfs、iscsi、flocker、glusterfs、rbd、cephfs、gitRepo、secret、persistentVolumeClaim、downwardAPI、azureFileVolume、azureDisk、vsphereVolume、Quobyte、PoteworxVolume、ScaleIO
九.Namespace
Namespace在很多情况下用于实现多用户的资源隔离,通过将集群内部的资源对象分配到不同的Namespace中,形成逻辑上的分组,便于不同的分组在共享使用整个集群的资源同时还能被分别管理。Kubernetes集群在启动后,会创建一个名为"default"的Namespace,如果不特别指明Namespace,则用户创建的Pod,RC,Service都将被系统 创建到这个默认的名为default的Namespace中。
十.Service
Service是Kubernetes最核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。