Docker容器
进程
核心技术
Namespace做隔离,Cgroups做限制,rootfs做文件系统
Kubernets
操作系统
Pod
容器设计模式,一组共享了某些资源的容器,Pod里的所有容器,共享同一个Network Namespace,并且可以声明共享同一个Volume
Pod的三个重要字段
Metadata
Spec
pod.status.phase
Pod对象在Kubernetes中的生命周期
- Pending:Pod的YAML文件已经提交给了Kubernetes,API对象已经创建并保存在Etcd中,但是,Pod中有些容器未顺利创建
- Running:Pod调度成功,已经和具体Node绑定,包含的容器都创建成功,并且至少有一个正在运行中
- Succeeded:Pod中所有容器正常运行完毕,并且已经退出,如一次性任务
- Failed:Pod至少有一个容器以不正常的状态退出
- Unknown:Pod的状态不能持续地被kubelet(负责维护节点上的Pod并确保容器健康运行)汇报给kube-apiserver(负责处理接受请求工作),可能主存节点通信异常
- Evicted:于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源
- CrashLoopBackOff:容器曾经启动,但又异常退出
- Error:Pod启动过程中发生错误
基础配置
# 版本号
apiVersion: v1
# 资源类型,如Pod
kind: Pod
# 元数据
metadata:
# Pod名称
name: nginx-demo1
# Pod所属的命名空间
namespace: string
# 自定义标签
labels:
app: nginx
# 自定义注释列表
annotations:
-name: string
Pod级别配置
调度、网络、存储、安全等
nodeSelector:是一个供用户将Pod与Node进行绑定的字段
nodeName:一旦Pod该字段赋值,Kubernetes项目就会认为该Pod已经经过了调度,调度的结果就是赋值的节点名字
hostAliases:定义Pod的hosts文件(比如/etc/hosts)里的内容
shareProcessNamespace:判断pod中的容器是否会共用一个pid namespace,多个容器共享同一进程命名空间
init Container和container: InitContainer相比于Container优先启动,并且按顺序逐一启动,而直到他们都启动并且退出了,用户容器才会启动
...
spec:
# Pod只能运行在携带了“disktype:ssd”标签的节点上,否则将调度失败
nodeSelector:
disktype: ssd
# 指定pod节点运行在哪个具体node上
nodeName: node2
# 修改/etc/hosts内容,这种方式可以避免Pod删除重建自动覆盖修改内容
# 10.1.2.3 foo.remote
# 10.1.2.3 bar.remote
hostAliases:
- ip: "10.1.2.3"
hostnames:
- "foo.remote"
- "bar.remote"
- shareProcessNamespace: true
...
容器级别配置
imagePullPolicy:镜像拉取策略
- 默认是Always,即每创建Pod都拉取一次镜像
- Nerver,表示Pod永远不会主动拉取镜像
- IfNotPresent,表示只有宿主机不存在镜像才拉取
LivenessProbe:容器健康检查,用探针来检查容器是否健康,如果不健康的话会重启容器
...
# Pod中容器的详细定义
spec:
nodeSelector:
node: compute
containers:
- name: nginx-demo1
# 副本数量
replicas: 3
#容器的镜像名称
image: nginx:1.8
# 镜像拉取策略
imagePullPolicy: [Always | Never | IfNotPresent]
# 容器的启动命令列表,如不指定,使用打包时使用的启动命令
command: [string]
# 容器的启动命令参数列表
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
# 探针
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
# 启动5s后进行检查
initialDelaySeconds: 5
# 每5s检查一次
periodSeconds: 5
# 容器的工作目录
workingDir: string
# 容器级别的安全上下文,作用于当前容器
securityContext:
# 打开/删除某个内核权限
capabilities:
add:
# 添加可执行iptables命令的权限
- NET_ADMIN
# 资源限制和请求的设置
resources:
# 资源限制的设置
limits:
# cpu的限制,单位为core数
cpu: string
# 内存限制,单位可以为Mib/Gib
memory: string
# 资源请求的设置
requests:
# cpu请求,容器启动的初始可用数量
cpu: string
# 内存请求,容器启动的初始可用内存
memory: string
# Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
restartPolicy: [Always | Never | OnFailure]
# 生命周期
lifecycle:
# 容器启动后,立刻执行一个指定的操作
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
# 容器被杀死之前,执行操作,同步命令,会阻塞当前容器的杀死流程
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
# 需要暴露的端口号
ports:
# 端口号名称
- name: web
# 容器需要监听的端口号
containerPort: 80
# 容器所在主机需要监听的端口号,默认与Container相同
hostPort: int
# 端口协议,支持TCP和UDP,默认TCP
protocol: string
# 容器运行前需设置的环境变量列表
env:
# 环境变量名称/值
- name: string
value: string
# 挂载到容器内部的存储卷配置
volumeMounts:
# 引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
- name: test
# 存储卷在容器内mount的绝对路径,应少于512字符
mountPath: /var/share/nginx/html
# 是否为只读模式
readOnly: boolean
# 在该pod上定义共享存储卷列表
volumes:
# 共享存储卷名称 (volumes类型有很多种)
- name: test
# 类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录,为空值
emptyDir: {}
- name: test1
# 类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
hostPath:
path: /var/data
- name: test2
# 类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
secret:
scretname: string
items:
- key: string
path: string
- name: test3
# 类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
configMap:
name: string
items:
- key: string
path: string
...
volumes(数据存储)
容器共享存储卷,实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储
kubelet创建Pod时,会先创建一个基础容器pause,Pod里面所有的容器共享一个网络名称空间和文件系统。挂载卷的工作就是由基础容器pause来完成的
volumnes比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留
基本存储之EmptyDir、HostPath、NFS
- EmptyDir
- EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一 个空目录
- EmptyDir是在Pod分配到Node时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为kubernetes会自动分配一个目录, 当Pod销毁时,EmptyDir中的数据也会被永久删除(EmptyDir与Pod生命周期一致,不适合做数据持久化存储)
- 用途
- 临时存储空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留
- 多容器共享目录,同一个Pod中的不同容器之间共享数据
- HostPath
- HostPath就是将Node主机中一个实际目录挂在到Pod中,以供容器使用,这样的设计就可以保证Pod销毁了,但是数据可以依旧存在于Node主机上
- NFS
- HostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统
- NFS是一个网络文件存储系统,可以搭建一台NFS服务器, 然后将Pod中的存储直接连接到NFS系统上,复杂
高级存储之PV、PVC
创建PV资源,通过PVC申请使用PV资源,将PVC与PV进行绑定,最后Pod通过引用PVC来使用PV资源
- PV
- 持久化卷,是对底层的共享存储的一种抽象,一般情况下PV由管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接
- PV是存储资源的抽象,PV资源是属于集群资源,跨namespace(不受命名空间隔离)
- PVC
- 持久卷声明,是用户对于存储需求的一种声明,是用户向kubernetes系统发出的一种资源需求申请
- PVC是对PV资源的申请,用来声明对存储空间、访问模式、存储类别需求信息。PVC会受到namespace隔离与PV不同
- PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了
- PV和PVC的什么周期
- PVC和PV是一 一对应的, PV和PVC之间的相互作用遵循以下生命周期
- 资源供应:管理员手动创建底层存储和PV,状态处于Available
- 资源绑定:用户创建PVC, kubernetes负责根据PVC的声明去寻找PV,并绑定,状态为Bound
- 在用户定义好PVC之后,系统将根据PVC对存储资源的请求在已存在的PV中选择一个满足条件的
- 一旦找到,就将该PV与用户定义的PVC进行绑定,用户的应用就可以使用这个PVC了
- 如果找不到,PVC则会无限期处于Pending状态, 直到等到系统管理员创建了一个符合其要求的PV
- 在用户定义好PVC之后,系统将根据PVC对存储资源的请求在已存在的PV中选择一个满足条件的
- 资源使用:用户可在pod中像volume一样使用pvc
- 当存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为”已释放(Released)“,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被留在存储设备上,只有在清除之后该PV才能再次使用
- 资源释放:用户删除pvc来释放pv
- 资源回收:kubernetes根据pv设置的回收策略进行资源的回收,只有PV的存储空间完成回收(处于Available状态),才能供新的PVC绑定和使用
配置存储之ConfigMap、Secret
configMap
- ConfigMap是一种比较特殊的存储卷,它的主要作用是以键值对的形式来存储配置信息的,可以将环境变量配置信息和容器镜像解耦,便于应用配置的修改
- ConfigMap必须在Pod使用它之前创建,Pod只能使用同一个命名空间的ConfigMap
Secret
- Secret资源主要用于存储和管理一些敏感数据,比如密码,token,密钥,证书等敏感信息。它把 Pod 想要访问的加密数据存放到 etcd 中。然后用户就可以通过在 Pod 的容器里挂载 Volume 的方式或者环境变量的方式访问到这些 Secret 里保存的信息了
问题
-
Pod为什么是Kubernets里的原子调度单位?
涉及到资源调度问题,如果容器为最小单位,一个Pod里面多个容器,可能会出现node资源不够导致容器无法全部部署在同一个node上
-
Pod里面为什么有多个容器?
容器之间可能存在以下场景:互相之间文件交换、频繁的远程调用、共享Namespace