kubernetes云原生纪元:深入pod(上)


pod 到底是什么?,为什么设计出pod? 直接用容器不是更简单吗?今天我们深入了解pod 的点点滴滴

设计思想

假设一个场景:很多情况下有很多服务很多应用,同时运行在一台机器上,但是每个容器只能运行一个服务,容器是单进程模式,一个容器跑多个应用违背了docker 的设计原则。一台机器有2.5G内存,三个服务等待调度,其中每个服务占用1G的内存,如果我们一个去调度是没问题的,调度完前两个,到第三个就发现内存不够了,也就是说在调度层面直接使用容器是有问题的。

我们知道Pod是kubernetes最小调度单位(原子单位),他的调度是按照整个pod的资源需求来做的,所以上面说的问题就迎刃而解了,但是pod 在kubernetes有更重要的作用。pod是逻辑的概念,在物理机器上他并不真实的存在,没有pod的边界,他真正处理的还是容器层面的隔离。

Pod 本质共享同一个namespace ,network namespace volume。是不是docker run --net=xxx --volumes-from=xxx…也是可以让一个容器共享同一个network volume,看似可以但是有一个潜在的问题,这种方式是对容器的启动顺序有要求的,这样多个容器就不是一个对等的关系,处理起来非常复杂。

这个时候就轮到pod登场他用到了一个中间容器Pause 容器不需要配置中声明,每个容器都会有,并且第一个启动的就是它,在配置文件启动的容器都是通过join-network跟pod容器关联在一起的,Pause 容器会不会占用内存,不用担心他是暂停状态的,不会占用我们的资源,镜像非常小一两百k,不会占用内存

  • Pod是最小调度单位
  • 本质还是容器的隔离
  • Pause 容器
pod的网络

在一个pod配置两容器,他们的网络IP地址一样都是共享一个IP,网络设备也是一样

kind: Pod 就是我们deployment 模版部分

Pod-network.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-network
spec:
  containers:
    - name: web
      image: hub.mooc.com/kubernetes/web:v1
      ports:
        - containerPort: 8080
      volumeMounts:
        - name: shared-volume
          mountPath: /shared-web
    - name: dubbo
      env:
        - name: DUBBO_PORT
          value: "20881"
      image: hub.mooc.com/kubernetes/dubbo:v1
      ports:
        - containerPort: 20881
          hostPort: 20881
          protocol: TCP

创建下

[root@master-001 ~]# kubectl create -f pod-network.yaml

来到运行节点查看下容器,有个pause 容器先启动它,在启动的我们服务 容器

image-20200127125807193

我们进入到容器内部dubbo访问web服务是相通的证明容器之间是共享网络的

image-20200127130153301

Pod-volume设计

一旦pod设置了数据卷,pod的容器都可以共同使用的,

当然在生产的时候完全没有必要一个pod 两个容器就算有也是两个两相同的服务,一个主力一个辅助,比如日志采集

pod-volume.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume
spec:
  containers: # 同样也是两个容器
  - name: web
    image: hub.mooc.com/kubernetes/web:v1
    ports:
    - containerPort: 8080
    volumeMounts: #把数据卷挂到容器里/shared-web目录
    - name: shared-volume
      mountPath: /shared-web
  - name: dubbo
    env:
    - name: DUBBO_PORT
      value: "20881"
    image: hub.mooc.com/kubernetes/dubbo:v1
    ports:
    - containerPort: 20881
      hostPort: 20881
      protocol: TCP
    volumeMounts: #把数据卷挂到容器里/shared-dubbo目录
    - name: shared-volume
      mountPath: /shared-dubbo
  volumes: # 数据卷
  - name: shared-volume
    hostPath: #主机目录
      path: /shared-volume-data

创建下

[root@master-001 ~]# kubectl create -f pod-volume.yaml

来到运行容器机器,进入dubbo容器里面,cd shared-dubbo目录创建一个文件abc

image-20200127141542157

然后 去web容器里面查看abc文件是否被共享

image-20200127141757045

Pod-host

