yaml 编写
可以通过 kubectl explain 查看资源清单包含了那些字段
kubectl explain Pod
可以通过提供的More info 网页查看具体的配置样例
apiVersion 定义了对象版本
Kind 定义了资源类型
matadata 定义了元属性信息 <资源名称>
spec 定义了Pod的规格,具体容器信息
status 定义了状态,不可修改,不需要定义。
查看matadata对象该如何定义
kubectl explain Pod.metadata
查看对象该如何定义直接在后面.+对象名即可。
字段类型为 <string> 字符串
apiVersion: v1
字段类型为 <Object> 对象
metadata:
字段类型为 <map[string]string> map集合
key: value
字段类型为 <[]Object> 对象列表
- name: tomcat-pod-java
带有required 为必填
常见属性:
metadate:
- labels 创建资源具有的标签
- namespace 资源所属命名空间(默认default)
spec:
- activeDeadlineSeconds pod可运行的最长时间
- affinity pod亲和性
- containers 定义容器必填字段,至少要有一个容器
- dnsConfig
- dnsPolicy
pod.spec.containers
- args
- command
- env
- envFrom
- image 用来指定容器需要的镜像
- imagePullPolicy 镜像拉取策略,Always 一直重新拉取、Never 从不拉取镜像、IfNotPresent优先使用本地镜像,没有在拉取镜像。
- name
- ports 端口
pod.spec.containers.ports
- containerPort 必须字段,端口号
- hostIP 将容器中的服务暴露到宿主机的端口上时,可以指定绑定的宿主机 IP
- hostPort 容器中的服务在宿主机上映射的端口
- name 端口名称
样例:
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
labels:
app: myapp
spec:
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat
命名空间
k8s中物理集群中的虚拟集群。可以给不同用户、租户、环境或项目创建对应的命名空间。
命名空间的名称仅能是字母、数字、下划线、连接线等字符组成。
命名空间通过资源配额可以限制资源。
删除命名空间,级联下的资源对象也会被删除。
# 创建命名空间
kubectl create namespace test
# 切换当前命名空间。切换命名空间后,kubectl get pods 如果不指定-n,查看的就是test命名空间的资源了。
kubectl config set-context --current --namespace=test
# 查看哪些资源属于命名空间级别的
kubectl api-resources --namespaced=true
资源限额
命名空间可以通过ResourceQuota限制空间资源
kubectl explain resourcequotas
apiVersion: v1
kind: ResourceQuota
metadata:
name: test-rq
# 指定名称空间
namespace: test
spec:
hard:
# 所有容器的内存请求总额不得超过
requests.cpu: "1"
# 所有容器的CPU请求总额不得超过
requests.memory: 1Gi
# 所有容器的内存限额总额不得超过
limits.cpu: "2"
# 所有容器的CPU限额总额不得超过
limits.memory: 2Gi
名称空间下的每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
查看限额
kubectl get quota -n test
标签
标签是一对 key/value, 被关联到对象。标签可以用来划分特定的对象,一个对象可以有多个标签。但是key值必须是唯一的。通过标签可以方便的对资源进行分组管理。k8s中大部分资源都可以打标签。
# 查看pods 标签,其他资源也可以用--show-labels查看标签
kubectl get pods --show-labels
# 对已经存在的pod打标签
kubectl label pod pod名称 key=value
# 列出默认命名空间下所有标签 key=app,不显示标签
kubectl get pods -l app
# 列出默认命名空间下所有标签 key是app,value是myapp 不显示标签
kubectl get pods -l app=myapp
# 列出默认名称空间下标签key是app的所有pod,并打印对应的标签值
kubectl get pods -L app
# 查看所有名称空间下的所有pod的标签
kubectl get pods --all-namespace --show-labels
node节点选择器
我们创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或调度到一些具有相同特点的node节点可以使用pod中的nodeName或nodeSelector字段指定调度到的节点
nodeName
kubectl explain pod.spec
通过nodeName 可以直接指定调度到那个节点
样例:
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
labels:
app: myapp
spec:
nodeName: k8snode02
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat
nodeSelector
通过node节点标签选择器,进行调度
样例:
# 节点打标签
kubectl label node k8snode01 dome=test
# dome yaml文件
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
labels:
app: myapp
spec:
nodeSelector:
dome: test
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat
污点和容忍度
亲和性(affinity)
kubectl explain pod.spec.affinity
node节点亲和性(nodeAffinity)
Node节点亲和性针对的是pod和node的关系,Pod调度到node节点的时候匹配的条件
preferredDuringSchedulingIgnoredDuringExecution (软亲和性)
requiredDuringSchedulingIgnoredDuringExecution (硬亲和性,必须满足)
查看文档可以获得填写规则
kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
填写筛选条件 values 可以设置多个 满足其中一个即可。
样例:根据节点标签dome=test完成调度
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
labels:
app: myapp
spec:
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: dome
operator: In
values:
- test
- dev
Pod节点亲和性
kubectl explain pod.spec.affinity
pod 自身亲和性调度有两种表现形式
podAffinity (pod亲和性)
podAntiAffinity (pod反亲和性)
使用pod亲和性必须添加位置拓扑键 topologyKey,完成调度的参照。
样例:
节点亲和性
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
labels:
dome: aff
spec:
containers:
- name: tomcat-pod
ports:
- containerPort: 8080
image: tomcat
affinity:
# 节点亲和性
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# 列表字段有同级属性时,子属性多缩进两个空格
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
# 位置拓扑键参照主机名调度
topologyKey: kubernetes.io/hostname
节点反亲和性:
apiVersion: v1
kind: Pod
metadata:
name: demo-pod2
labels:
dome2: noaff
spec:
containers:
- name: tomcat-pod2
ports:
- containerPort: 8080
image: tomcat
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
污点
给节点选择的主动权,我们给节点打个污点,不能容忍的pod就运行不上来。
污点是定义在节点上的键值属性数据。taints是键值对数据。
污点等级
- NoSchedule (仅影响pod调度,后来的pod不容忍这个污点无法调度到该节点,已存在的pod不受影响)
- NoExecute(既影响现有pod也影响pod调度,节点中现有pod会被剔除)
- PreferNoSchedule (最好不也可以是NoSchedule的柔性版本)
# 查看污点
kubectl describe nodes |grep Taints
# 给节点打污点
kubectl taint nodes 节点名 key=value:NoSchedule
# 删除污点
kubectl taint nodes 节点名 key-
污点容忍
kubectl explain pod.spec.tolerations
如果 operator 的值是 Exists,则 value 属性可省略
如果 operator 的值是 Equal,则表示其 key 与 value 之间的关系是 equal(等于)
如果不指定 operator 属性,则默认值为 Equal
另外,还有两个特殊值:
空的 key 如果再配合 Exists 就能匹配所有的 key 与 value,也是是能容忍所有 node 的所有 Taints
空的 effect 匹配所有的 effect
样例:
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
labels:
app: myapp
spec:
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: dome
operator: In
values:
- test
tolerations:
- key: "taint"
operator: "Equal"
value: "node02"
effect: "NoSchedule"
pod常见状态
pod的status简述了其生命周期的阶段。
挂起(pending): pod创建时调度条件不满足,多会处于此状态。
运行中(running): pod正常运行。
成功(succeeded): pod成功运行结束,并且不在重启
失败(failed): pod中容器异常终止,或者说容器以非0状态推出
未知(unknown):未知状态,pod所在节点kubelet故障未上报pod信息,
Evicted: 这种状态多见系统内存不足
CrashLoopBackOff: 容器启动又异常退出,重启次数过多也会出现此状态
Error 状态:Pod 启动过程中发生了错误
ready 代表pod的容器状态
问题排查命令
查看pod详情
kubectl describe pod pod名称 (如果不是默认空间需要指定空间名)
查看pod容器日志
kubectl logs test-host -c test-host
pod 重启策略
pod重启策略(RestartPolicy)应用于pod内的所有容器,pod所在的node上的kubelet会进行判断和重启操作。某个容器异常推出或健康检测失败会。kubelet会根据重启策略进行操作
pod的重启策略包括: Always、OnFailure、Never 默认是Always
Always:当容器失败时,由kubelet自动重启该容器。
OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。
Never:不论容器运行状态如何,kubelet都不会重启该容器。
示例:
apiVersion: v1
kind: Pod
metadata:
name: test2
spec:
restartPolicy: Never
containers:
- name: test2
image: nginx
生命周期
init容器
pod中可以定义多个容器,部署应用的容器称为主容器。pod创建时可以有一个或多个先于主容器启动的init容器,init容器中的程序执行完了才会运行主容器,由于pod中共享存储,多用于主容器启动前的一些初始化工作
init容器与主容器区别:
1 init容器运行完,主容器才会启动。
2 每个init容器必须运行成功,才可以执行下一个init容器
3 如果init容器运行失败,pod会不断重启,知道运行成功,如果重启策略设置为Never,他不会重启
示例:
apiVersion: v1
kind: Pod
metadata:
name: init-test
spec:
initContainers:
- name: init-con
image: centos
command: ["sh", "-c", "echo '123' > /temdir/123"]
volumeMounts:
- mountPath: "/temdir"
name: vol
containers:
- name: zhu-con
image: centos
command: ["sh", "-c", "cat /temdir/123 && sleep 3600"]
volumeMounts:
- mountPath: "/temdir"
name: vol
volumes:
- name: vol
emptyDir: {}
容器探测
容器钩子
初始化容器启动之后,开始启动主容器,在主容器启动之前有一个post start hook(容器启动后钩子)和pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放两个钩子,这个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的清理,如awk有begin,end,和这个效果类似;
postStart:该钩子在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的hook handler执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。
preStop:该钩子在容器被删除前触发,其所对应的hook handler必须在删除该容器的请求发送给Docker daemon之前完成。在该钩子对应的hook handler完成后不论执行的结果如何,Docker daemon会发送一个SGTERN信号量给Docker daemon来删除该容器,这个钩子不需要传递任何参数。
在k8s中支持两类对pod的检测,第一类叫做livenessprobe(pod存活性探测):
存活探针主要作用是,用指定的方式检测pod中的容器应用是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的 restartPolicy来判断Pod 是否要进行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测一直为成功状态。
第二类是状态检readinessprobe(pod就绪性探测):用于判断容器中应用是否启动完成,当探测成功后才使Pod对外提供网络访问,设置容器Ready状态为true,如果探测失败,则设置容器的Ready状态为false。
postStart:容器创建成功后,运行前的任务,用于资源部署、环境准备等。
preStop:在容器被终止前的任务,用于优雅关闭应用程序、通知其他系统等。
lifecycle
......
containers:
- image: sample:v2
name: war
lifecycle:
postStart:
exec:
command:
- “cp”
- “/sample.war”
- “/app”
prestop:
httpGet:
host: monitor.com
path: /waring
port: 8080
scheme: HTTP
......
而在容器终止之前,发送HTTP警告请求到监控系统。
优雅的删除资源对象
当用户请求删除含有pod的资源对象时(如RC、deployment等),K8S为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:
1)、默认:K8S通知node执行docker stop命令,docker会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行kill掉进程。
2)、使用pod生命周期(利用PreStop回调函数),它执行在发送终止信号之前。默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户来修改默认值。0表示删除立即执行,并且立即从API中删除pod。在节点上,被设置了立即结束的的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。
spec:
containers:
- name: nginx-demo
image: centos:nginx
lifecycle:
preStop:
exec:
# nginx -s quit gracefully terminate while SIGTERM triggers a quick exit
command: ["/usr/local/nginx/sbin/nginx","-s","quit"]
ports:
- name: http
containerPort: 80
pod阶段
当用户创建pod时,这个请求给apiserver,apiserver把创建请求的状态保存在etcd中;接下来apiserver会请求scheduler来完成调度,如果调度成功,会把调度的结果(如调度到哪个节点上了,运行在哪个节点上了,把它更新到etcd的pod资源状态中)保存在etcd中,一旦存到etcd中并且完成更新以后,节点上的kubelet通过apiserver当中的状态变化知道有一些任务被执行了,所以此时此kubelet会拿到用户创建时所提交的清单,这个清单会在当前节点上运行或者启动这个pod,如果创建成功或者失败会有一个当前状态,当前这个状态会发给apiserver,apiserver在存到etcd中;在这个过程中,etcd和apiserver一直在打交道,不停的交互,scheduler也参与其中,负责调度pod到合适的node节点上,这个就是pod的创建过程。
pod探测
三种探测方法:
1、ExecAction:在容器中执行指定的命令,如果执行成功,退出码为 0 则探测成功。
2、TCPSocketAction:通过容器的 IP 地址和端口号执行 TCP 检 查,如果能够建立 TCP 连接,则表明容器健康。
3、HTTPGetAction:通过容器的IP地址、端口号及路径调用 HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器健康
存活性探测livenessProbe
K8S提供livenessProbe来检测容器是否正常运行,许多应用程序经过长时间运行,最终过渡到无法运行的状态。这时候检测到容器异常,kubelet会根据重启策略重启容器。
示例:
Exec:
apiVersion: v1
kind: Pod
metadata:
name: liveness
spec:
containers:
- image: centos
name: test-liv
command: ["sh", "-c", "touch /123 && sleep 120 && rm -rf /123 && sleep 600"]
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 5
exec:
command: ["sh", "-c", "cat /123"]
# #netstat -an|grep 80
# #echo $? 查看上面命令执行后的状态码
# 相关属性:
# initialDelaySeconds: Pod启动后首次进行检查的等待时间,单位“秒”。
# periodSeconds: 检查的间隔时间,默认为10s,单位“秒”。
# timeoutSeconds: 探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”。
# successThreshold:连续探测几次成功,才认为探测成功,默认为 1,在 Liveness 探针中必须为1,最小值为1。
# failureThreshold: 探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3,最小值为
tcp
apiVersion: v1
kind: Pod
metadata:
name: test-tcp
spec:
containers:
- name: test-tcp
image: nginx
# 存活性探测
livenessProbe:
# 容器启动多长时间后开始探测,默认是秒
initialDelaySeconds: 10
# 探测间隔时间,默认是秒
periodSeconds: 5
# 探测超时时间
timeoutSeconds: 10
# 探测端口
tcpSocket:
port: 80
# host 默认是本机
#TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds 参数设定的时间后,kubelet将发送第一个 livenessProbe 探针,尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。
http
apiVersion: v1
kind: Pod
metadata:
name: test-http
spec:
containers:
- name: test-http
image: nginx
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 5
httpGet:
port: 80
# httpGet探测方式有如下可选的控制字段:
# scheme: 用于连接host的协议,默认为HTTP。
# host:要连接的主机名,默认为Pod IP,可以在http request head中设置host头部。
# port:容器上要访问端口号或名称。
# path:http服务器上的访问URI。
# httpHeaders:自定义HTTP请求headers,HTTP允许重复headers。
就绪性探测readinessProbe
没有配置就绪性探测,pod中容器运行后默认成功。
就绪性探测和存活性探测配置方法类似。
区别在于:
存活性探测失败后会由kubelet根据重启策略操作pod.
就绪性探测失败后会从EndPoint中移除。
存活性探测和就绪性探测配合使用案例:
apiVersion: v1
kind: Pod
metadata:
name: test-live-read
spec:
containers:
- name: test-live-read
image: nginx
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 5
httpGet:
port: 80
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 5
httpGet:
port: 80