一、Pod定义详解
Pod可以由一个或者多个容器组合而成。
注意:
在k8s中,对长时间运行容器的要求是:其主程序需要一直在前台执行,如果我们
创建的Docker镜像的启动命令是后台执行程序,例如Linux脚本:
nohup ./start.sh &
则在kubelet创建包含这个容器的pod之后运行完该命令,即认为pod执行结束,将立
即销毁该Pod;然后Pod又定义了副本数,会重启,这样会陷入一个死循环;
1、静态Pod
2、Pod容器共享Volume
在同一个Pod中的多个容器能够共享Pod级别的存储卷Volume。
Volume可以定义为各种类型,多个容器各自进行挂载操作,将一个Volume挂载为容器内部需要的目录。
二、ConfigMap:容器应用的配置管理(项目配置文件解决方案之一)
为了将配置文件与程序应用隔离,使得程序更好的复用,K8S提供了ConfigMap来解决。
典型用法:
- 生成为容器内的环境变量
- 设置容器的启动参数
- 以Volume挂载容器目录
ConfigMap的创建:
- 以yaml文件创建ConfigMap
- kubectl命令创建,参数:—from-file或—from-literal
ConfigMap的使用:
- 环境变量方式:在创建pod的时候将ConfigMap的变量引入进来
- VolumeMount模式:将ConfigMap声明的文件以挂载方式使用
使用ConfigMap的限制条件
- ConfigMap必须在pod之前创建
- ConfigMap受Namespace限制,只有处于相同Namespace中的Pod才可以引用它
- ConfigMap中的配额管理还未能实现
- kubelet只支持可以被API Server管理的Pod使用ConfigMap。kubelet在本Node上通过—maniifest-url或—config自动创建的静态Pod将无法引用ConfigMap
- 在Pod对ConfigMap进行挂载操作时,容器内部只能挂载为“目录”,无法挂载为“文件”。在挂载到容器内部后,目录中将包含ConfigMap定义的每个item,如果该目录下原来还有其他文件,则容器内的该目录将会被挂载的ConfigMap覆盖。如果应用程序需要保留原来的其他文件,则需要进行额外的处理。可以将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件赋值或者链接到应用所用的实际配置目录下
三、在容器内获取Pod信息(Downward API)
每个Pod在成功创建出来之后,都会被系统分配唯一的名字、IP地址,并且处于某个Namespace中,那么我们如何在Pod的容器内获取Pod的这些重要信息呢?答案就是使用Downward API。
有以下两种方式:
- 环境变量:用于单个变量,可以将Pod信息和Container信息注入容器内部
- Volume挂载:将数组类信息生成文件,挂载到容器内部
例如:环境变量方式 — 将Pod信息注入为环境变量
dapi-test-pod.yaml
apiVesion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
-name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
-name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
-name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
其中,podId就是Pod信息
例如:环境变量方式:将容器资源信息注入为环境变量
dapi-test-pod.yaml
apiVesion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: busybox
command: ["/bin/sh", "-c", "env"]
resources:
requests:
memory: "32Mi"
cpu: "125m"
env:
-name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: request.cpu
-name: MY_MEM_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: request.memory
其中,request.memory就是该容器在yaml文件中声明的资源对象的值
例如:Volume挂载方式:将容器资源,通过Volume方式挂载到容器内部
dapi-test-pod.yaml
apiVesion: v1
kind: Pod
metadata:
name: dapi-test-pod
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
annotations:
build: two
builder: john-doe
spec:
containers:
- name: test-container
image: busybox
command: ["/bin/sh", "-c", "env"]
volumeMounts:
- name: podInfo
mountPath: /etc
readOnly: false
volumes:
- name: podInfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
其中,podInfo在容器内部挂载的路径下会生成labels和annotations两个文件,其中labels包含了metadata.labels全部的label列表。
获取Pod信息的用处
通过环境变量读取pod信息:
1.写入配置文件,可以做集群自动发现的功能;
2.以pod name为维度的收集信息,比如:log;
四、Pod生命周期和重启策略
Pod状态包括以下:
- Pending:API已经创建Pod,可是Pod内还有一个或者多个容器的镜像没有创建,包括正在下载的镜像;
- Running:Pod内的所有镜像均已创建,且至少有一个容器处于运行状态、正在启动状态或者重启状态;
- Successed:所有容器都已启动成功,且不会重启;
- Failed:Pod内的所有容器均已退出,但至少有一个容器退出为失败状态;
- Unkonwn:由于某种原因无法获取该Pod的状态,可能是网络原因;
Pod的重启策略:
- Alaways:当容器失效时,由kubelet自动重启该容器;
- OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器;
- Never:不论Pod状态如何,都不会重启该容器;
五、Pod健康检查
两类探针检查:LivenessProbe和ReadinessProbe
- LivenessProbe:用于判断容器是否存活,如果探测到容器不健康,kubelet会杀掉该容器,并根据Pod策略重启该容器;
- ReadinessProbe:用于判断容器是否启动成功;如果检测到失败,则会修改pod的状态;
三种检查手段:
- ExecAction:在容器内部执行一个命令,如果该命令的返回码为0,则表明容器健康
- TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP链接,则表明容器健康
- HTTPGetAction:通过容器的IP地址、端口号及路径调用HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器状态健康
六、Pod调度
全自动调度
由Master的Scheduler经过一系列算法计算得出,用户无法干预调度过程和结果;
NodeSelector:定向调度
通过给Node打标签和使用Pod的NodeSelector属性匹配,来达到NodeSelector的定向调度;
- 通过kubectl label命令给目标Node打上一些标签
$ kubectl label nodes <node-name> <label-key>=<label-value>
- 在Pod的定义中加上NodeSelector的设置
NodeAffinity:Node亲和性调度
NodeAffinity意为Node亲和性的调度策略,是用于替换NodeSelector的全新调度策略。目前有两种节点亲和性表达:
- RequiredDuringSchedulingIgnoredDuringExecution:必须满足指定的规则才可以调度Pod到Node上,相当于硬限制;
- PreferredDuringSchedulingIgnoredDuringExecution:强调优先满足指定规则,调度器会尝试调度Pod到Node上,但并不强求,相当于软限制。多个优先级规则还可以设置权重值,以定义执行的先后顺序;
PodAffinity:Pod亲和与互斥调度策略
Pod的亲和性调度的表达也有两种:
- RequiredDuringSchedulingIgnoredDuringExecution
- PreferredDuringSchedulingIgnoredDuringExecution
Pod的亲和度与互斥调度,定义与同一层次中的podAntiAffinity子字段中
Taints和Tolerations(污点和容忍)
前面介绍的NodeAffinity节点亲和性,是在Pod上定义的一种属性,是的Pod能够被调度到某些指定的Node上。Taint则正好相反,它让Node拒绝Pod的运行;
七、DaemonSet:在每个Node上调度一个Pod
DeamonSet是k8s在v1.2版本上新增的一种资源对象,用于管理在集群中每个Node上仅运行一份Pod的副本实例;
使用场景:
- 在每个Node上运行一个GlusterFS存储或者Ceph存储的Daemon进程
- 在每个Node上运行一个性能监控程序,例如:Fluentd或者Logstach
- 在每个Node上运行一个性能监控程序,采集该Node的运行性能数据,例如:Prometheus Node Exporter...
八、Job:批处理调度
九、CronJob:定时任务
k8s从v1.5版本开始增加了一种新类型的Job,即类似Linux Cron的定时任务Cron Job;
- 在Api Server的启动进程上增加以下配置参数并重启:
--runtime-config=batch/v2alphal=true
- 编写Cron Job yaml配置文件
- 创建:kubectl create -f cron.yaml
- kubectl get cronjob -n namespace
十、Pod的扩容和缩容
通过修改副本数量,来达到自动扩、缩容
$ kubectl get deploy -n namespace
$ kubectl edit deploy deployName -n namespace
十一、Pod的滚动升级
滚动升级通过执行:
kubectl rolling-update name --image=imageName
命令完成。可以看到kubectl通过创建一个新的Pod版本,停掉一个旧的
Pod版本,逐步迭代完成整个滚动升级。
或者
$ kubectl get deploy -n namespace
$ kubectl edit deploy deployName -n namespace