Pod中如何管理多个容器

Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。

注意在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件,如下图所示:

kubernetes-深入理解pod对象(七)

 

Pod中可以共享两种资源:网络和存储。
  •  网络:每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。
  • 存储:可以Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。
Pod容器分类

•Infrastructure Container:基础容器,维护整个Pod网络空间
•InitContainers:初始化容器,先于业务容器开始执行
•Containers:业务容器,并行启动

kubernetes中pod创建流程

Pod是Kubernetes中最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。例如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我们可以创建包含三个container的pod。

kubernetes-深入理解pod对象(七)

具体的创建步骤包括:
(1)客户端提交创建请求,可以通过API Server的Restful API,也可以使用kubectl命令行工具。支持的数据类型包括JSON和YAML。
(2)API Server处理用户请求,存储Pod数据到etcd。
(3)调度器通过API Server查看未绑定的Pod。尝试为Pod分配主机。
(4)过滤主机 (调度预选):调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
(5)主机打分(调度优选):对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
(6)选择主机:选择打分最高的主机,进行binding操作,结果存储到etcd中。
(7)kubelet根据调度结果执行Pod创建操作: 绑定成功后,scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步boundpod信息,一旦发现应该在该工作节点上运行的boundpod对象没有更新,则调用Docker API创建并启动pod内的容器。

调度约束

https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

scheduler组件

k8s调度器会将pod调度到资源满足要求并且评分最高的node上。

我们可以使用多种规则比如:
1.设置cpu、内存的使用要求
2.增加node的label,并通过pod.Spec.NodeSelector进行强匹配;
3.直接设置pod的nodeName,跳过调度直接下发。
k8s 1.2加入了一个实验性的功能:affinity。意为亲和性。这个特性的设计初衷是为了替代nodeSelector,并扩展更强大的调度策略。

调度器的工作机制是这样的

一、预备工作
1、缓存所有的node节点,记录他们的规格:cpu、内存、磁盘空间、gpu显卡数等;
2、缓存所有运行中的pod,按照pod所在的node进行区分,统计每个node上的pod request了多少资源。request是pod的QoS配置。
3、list & watch pod资源,当检查到有新的Pending状态的pod出现,就将它加入到调度队列中。
4、调度器的worker组件从队列中取出pod进行调度。
二、调度过程
1、先将当前所有的node放入队列;
2、执行predicates算法,对队列中的node进行筛选。这里算法检查了一些pod运行的必要条件,包括port不冲突、cpu和内存资源QoS(如果有的话)必须满足、挂载volume(如果有的话)类型必须匹配、nodeSelector规则必须匹配、硬性的affinity规则(下文会提到)必须匹配、node的状态(condition)必须正常,taint_toleration硬规则(下文会提到)等等。
3、执行priorities算法,对队列中剩余的node进行评分,这里有许多评分项,各个项目有各自的权重:整体cpu,内存资源的平衡性、node上是否有存在要求的镜像、同rs的pod是否有调度、node affinity的软规则、taint_toleration软规则(下文会提到)等等。
4、最终评分最高的node会被选出。即代码中suggestedHost, err := sched.schedule(pod)一句(plugin/pkg/scheduler/scheduler.go)的返回值。
5、调度器执行assume方法,该方法在pod调度到node之前,就以“该pod运行在目标node上” 为场景更新调度器缓存中的node 信息,也即预备工作中的1、2两点。这么做是为了让pod在真正调度到node上时,调度器也可以同时做后续其他pod的调度工作。
6、调度器执行bind方法,该方法创建一个Binding资源,apiserver检查到创建该资源时,会主动更新pod的nodeName字段。完成调度

nodeSelector用于将Pod调度到匹配Label的Node上

将标签附加到node

[root@k8s-master1 ~]# kubectl label nodes 192.168.0.126 env_role=dev
node/192.168.0.126 labeled
[root@k8s-master1 ~]# kubectl label nodes 192.168.0.125 env_role=test
node/192.168.0.125 labeled
[root@k8s-master1 ~]# kubectl get nodes --show-labels
NAME            STATUS   ROLES    AGE    VERSION   LABELS
192.168.0.125   Ready    <none>   2d4h   v1.13.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=test,kubernetes.io/hostname=192.168.0.125
192.168.0.126   Ready    <none>   2d4h   v1.13.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/hostname=192.168.0.126

将nodeSelector字段添加到pod配置中

[root@k8s-master1 ~]# vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
labels:
app: nginx spec: containers:
- name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: env_role: dev [root@k8s-master1 ~]# kubectl create -f pod2.yaml pod/nginx created

查看pod

[root@k8s-master1 ~]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          115s
[root@k8s-master1 ~]# kubectl describe pod nginx
Name:               nginx
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               192.168.0.126/192.168.0.126
Start Time:         Fri, 21 Dec 2018 14:07:49 +0800
Labels:             <none>
Annotations:        <none>
Status:             Running
IP:                 172.17.92.2
Containers:
  nginx:
    Container ID:   docker://8c7e442cc83b6532b3bda707f389fa371861d173e9395149bbede9e166bf559c
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:1a0043cfb1987774c6981c41e49f758c58ace64c30e1c4ecff5cedff0b5c88da
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 21 Dec 2018 14:07:50 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-7vs6s (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-7vs6s:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-7vs6s
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  env_role=dev
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From                    Message
  ----    ------     ----   ----                    -------
  Normal  Scheduled  2m11s  default-scheduler       Successfully assigned default/nginx to 192.168.0.126
  Normal  Pulled     2m11s  kubelet, 192.168.0.126  Container image "nginx" already present on machine
  Normal  Created    2m10s  kubelet, 192.168.0.126  Created container
  Normal  Started    2m10s  kubelet, 192.168.0.126  Started container
View Code

相关文章: