深入理解Pod对象(上)

377 阅读3分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

深入理解Pod对象

Pod是最小的部署单元,也是后面经常配置的地方,本章节带你熟悉Pod中常见资源配置及参数。

也就是YAML这部分:

  ...
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: lizhenliang/java-demo:latest
        imagePullPolicy: Always
        name: java 

Pod介绍

  • 最小部署单元
  • 一组容器的集合
  • 一个Pod中的容器共享网络命名空间
  • Pod是短暂的

Pod存在的意义

Pod为亲密性应用而存在。

亲密性应用场景:

  • 两个应用之间发生文件交互
  • 两个应用需要通过127.0.0.1或者socket通信
  • 两个应用需要发生频繁的调用

Pod实现机制与设计模式

Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?

众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。

具体分为两个部分:网络和存储

  • 共享网络

kubernetes的解法是这样的:会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址。

  • 共享存储

比如有两个容器,一个是nginx,另一个是普通的容器,普通容器要想访问nginx里的文件,就需要nginx容器将共享目录通过volume挂载出来,然后让普通容器挂载的这个volume,最后大家看到这个共享目录的内容一样。

例如:

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: write
    image: centos
    command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
    volumeMounts:
      - name: data
        mountPath: /data

  - name: read
    image: centos
    command: ["bash","-c","tail -f /data/hello"]
    volumeMounts:
      - name: data
        mountPath: /data
  
  volumes:
  - name: data
    emptyDir: {}

上述示例中有两个容器,write容器负责提供数据,read消费数据,通过数据卷将写入数据的目录和读取数据的目录都放到了该卷中,这样每个容器都能看到该目录。

验证:

kubectl apply -f pod.yaml
kubectl logs my-pod -c read -f

在Pod中容器分为以下几个类型:

  • Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见
  • InitContainers:初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作
  • Containers:业务容器,具体跑应用程序的镜像

镜像拉取策略

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: java
      image: lizhenliang/java-demo
      imagePullPolicy: IfNotPresent

imagePullPolicy 字段有三个可选值:

  • IfNotPresent:默认值,镜像在宿主机上不存在时才拉取
  • Always:每次创建 Pod 都会重新拉取一次镜像
  • Never: Pod 永远不会主动拉取这个镜像

如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  imagePullSecrets:
    - name: myregistrykey
  containers:
    - name: java
      image: lizhenliang/java-demo
      imagePullPolicy: IfNotPresent

上述中名为 myregistrykey 的secret是由kubectl create secret docker-registry命令创建:

 kubectl create secret docker-registry myregistrykey --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@harbor.com --docker-server=192.168.31.70

--docker-server: 指定docke仓库地址 --docker-username: 指定docker仓库账号 --docker-password: 指定docker仓库密码 --docker-email: 指定邮件地址(选填)