容器与pod
pod简介
pod是一组相关容器的集合:借助基础容器pause组成而成,pod中容器共享UTS、IPC、PID,但在mount、user、pid上又是隔离的,
pod是k8s集群管理的最小调度单元,也是k8s集群的核心资源,围绕其延伸出其他一系列资源,都为其提供服务:
deployment、replicatset、replicatcontroller用来管理无状态如web容器的运行;statufulset和operator管理有状态如db容器的运行;service和ingress为其暴露容器中提供的应用;configmap和secret为其提供一般配置和敏感配置功能;pv和pvc为pod提供可靠的持久数据存储;
pod架构
pod中容器组合模型
边车模型
即pod中一个主应用容器,其他容器为其提供辅助功能,如为web主容器的提供的日志收集,为db主容器启用本地缓存;
大使模型
即为远程服务创建一个本地代理,例如:主容器需要访问远程的redis应用,只需为其创建一个辅助容器在本地,访问时通过localhost访问辅助容器,间接访问到远程的redis服务;
远程redis服务发生变更时,只需修改辅助容器即可,主容器无需变更;
适配器模型
此种模型中,辅助容器起到了一个中间者标准化的作用,例如不管主容器输出日志格式如何,辅助容器都可以将其统一为一种格式输出,方便日志收集器收集,避免了日志收集器和主容器做任何变更;
管理pod中容器
定义pod常用字段
利用yaml文件定义pod资源时,常用的字段有:资源名,镜像的版本名,要暴露的端口,容器的入口程序,环境变量,pod需要的最低资源配置和最高上限,存储卷、运行身份serviceaccount、等;
镜像拉取策略
k8s集群的每个节点都需要为其容器引擎如docker配置合适的镜像仓库地址,如dockerhub(默认)或私有仓库;
imagepullPolicy定义了镜像的拉取策略
- always:总是去拉取最新的即lateset标签的镜像
- ifnotpresent:本地不存在的镜像再去拉取
- never:只使用本地镜像
注:
带有认证的私有仓库,都需要登陆,1:每个节点docker login先登陆一次;2、将认证信息定义为secret资源,在imagepullSecrets中调用;
端口暴露
ports:
- name: http # 给端口起个名字,
containerPort: 80 # 要暴露的容器端口
protocol: TCP # 协议,默认tcp,也可udp
对应pod的ip和开放端口,只有同一个集群内主机节点,和集群内其他pod可以访问,集群外部主机是无法访问,因此需要借助service或ingress资源来向集群外部暴露;
hostport字段:
该字段可以将pod的端口映射到指定的节点的某端口上,从而可以通过访问节点某端口进而访问到pod;
nodeport字段:
属于service中定义,与hostport不同的时,该定义会再集群每个节点多映射一该端口,而hostport只在pod运行的节点上映射;
修改容器中的运行程序
在docker镜像中,dockerfile通过entrypoint指定容器中运行程序,cmd指定传递给运行程序的参数;或采用cmd直接一起传递运行程序和其参数;
在定义pod的清单时:
command字段可以指定容器中运行的程序,会覆盖镜像中默认定义,args字段可以给要运行的程序传递参数;若只定义了args字段,将作为参数传递给镜像中默认运行程序,若只定义了command字段,将覆盖镜像原有程序,并以无参数方式运行;
环境变量
args可以向容器中应用传递配置信息,环境变量也可以实现;将配置信息定义成环境变量,在启动容器时,将清单中定义的环境传递给容器,实现容器的配置;
注:
该方式需要容器中应该支持环境变量的配置方式,如程序主程序文件可以接收一些命令行参数做配置,不支持应用的解决方法,通过entrypoint脚本,脚本中将args传入的环境变量,依次替换到程序的配置文件中,实现配置;
向pod中容器传递环境变量方法:env和envFrom,
env:
env字段,是环境变量组成的列表;
name和value组成的kv数据
eg;
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alpine
env:
- name: REDIE_HOST
value: myredis.io:6379
- name: LOG_LEVEL
value: info
环境变量会直接注入到容器的shell环境变量中,printenv可以看出;
共享主机网络hostNetwork
有些pod会需要能访问宿主节点的网络名称空间,如kubeadm部署的k8s组件:api-server、sechduler、kube-proxy等;在yaml文件中,定义字段hostNetwork: true
即可;pod监听的端口,也是监听在宿主节点上;
eg:以api-server为例,就设定了hostnetwork选项;其监听的6443端口,也监听到了节点上;
[root@master ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
[root@master ~]# grep hostNetwork !$
grep hostNetwork /etc/kubernetes/manifests/kube-apiserver.yaml
hostNetwork: true
[root@master ~]# ss -nlt |grep 6443
LISTEN 0 128 :::6443 :::*
另外,hostPID,hostIPC还可以共享节点的pid和ipc名称空间;
pod安全上下文
可以设置pod或容器的权限,访问控制功能;常用的有:
- 基于用户id的访问权限
- 基于selinux的安全标签
- 是否能权限升级
[root@client ~]# kubectl explain pods.spec.containers.securityContext
[root@client ~]# kubectl explain pods.spec.securityContext
#可分别在pod和containers级别设置;
标签与标签选择器
标签示例
一个集群中,会有各种不同种类的资源,此时借助标签,可以将不同的资源归类,定义资源时添加,或随时动态添加标签都可以,然后利用标签选择器过滤出特定标签的资源
资源常用的分类维度举例:
标签种类 | 示例 |
---|---|
环境标签 | env:dev env:test env:production |
版本标签 | release:stable release:beta release:cannary |
应用 | app:ui app:pc app:mobile |
架构层级 | tier: frontend tier:backend tier:middlerware |
分区 | partion:partA partion:partB |
品控级别 | track:daily track:weekly |
标签规范
格式:key_prefix/key_value
其中,key最多63字符,prefix可省略,一般k8s官方组件或第三方组件会填相应前缀,如KEY.kubernetes.io/VALUE
prefix为dns域名形式,以.隔开,最大253字符
管理标签
添加标签给pod
1、添加标签给pod
[root@client k8s_yaml]# cat pod-with-label.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-label
labels:
env: dev
tier: fronted
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
[root@client k8s_yaml]# kubectl apply -f pod-with-label.yaml
pod/pod-with-label created
2、查看标签
# 根据具体的标签键值过滤出pod
[root@client k8s_yaml]# kubectl get pods -L env=production
NAME READY STATUS RESTARTS AGE ENV=PRODUCTION
pod-with-label 1/1 Running 0 116s
# 过滤出具有tier标签的pod
[root@client k8s_yaml]# kubectl get pods -L tier
NAME READY STATUS RESTARTS AGE TIER
pod-with-label 1/1 Running 0 2m10s fronted
# 添加新标签
[root@client k8s_yaml]# kubectl label pods/pod-with-label release=stable
pod/pod-with-label labeled
[root@client k8s_yaml]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-with-label 1/1 Running 0 13m env=dev,release=stable,tier=fronted
定义标签选择器
pod资源定义时添加的标签,在replicaset、deployment、service中,就需要定义相应的标签选择器来匹配相应的pod对象;定义字段为selector,selector中定义时有matchlabels和matchExpressssions两种,1是等值匹配确定的标签、2是范围匹配一类标签
eg:
selector:
matchLabels:
env: test
app: db
matchExpressions:
- {key: tier, operator: In, values: {cache}}
- {key: env, operator: Exists, values: }
# matchLabels是等值
# matchExpressions是范围
多个条件之间是与的关系,需要同时满足;
matchExpressions的语法格式:
- {key: 某个key, operator: 动作in、notin、exists等, values: 比对的值,可以为空}
节点选择器
pod对象定义的spec.nodeselector可以选择pod运行时所选择的节点,如架构类型,os类型,硬件是否ssd,是否有gpu等,定义后,scheduler在调度pod时就会根据pod中定义的节点选择要求,选择与之匹配的节点进行运行pod;
当然节点上要事先定义好相应的标签,来标识节点的某些特性,如硬盘类型;节点本身自带一些标签:
[root@client ~]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master Ready master 2d v1.12.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node1 Ready <none> 28h v1.12.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node1
node2 Ready <none> 45h v1.12.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node2
node3 Ready <none> 27h v1.12.9 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node3
1、给pod定义nodeselector
[root@client k8s_yaml]# cat pod-with-label.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-label
labels:
env: dev
tier: fronted
spec:
nodeSelector:
disktype: ssd
containers:
- name: myapp
image: ikubernetes/myapp:v1
2、给节点打对应标签
[root@client k8s_yaml]# kubectl label nodes/node3 disktype=ssd
node/node3 labeled
3、查看调度效果
[root@client k8s_yaml]# kubectl apply -f pod-with-label.yaml
pod/pod-with-label created
[root@client k8s_yaml]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
pod-with-label 0/1 ContainerCreating 0 2s <none> node3 <none>
资源注解
资源注解:annotation,是类似标签的键值数据,用于标识某对象的元数据信息,只是不能像标签 一样用来过对象的过滤,长度不受限制,可是结构化或非结构化数据;
常用示例:
- 镜像相关信息:时间戳,git分支,哈希值等
- 人员联系方式:
- 指向日志、监控、分析或审计仓库的指针
- ...
查看注解
[root@client k8s_yaml]# kubectl get pods -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"env":"dev","tier":"fronted"},"name":"pod-with-label","namespace":"default"},"spec":{"containers":[{"image":"ikubernetes/myapp:v1","name":"myapp"}],"nodeSelector":{"disktype":"ssd"}}}
# 注意:在annotation中保存了pod在yaml中定义的信息,用于下次定义变动时做比对;
[root@client k8s_yaml]# kubectl describe pods/pod-with-label
Name: pod-with-label
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: node3/192.168.80.108
Start Time: Thu, 12 Nov 2020 15:19:41 +0800
Labels: env=dev
tier=fronted
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"env":"dev","tier":"fronted"},"name":"pod-with-label","namespace":"...
管理注解
可以在命令行或yaml文件中定义;
命令行:
kubectl annotate pods POD-NAME ilinux.io/created-by="cluster admin"
yaml文件:
[root@client k8s_yaml]# cat pod-with-label.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-label
labels:
env: dev
tier: fronted
annotations:
ilinux.io/created-by: cluster-admin
spec:
nodeSelector:
disktype: ssd
containers:
- name: myapp
image: ikubernetes/myapp:v1
pod生命周期
pod在其创建开始,到,结束退出,会经过若干的阶段,pod处于不同的状态,大致有:
- main container:创建主容器,(必须)
- init container: 运行初始化容器,(如帮主容器挂载个配置文件之类的)
- post start hook: 容器启动后钩子函数
- liveness probe: 存活性探测
- readinesss probe: 就绪性探测
- pre stop hook: 容器停止前hook函数
- 除了第一个,其余皆为非必须阶段,依据yaml文件定义而来;
pod的几种状态
- Pending:api-server已经创建了pod对象,并存入etcd中,尚未完成调度,如镜像下载中
- Running:pod完成调度,其中所有容器创建完成
- Succeded:pod中所有容器成功终止,不会被重启,如一次性的job容器
- Failed:至少一个容器终止失败;
- Unknown: 一般是api-server无法和节点的kubelet通信导致
pod的创建过程(9步)
- 通过kubectl或其他客户端,提交一个创建pod的请求给api-server
- api-server接收后,先将spec写入etcd,并返回给客户端
- 接收到刚刚的pod的spec定义后,此时api-server就发生了变化
- (其他组件都通过watch机制持续监测api-server的变化,其实是etcd的变化,api-server本身无状态)
- 检测到后,schduler先发现一个新的pod定义,但没被调度,会先为其选择一个节点,返回给api-server
- api-server将选中的节点信息写入etcd
- 被选中的节点上的kubelet监测到了这一结果,知道自己被选中了yep,然后kubelet调用容器引擎如docker,拉取镜像或利用本地镜像开始启动pod中所有容器,并将容器的状态信息结果返回给api-server
- api-server将接受到的pod的状态,写入etcd,即写入该pod的status属性
- etcd写入成功后,api-server发送确认给相关的kubelet,给个确认;
pod生命周期重点阶段
pod中主要的就是主容器,和辅助容器,除此之外,还可以根据需求定义init-container,存活探测,就绪探测等;
init-container
1、作用
初始化容器的作用:通常是为主容器准备其所需要的环境,如:
- 探测其所依赖的服务是否可用
- 根据环境变化、模版文件,修改注入配置文件
- 挂载卷等
- 从配置中心获取配置
2、特点
-
根据定义顺序依次执行
-
必须全部执行成功,否则一直重启,除非restartPolicy定义了never
-
提供主容器独立性,变更尽量在init-container镜像,使得主容器镜像较少变更
-
初始容器和主容器,独立的mount、pid、user,使得可以分别使用自己的secret等敏感资源
3、定义
[root@client k8s_yaml]# kubectl explain pods.spec.initContainers
KIND: Pod
VERSION: v1
RESOURCE: initContainers <[]Object>
# 是一个容器定义的对象列表
4、示例
apiVersion: v1
kind: Pod
metadata:
name: test-init-pod
labels:
app: myapp
spec:
containers:
- name: app1
image: ikubernetes/myapp:v1
initContaiers:
- name: init-test
image: busybox
command: ['sh','-c','sleep 10']
hook函数
1、hook函数分类
-
poststart:容器创建后运行的操作
-
prestop:容器停止前运行的操作,完成后,容器才可删除
2、hook函数定义的方式2种:
- exec:进入容器,执行命令
- http:进入容器,向某url发起请求
3、定义
定义在lifecycle中,也是个对象列表,在container下一层,定义在某个容器下一层,有poststart,和prestop两个字段,这俩也是列表,即可以定义多个hook行为
[root@client k8s_yaml]# kubectl explain pods.spec.containers.lifecycle
KIND: Pod
VERSION: v1
RESOURCE: lifecycle <Object>
DESCRIPTION:
Actions that the management system should take in response to container
lifecycle events. Cannot be updated.
4、eg:
apiVerson: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: app1
image: some-image
lifecycle:
poststart:
exec:
command: ["/bin/sh", "-c", "echo 'hello' > /index.html"]
容器探测
探测的种类:
- 存活性探测:容器running状态就通过,否则杀死重启,(依据restartPolicy)
- 就绪性探测:容器内服务是否准备好,如nginx服务, 未好就从service后端端点移除,直到就绪
探测的方式:
- exec:根据容器中执行命令,命令返回状态0为正常
- tcpsocket:探测端口是否可以访问
- httpget:探测某url,2xx或3xx状态码正常
容器的重启策略
三种重启策略:
- alway,默认的,pod终止就尝试重启
- never,绝不重启
- onfailure:pod出错就重启
反复重启时,时间间隔依次加长,直到最大300s,pod被绑定到某节点后,重启时就在该节点重启,除非节点故障重新调度,否则就在这个节点
pod的终止过程(5步)
pod的组成为多个容器,容器在节点内核看来,就是进程树上一个个进程,**因此停止pod就是停止节点上的容器的进程,通过发送信号实现,**过程如下:
- 用户通过客户端发送删除指令,如kubectl delete
- api-server接受到后,更新该pod在etcd的状态,为terminating状态,(启动计数器默认30s,给容器从容退出的时间)
- 其他组件:通过watch机制发现(同时)
- 该pod所在节点的kubelet监测到该pod变为terninating状态,即发送term信号给docker引擎,进而停止pod中容器
- 若容器中定义了prestop操作会在接收term信号后先执行prestop,完毕后,再退出容器进程;
- 端点endpoint控制器检测到pod的状态变化,会更新其所属service,将其移除service的可用列表中
- pod中所有容器停止后,kubelet会返回信息给api-server
- api-server会更新etcd中该pod的状态,计数器归0,删除该pod所有信息
- 注:容器停止过程超过默认30s时,kubelet会发送sigkill信号,直接杀死相关容器进程
图示:
pod存活性探测
在pod的容器级别的下一层可以定义存活性探测字段:livenessprobe,其中有3种探测方式:
- exec:在容器中执行命令,命令结果返回0则表示健康,否则不健康
- httpget:http请求访问容器某url,状态码2xx或3xx表示健康,否则异常
- tcpsocket:向目标容器建立tcp连接,成功建立正常,否则异常
[root@client ~]# kubectl explain pods.spec.containers.livenessProbe
exec探针
1、示例
[root@client k8s_yaml]# cat pod-liveness.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-liveness
spec:
containers:
- name: busybox
image: busybox
args: ['/bin/sh', '-c', 'touch /tmp/yes; sleep 30 ;rm -rf /tmp/yes']
livenessProbe:
exec:
command: ['test', '-e', '/tmp/yes']
2、查看pod状态
可以看到pod会不断重启,因为每30s后,探测/tmp/yes文件就会失败
[root@client k8s_yaml]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
pod-liveness 0/1 CrashLoopBackOff 8 25m 10.244.2.3 node1 <none>
pod-with-label 1/1 Running 1 19h 10.244.4.4 node3 <none>
[root@client k8s_yaml]# kubectl describe pods/pod-liveness
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 25m default-scheduler Successfully assigned default/pod-liveness to node1
Normal Created 21m (x4 over 25m) kubelet, node1 Created container
Normal Started 21m (x4 over 25m) kubelet, node1 Started container
Normal Pulling 20m (x5 over 25m) kubelet, node1 pulling image "busybox"
Normal Pulled 20m (x5 over 25m) kubelet, node1 Successfully pulled image "busybox"
Warning BackOff 39s (x89 over 23m) kubelet, node1 Back-off restarting failed container
http探针
livenessProbe下级的httpGet方法定义了http探针的方式:
1、语法:
[root@client ~]# kubectl explain pods.spec.containers.livenessProbe.httpGet
KIND: Pod
VERSION: v1
RESOURCE: httpGet <Object>
DESCRIPTION:
HTTPGet specifies the http request to perform.
HTTPGetAction describes an action based on HTTP Get requests.
FIELDS:
host <string>
Host name to connect to, defaults to the pod IP. You probably want to set
"Host" in httpHeaders instead.
httpHeaders <[]Object>
Custom headers to set in the request. HTTP allows repeated headers.
path <string>
Path to access on the HTTP server.
port <string> -required-
Name or number of the port to access on the container. Number must be in
the range 1 to 65535. Name must be an IANA_SVC_NAME.
scheme <string>
Scheme to use for connecting to the host. Defaults to HTTP.
2、示例yaml
其中,lifecycle中postStart中利用exec向容器中nginx的网页文件目录写入一个健康页面,用于探测,livenessProbe中的httpGet指定端口、协议、检查页面来检查刚定义的健康页面;
[root@client k8s_yaml]# cat httpget-liveness.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget
spec:
containers:
- name: nginx
image: nginx:1.12-alpine
ports:
- name: http
containerPort: 80
lifecycle:
postStart:
exec:
command: ['/bin/sh', '-c', 'echo healthy > /usr/share/nginx/html/healthy']
livenessProbe:
httpGet:
path: /healthy
port: http
scheme: HTTP
# 刚运行后正常
[root@client k8s_yaml]# kubectl describe pods/liveness-httpget
3、测试
# 连入容器,删除健康页面
[root@client k8s_yaml]# kubectl exec liveness-httpget rm /usr/share/nginx/html/healthy
# 再次查看状态,从事件中可以看出探测失败,进行重启
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 9m19s default-scheduler Successfully assigned default/liveness-httpget to node2
Normal Pulling 9m18s kubelet, node2 pulling image "nginx:1.12-alpine"
Normal Pulled 8m20s kubelet, node2 Successfully pulled image "nginx:1.12-alpine"
Normal Created 6s (x2 over 8m20s) kubelet, node2 Created container
Normal Started 6s (x2 over 8m20s) kubelet, node2 Started container
Warning Unhealthy 6s (x3 over 26s) kubelet, node2 Liveness probe failed: HTTP probe failed with statuscode: 404
Normal Killing 6s kubelet, node2 Killing container with id docker://nginx:Container failed liveness probe.. Container will be killed and recreated.
Normal Pulled 6s kubelet, node2 Container image "nginx:1.12-alpine" already present on machine
[root@client k8s_yaml]# kubectl describe pods/liveness-httpget
tcp探针
1、语法:
[root@client k8s_yaml]# kubectl explain pods.spec.containers.livenessProbe.tcpSocket
KIND: Pod
VERSION: v1
RESOURCE: tcpSocket <Object>
DESCRIPTION:
TCPSocket specifies an action involving a TCP port. TCP hooks not yet
supported
TCPSocketAction describes an action based on opening a socket
FIELDS:
host <string>
Optional: Host name to connect to, defaults to the pod IP.
port <string> -required-
Number or name of the port to access on the container. Number must be in
the range 1 to 65535. Name must be an IANA_SVC_NAME.
2、示例
[root@client k8s_yaml]# cat tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget
spec:
containers:
- name: nginx
image: nginx:1.12-alpine
ports:
- name: http
containerPort: 80
lifecycle:
postStart:
exec:
command: ['/bin/sh', '-c', 'echo healthy > /usr/share/nginx/html/healthy']
livenessProbe:
tcpSocket:
port: http
3、测试:创建pod后,连入容器,将80端口禁掉,然后查看pod状态即可
探测行为参数
常用属性值:第一次探测延时、超时时间、多少次探测失败认为失败等;
默认参数:
Liveness: http-get http://:http/healthy delay=0s timeout=1s period=10s #success=1 #failure=3
查看pod信息时,定义了livenessprobe,会有默认的相关参数
官方文档说明:可自定义覆盖默认属性值
[root@master ~]# kubectl explain pods.spec.containers.livenessProbe.
FIELDS:
exec <Object>
One and only one of the following should be specified. Exec specifies the
action to take.
failureThreshold <integer>
Minimum consecutive failures for the probe to be considered failed after
having succeeded. Defaults to 3. Minimum value is 1.
httpGet <Object>
HTTPGet specifies the http request to perform.
initialDelaySeconds <integer>
Number of seconds after the container has started before liveness probes
are initiated. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
periodSeconds <integer>
How often (in seconds) to perform the probe. Default to 10 seconds. Minimum
value is 1.
successThreshold <integer>
Minimum consecutive successes for the probe to be considered successful
after having failed. Defaults to 1. Must be 1 for liveness. Minimum value
is 1.
tcpSocket <Object>
TCPSocket specifies an action involving a TCP port. TCP hooks not yet
supported
timeoutSeconds <integer>
Number of seconds after which the probe times out. Defaults to 1 second.
Minimum value is 1. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
pod就绪性探测
存活性探测只能判断容器正常存活与否,但容器正常不代表其中进程提供的服务正常,可以提供对外服务,因为需要有就绪性探测;生产中一般需要定义合理的就绪性探测,不仅可以探测定义了就绪性探测的pod本身,其依赖的其他pod也都可以通过就绪性探测探测;
和livenessProbe一样,探测方法有三种:tcpsocket、httpget、exec,以及可自定义的一些参数值
语法:
[root@master ~]# kubectl explain pods.spec.containers.readinessProbe
可以探测的方面有:页面是否准备,数据是否加载,某依赖pod是否可访问
资源需求与资源限制
资源需求:
分配pod时,其包含容器所需的最小资源量,(cpu和内存),必须找到满足这个下限的节点,pod才能分配成功,cpu可压缩,内存不可压缩,pod的资源需求实际作用实体是docker容器
资源限制:
pod中容器在运行中,可以申请使用的最大的资源量,即上限
资源单位:
- cpu:毫核,1000毫核为1个虚拟cpu(虚拟机vcpu)或一个物理机核的超线程(一个逻辑cpu)如:500m为半个cpu
- 内存:M K G
资源需求
1、语法:
[root@master ~]# kubectl explain pods.spec.containers.resources
KIND: Pod
VERSION: v1
RESOURCE: resources <Object>
DESCRIPTION:
Compute Resources required by this container. Cannot be updated. More info:
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
ResourceRequirements describes the compute resource requirements.
FIELDS:
limits <map[string]string>
Limits describes the maximum amount of compute resources allowed. More
info:
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
requests <map[string]string>
Requests describes the minimum amount of compute resources required. If
Requests is omitted for a container, it defaults to Limits if that is
explicitly specified, otherwise to an implementation-defined value. More
info:
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
2、示例:
该pod在调度时,schduler组件在选择node节点调度时,低于该requests的节点会被过滤掉;pod被调度节点后,节点会为其预留其request中定义的内存量,(因为内存不可压缩)但cpu过度压缩可能会导致pod几乎分不到cpu时间而异常;
spec:
containers:
- name: busybox
image: busybox
args: ['/bin/sh', '-c', 'touch /tmp/yes; sleep 30 ;rm -rf /tmp/yes']
livenessProbe:
exec:
command: ['test', '-e', '/tmp/yes']
resources:
requests:
cpu: "500m"
memory: "64Mi"
资源限制
**资源需求定义了pod运行的最小资源需求量,资源限制则定义了其运行中能够申请使用的最大资源量。**尤其可以避免容器中bug导致的不断占用cpu和内存资源,影响其他容器的现象;
某节点所有运行pod的limit之和可以超过节点的总资源,即允许资源超配,分配pod时只看requests下限,不看limit上限;k8s确保pod的所需cpu的下限资源,但再多的就看节点空余,以及其他pod对资源的占用能力而定;
1、语法:
[root@master ~]# kubectl explain pods.spec.containers.resources.limits
KIND: Pod
VERSION: v1
FIELD: limits <map[string]string>
...
2、示例:
[root@client k8s_yaml]# cat pod-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-limit
spec:
containers:
- name: memleak-pod
image: saadali/simmemlead
resources:
requests:
memory: "64Mi"
cpu: "1"
limits:
memory: "64Mi"
cpu: "1"
容器可见资源
在容器中可见到的资源其实是所在节点的资源量,示例如下:容器中看到的内存总量和节点的内存总量一致;可能带来的问题:
- pod中运行的java应用,未指定-Xmx指定确定的内存总量时,默认申请可见内存的30%,即节点的30%,显然有可能会超过limit限制而被OOMkilled
- pod中运行的nginx应用,worker_processer配置为auto,那么即可见所有cpu数,即主机的cpu核数个的工作线程,而容器限制的cpu一般小于节点cpu总数,则会产生大量上下文切换,消耗更多资源;
- 解决方法:通过downward api将limits的定义上限暴露给容器,使得容器只看到limit限制的资源量,而非节点的;
[root@client k8s_yaml]# kubectl exec pod-with-label -- cat /proc/meminfo |grep -i memtotal
MemTotal: 997980 kB
[root@client k8s_yaml]# free
total used free shared buff/cache available
Mem: 997980 145180 504692 7840 348108 661876
pod服务质量QOS
节点上所有pod的limit之和可以大于节点资源总量,意味着:所有pod满载运行时,将有pod会被杀死,那么pod被杀的优先级由pod的(quality of service)决定;k8s给pod定义了三种级别的qos:由上到下,重要性依次降低
- guaranteed:pod中所有容器都定义了相同值的requests和limits
- burstable:至少一个容器定义了request和limits值,但非全部
- besteffort:没有容器定义了requests和limits值,(出现资源紧张时会被最先杀死)
小结:
- pod就是一组联系紧密的容器,共享network、uts、ipc和存储卷,通过pause容器结合一起
- 分布式系统pod总容器组织方式:边车、本地代理、适配器
- k8s一切皆资源,基本都支持增删改查,支持陈述式命令、陈述式配置文件、声明式配置文件
- pod中容器常见的定制为暴露端口,传递环境变量,挂载卷
- 标签和注解都为键值对数据,用于描述容器的元数据信息,标签可以被标签选择器选择过滤各种资源对象
- pod启动与停止过程
- 存活和就绪性探测用于判定容器的状态
- 资源limit和requests用于定义容器运行所需资源的上下限