而且这两个容器的host是一样的,也是由pod的创建的,必须由pod管理,自定义host文件的时候不能直接修改,我们必须保持当前pod 的容器的host文件一致

Pod 的定义host

hostAliases: #定义 当前容的host   我们对特定服务做一些修改的时候一定要在pod层面做不要再容器层面做
    - ip: "10.155.20.120"
      hostnames:
        - "web.mooc.com"

完整配置:

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume
spec:
  hostAliases: #定义 当前容的host   我们对特定服务做一些修改的时候一定要在pod层面做不要再容器层面做
    - ip: "10.155.20.120"
      hostnames:
        - "web.mooc.com"
  containers:
  - name: web
    image: hub.mooc.com/kubernetes/web:v1
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: shared-volume
      mountPath: /shared-web
  - name: dubbo
    env:
    - name: DUBBO_PORT
      value: "20881"
    image: hub.mooc.com/kubernetes/dubbo:v1
    ports:
    - containerPort: 20881
      hostPort: 20881
      protocol: TCP
    volumeMounts:
    - name: shared-volume
      mountPath: /shared-dubbo
  volumes:
  - name: shared-volume
    hostPath:
      path: /shared-volume-data

省去创建步骤…查看容器里面的host,已经被加入进去,而且两个服务的容器都有

image-20200127143237919

除里网络部分,所以的liunx namespace 也都是属于pod级别

比如

hostNetwork: true # 是否使用宿主机的网络
  hostPID: true # 是否使用宿主机的pid

都可以在pod级别定义,spec下配置。不要在容器层面去做,那样是错的

容器生命周期

在容器下配置

postStart:#在我们容器启动前执行一个命令

preStop:容器停止前要做的执行的命令

lifecycle:
        postStart:
          exec: #在我们容器启动前执行一个命令,比如下面,也是说容器执行ENTRYPOINT的同时会并行执行下面命令是同时执行
            command: ["/bin/sh","-c","echo web starting .... >/var/log/messages"]
        preStop: #容器停止前要做的执行的命令,并且是串行的,是在命令执行完给容器发射停止的信号,如果脚本执行的比较长他会有一个超时,自动跳过等待
        	exec:
            command: ["/bin/sh","-c","echo web stoping .... >/var/log/messages"]

完整配置如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume
spec:
  containers:
  - name: web
    image: hub.mooc.com/kubernetes/web:v1
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: shared-volume
      mountPath: /shared-web
    lifecycle:
        postStart:
          exec: #在我们容器启动前执行一个命令,比如下面,也是说执行ENTRYPOINT的同时会并行执行下面命令是同时执行
            command: ["/bin/sh","-c","echo web starting .... >/var/log/messages"]
        preStop: #停止前要做的执行的命令,并且是串行的,是在命令执行完给容器发射停止的信号,如果脚本执行的比较长他会有一个超时,自动跳过等待
          exec:
            command: ["/bin/sh","-c","echo web starting .... >/var/log/messages"]
  - name: dubbo
    env:
    - name: DUBBO_PORT
      value: "20881"
    image: hub.mooc.com/kubernetes/dubbo:v1
    ports:
    - containerPort: 20881
      hostPort: 20881
      protocol: TCP
    volumeMounts:
    - name: shared-volume
      mountPath: /shared-dubbo
  volumes:
  - name: shared-volume
    hostPath:
      path: /shared-volume-data

preStop是做容器的意外退出的

这里就不演示了。

pod的状态

pod的生命周期刚开始是处于Pending状态没有被调度最最开始的状态,过了Pending状态说明我们的容器被调度了找到合适的机器了这个时候处于containerCreating 创建容器状态,这个状态不会持续很久,过了这个状态容器进入Runing状态运行中。成功运行处于Succeeded成功运行状态,失败退出处于Failed状态,这两种状态只有在job 和createjob才达到这种状态,通过健康检查会处于Ready状态,一直没有通过健康检查CrashLoopBackOff等待状态,错误越多等待越久,处于这个状态就是我们服务启动失败的状态。Unknown未知状态apiServer 没有收到 pod 信息相关的汇报,kubelet 与apiServer中间的通讯一般有问题。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