POD:
POD模板:
控制器(如deployment、daemonset、statefulset等)是通过创建pod模板来创建和管理pod的,PodTemplate是用于创建pod的规范,并且包含在deployment、job和daemonset中。
cat job-template.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# This is the pod template
spec:
containers:
- name: hello
image: busybox
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# The pod template ends here
修改pod template或切换到新的pod tmplate对已经存在的pod没有影响。 POD不直接接收模板更新,而是创建一个新的POD来匹配修改后的POD模板。
和pod相关的api对象
kubectl explain pods
kubectl explain pod.apiVersion
apiVersion
apiVersion定义了此对象表示的版本化模式。服务器应将已识别的模式转换为最新的内部值,并可能拒绝无法识别的值。更多信息参考:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
查看k8s集群支持的apiVersion有哪些,可以使用下面的命令:
kubectl api-versions
kind
Kind是表示此对象表示的REST资源的字符串值。服务器可以从客户端提交请求的端点推断出这一点,说白了就是表示我们要创建什么资源,如deployment、statefulset、pod、service、ingress
查看更详细信息可参考:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata
标准对象的元数据。更多信息:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec
指定容器的所需行为。更多信息:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status
最近观察到的pod的状态。此数据可能不是最新的。Status不需要在pod或者其他资源中定义,这个默认是存在的
apiVersion: v1
kind: Pod
metadata:
name: web
namespace: default
annotations:
spek: "test-pod-tomcat"
labels:
web1: tomcat
spec:
containers:
- name: pod-tomcat
image: docker.io/library/tomcat:8.5
imagePullPolicy: IfNotPresent
- name: busybox
image: docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
command: ["top","-b"]
#通过kubectl apply创建一个pod
kubectl apply -f pod.yaml
#查看pod创建的情况
kubectl get pods
显示如下:
NAME READY STATUS RESTARTS AGE
web 0/1 ContainerCreating 0 37s
#查看pod的详细信息
kubectl describe pods web
# pod.yaml定义的所有资源都删除掉
kubectl delete -f pod.yaml yaml
#查看pod调度到哪个节点
kubectl get pods -o wide
显示如下:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 5m30s 10.244.1.21 node1 <none> <none>
#查看pod日志
kubectl logs web
#查看pod里指定容器的日志
kubectl logs -c tomcat1 web
k8s不支持修改yaml了直接apply 需要删除了再启动
#进入到刚才创建的pod,刚才创建的pod名字是web
kubectl exec -it web -- /bin/bash
#假如pod里有多个容器,进入到pod里的指定容器,按如下命令:
kubectl exec -it web -c tomcat1 -- /bin/bash
我们上面创建的pod是一个自主式pod,也就是通过pod创建一个应用程序,如果pod出现故障停掉,那么我们通过pod部署的应用也就会停掉,不安全,所以还有一种pod,
还有一种控制器管理的pod,通过控制器创建pod,可以对pod的生命周期做管理,如定义pod的副本数,如果有一个pod意外停掉,那么会自动起来一个pod替代之前的pod,之后会讲解pod的控制器
kubectl get pods
可查看到刚才创建的pod
pod的持久性
一般来说,用户不需要直接创建 Pod。他们几乎都是使用控制器进行创建,即使对于单例的 Pod 创建也一样使用控制器,例如Deployments控制
(无状态,一组集群单个出问题不会有影响,共用volume)
器提供集群范围的自修复以及副本数和滚动管理。 像StatefulSet这样的控制器还可以提供支持有状态的Pod。
(如主从数据库)
Pod生命周期
同一个pod中可以运行多个容器,我们在创建一个pod时可以通过创建多个容器来实现pod的整个生命周期,一个pod的创建包含如下过程:
Init容器(也叫做初始化容器):kubectl explain pod.spec.initContainers
Init容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,只有所有的初始化容器执行完后,主容器才启动。由于一个Pod里的存储卷是共享的,所以Init Container里产生的数据可以被主容器使用到,Init Container可以在多种K8S资源里被使用到,如Deployment、DaemonSet, StatefulSet、Job等,但都是在Pod启动时,在主容器启动前执行,做初始化工作。
主容器:
容器钩子:kubectl explain pod.spec.containers.lifecycle
对于pod资源来说,容器钩子是在pods.spec.containers.lifecycle下定义的
初始化容器启动之后,开始启动主容器,在主容器启动之前有一个post start hook(容器启动后钩子)和pre stop hook(容器结束前钩子)
postStart:该钩子在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的hook handler执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数
preStop:该钩子在容器被删除前触发,其所对应的hook handler必须在删除该容器的请求发送给Docker daemon之前完成。在该钩子对应的hook handler完成后不论执行的结果如何,Docker daemon会发送一个SGTERN信号量给Docker daemon来删除该容器,这个钩子不需要传递任何参数
#查看postStart怎么定义的,可以用如下命令:
kubectl explain pods.spec.containers.lifecycle.postStart
#查看preStop怎么定义的,可以用如下命令:
kubectl explain pods.spec.containers.lifecycle.preStop
容器探针:
livenessProbe:存活探测
指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success。
readinessProbe:服务探测
指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success
#查看livenessProbe帮助命令:
kubectl explain pods.spec.containers.livenessProbe
#查看readinessProbe帮助命令:
kubectl explain pods.spec.containers.readinessProbe
整个图如下:
从上面可以看出,我们pod在从创建到结束之前,会一直处于某种状态之中,有一些状态:
常见的pod状态
(1)Pending:挂起,我们在请求创建pod时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件。已经创建了但是没有适合它运行的节点叫做挂起,调度没有完成。
(2)Running:运行状态
(3)Failed:表示失败
(4)Succeeded:表示成功状态
(5)Unknown:未知状态,所谓pod是什么状态是apiserver和运行在pod节点的kubelet进行通信获取状态信息的,如果节点之上的kubelet本身出故障,那么apiserver就连不上kubelet,得不到信息了,就会看Unknown
创建pod时大概经历哪些阶段:
初始化容器(initContainers)–>主容器
pod重启策略
Always:只要容器挂了就重启
OnFailure:只有容器状态为错误的时候才重启
Never:从不重启容器
默认重启策略就是Always
#查看重启策略restartPolicy怎么定义的:
kubectl explain pods.spec.restartPolicy
名称空间-namespace
namespace叫做命名空间,可以把k8s集群划分成多个名称空间,然后对不同的名称空间的资源做隔离,可以控制各个名称空间的入栈,出栈策略,是一种在多个用户之间划分群集资源的方法
#查看k8s集群当前有哪些名称空间:
kubectl get namespace
pod label
(1)什么是标签?
标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够标示对象的特殊特点,并且对用户而言是有意义的(就是一眼就看出了这个Pod是干什么的),标签可以用来划分特定组的对象(比如版本,服务类型等),标签可以在创建一个对象的时候直接给与,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的
(2)查看所有pod资源对象的标签
kubectl get pods --show-labels
(3)查看带有指定标签的pod
kubectl get pods -L web1
显示所有资源对象下web1这个标签的标签值
(4)kubectl get pods -l web1 --show-labels
查看拥有web1这个标签的资源对象,并且把标签显示出来
(5)想修改资源的标签,比方说想给web加上个release标签
给资源对象打标签要使用label命令,指定给某个类型下的某个资源打标签,资源中的key/value可以是多个,因此在web(pod名字)这个资源下再打个标签release,用如下命令
kubectl label pods web release=new
查看标签是否打成功:
kubectl get pods --show-labels
显示如下,显示如下,说明标签达成功了;
NAME READY STATUS RESTARTS AGE LABELS
web 1/1 Running 1 21h release=new,web1=tomcat
(6)k8s的标签选择器:
与name和UID不同,label不提供唯一性。通常,我们会看到很多对象有着一样的label。通过标签选择器,客户端/用户能方便辨识出一组对象。
API目前支持两种标签选择器:基于等值的和基于集合的标签选择器。一个label选择器可以由多个必须条件组成,由逗号分隔。在多个必须条件指定的情况下,所有的条件都必须满足,因而逗号起着AND逻辑运算符的作用。
一个空的label选择器(即有0个必须条件的选择器)会选择集合中的每一个对象。
一个null型label选择器(仅对于可选的选择器字段才可能)不会返回任何对象。
基于等值关系的标签选择器:kubectl get pods --show-labels -l app!=mysql-zr
=,,!=
基于相等性或者不相等性的条件允许用label的键或者值进行过滤。匹配的对象必须满足所有指定的label约束,尽管他们可能也有额外的label。有三种运算符是允许的,“=”,“”和“!=”。前两种代表相等性(他们是同义运算符),后一种代表非相等性。例如:
environment = production tier != frontend
第一个选择所有键等于 environment 值为 production 的资源。后一种选择所有键为 tier 值不等于 frontend 的资源,和那些没有键为 tier 的label的资源。
要过滤所有处于 production 但不是 frontend 的资源,可以使用逗号操作符, environment=production,tier!=frontend 。
第二类叫做基于集合的标签选择器:
基于集合的label条件允许用一组值来过滤键。支持三种操作符: in , notin ,和 exists(仅针对于key符号) 。例如:
environment in (production, qa)
tier notin (frontend, backend)
第一个例子,选择所有键等于 environment ,且value等于 production 或者 qa 的资源。 第二个例子,选择所有键等于tier且值是除了frontend 和 backend 之外的资源,和那些没有label的键是 tier 的资源。 类似的,逗号操作符相当于一个AND操作符。因而要使用一个 partition 键(不管值是什么),并且 environment 不是 qa 过滤资源可以用 partition,environment notin (qa) 。
基于集合的选择器是一个相等性的宽泛的形式,因为 environment=production 相当于environment in (production) ,与 != and notin 类似。
基于集合的条件可以与基于相等性 的条件混合。例如, partition in (customerA,customerB),environment != qa 。
标签选择器根据定义的标签可以选择匹配到的资源对象
更多详细信息可参考:
https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
Example labels:
*
“release” : “stable”, “release” : “canary”
*
版本:稳定版和发行版
*
“environment” : “dev”, “environment” : “qa”, “environment” : “production”
*
环境:开发 测试 生产
*
“tier” : “frontend”, “tier” : “backend”, “tier” : “cache”
*
前段后端,缓存层
*
“partition” : “customerA”, “partition” : “customerB”
*
*
“track” : “daily”, “track” : “weekly”
node label
(1)查看nodes节点的标签
kubectl get nodes --show-labels
(2)给node节点打标签:
kubectl label nodes node1 node011=haha
kubectl get nodes --show-labels
可以看到node01上有node011这个标签了
(3)节点选择器nodeSelector
#查看nodeSelector帮助命令
kubectl explain pods.spec.nodeSelector
nodeSelector <map[string]string>
NodeSelector is a selector which must be true for the pod to fit on a node.
Selector which must match a node’s labels for the pod to be scheduled on
that node. More info:
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
上面有一个nodeSelector,这个是节点标签选择器,可以限制pod运行在哪个节点上
kubectl get pods -o wide
从上面可以看到web运行在node1上,如果我们想要让它运行在master1上,就需要用到节点选择器
nodeSelector:
node011: haha
#这个node011是我们给node1节点打的标签,在上面已经操作过
cat pod.yaml 看到完整的文件如下:
apiVersion: v1
kind: Pod
metadata:
name: web
namespace: default
labels:
web1: tomcat
spec:
containers:
- name: tomcat1
image: tomcat:8.5-jre8-alpine
nodeSelector:
node-1:test
kubectl delete -f pod.yaml
kubectl apply -f pod.yaml
kubectl get pods -o wide
显示pod运行在node1上
如果node1和node2都有node011这个标签,那么nodeSelector则根据调度策略调度pod到相应的node节点上。
更多详细信息可参考:
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
节点名称
nodeName:指定pod节点运行在哪个具体node上,不存在调度说法
查看 nodeName帮助命令:
kubectl explain pods.spec.nodeName