Testops之路6.Kubernetes之Pod

先来一起回忆一下上节课内容,k8s的几个组成部分:

Testops之路6.Kubernetes之Pod_第1张图片
image

研发采用声明式定义自己的应用:

Testops之路6.Kubernetes之Pod_第2张图片
image

应用运行在k8s集群上的全景图:

Testops之路6.Kubernetes之Pod_第3张图片
image

什么是pod

Pod,是 Kubernetes 项目中最小的 API 对象。如果换一个更专业的说法,我们可以这样描述:Pod,是 Kubernetes 项目的原子调度单位。

Testops之路6.Kubernetes之Pod_第4张图片
image

Kubernetes 项目中的最小编排单位是Pod,而不是容器。

Pod 扮演的是传统部署环境里“虚拟机”的角色。

而如果你能把 Pod 看成传统环境里的“机器”、把容器看作是运行在这个“机器”里的“用户程序”,那么很多关于 Pod 对象的设计就非常容易理解了。

比如,凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的。

Testops之路6.Kubernetes之Pod_第5张图片
image

这些属性的共同特征是,它们描述的是“机器”这个整体,而不是里面运行的“程序”。比如,配置这个“机器”的网卡(即:Pod 的网络定义)。

Testops之路6.Kubernetes之Pod_第6张图片
image

配置这个“机器”的磁盘(即:Pod 的存储定义),以及这台“机器”运行在哪个服务器之上(即:Pod 的调度)。

Testops之路6.Kubernetes之Pod_第7张图片
image

当容器间存在超紧密协作时,我们可以称为“超亲密关系”。这些具有“超亲密关系”容器的典型特征包括但不限于:互相之间会发生直接的文件交换、使用 localhost 或者 Socket 文件进行本地通信、会发生非常频繁的远程调用等等。

这也就意味着,并不是所有有“关系”的容器都属于同一个 Pod。比如,Backend 后端容器和 Fronted 前端容器 虽然会发生访问关系,但并没有必要、也不应该部署在同一台机器上,它们更适合做成两个 Pod分开部署。

那什么时候定义这种“超亲密关系“呢?

比较典型的例子——容器的日志收集,。

比如,我现在有一个应用,需要不断地把日志文件输出到容器的 /var/log 目录中。

这时,我就可以把一个 Pod 里的 Volume 挂载到应用容器的 /var/log 目录上。

实际上,这个所谓的“组合”操作,正是容器设计模式里最常用的一种模式,它叫:边车模式(sidecar)

我们在这个 Pod 里同时运行一个 sidecar 容器,它也声明挂载同一个 Volume 到自己的 /var/log 目录上。这样,接下来 sidecar 容器就只需要做一件事儿,那就是不断地从自己的 /var/log 目录里读取日志文件,转发到 MongoDB 或者 Elasticsearch 中存储起来。这样,一个最基本的日志收集工作就完成了。

Infra容器

Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume。

在 Kubernetes 项目里,Pod 的实现需要使用一个中间容器,这个容器叫作 Infra 容器。在这个 Pod 中,Infra 容器永远都是第一个被创建的容器,而其他用户定义的容器,则通过 Join Network Namespace 的方式,与 Infra 容器关联在一起。这样的组织关系,可以用下面这样一个示意图来表达:

Testops之路6.Kubernetes之Pod_第8张图片
image

创建一个Pod

配置kube_config

联系tower配置测试环境kube_config

通过kubectl创建一个namespace

kubectl create ns testops

通过kubectl创建一个pod

apiVersion: v1             
kind: Pod
metadata:
  name: kubia-manual  
  namespace: testops
spec:
  containers:
  - image: luksa/kubia      
    name: kubia             
    ports:
    - containerPort: 8080   
      protocol: TCP
kubectl create -f kubia-manual.yaml

Pod的关键字段

Kubernetes 项目中对 Container 的定义,和 Docker 相比并没有什么太大区别。Image(镜像)、Command(启动命令)、workingDir(容器的工作目录)、Ports(容器要开发的端口),以及 volumeMounts(容器要挂载的 Volume)都是构成 Kubernetes 项目中 Container 的主要字段。

看个例子:

Testops之路6.Kubernetes之Pod_第9张图片
image

Testops之路6.Kubernetes之Pod_第10张图片
image

1、这个YAML描述符中使用的Kubernetes API版本。
2、Kubernetes对象/资源的类型。
3、Pod元数据(名称、标签、注释等)。
4、Pod规格/内容(Pod容器、卷等列表)。
5、Pod和其容器的详细情况。

接下来,介绍 Pod 中几个重要字段的含义和用法。

Label

是一个供用户将 Pod 与 Node 进行绑定的字段

Testops之路6.Kubernetes之Pod_第11张图片
image

通常,我们微服务架构下中会有许多个pod,那么如何给这些pod分类呢,这里就要用到 Label 这个概念。

Testops之路6.Kubernetes之Pod_第12张图片
image
kubectl get pods -n {namespaces} -a --show-labels=true
Testops之路6.Kubernetes之Pod_第13张图片
image

NodeSelector

NodeSelector:是一个供用户将 Pod 与 Node 进行绑定的字段,用法如下所示:

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

这样的一个配置,意味着这个 Pod 永远只能运行在携带了“disktype: ssd”标签(Label)的节点上;否则,它将调度失败。

HostAliases

定义了 Pod 的 hosts 文件(比如 /etc/hosts)里的内容,用法如下:

apiVersion: v1
kind: Pod
...
spec:
  hostAliases:
  - ip: "10.1.2.3"
    hostnames:
    - "foo.remote"
    - "bar.remote"
...

在这个 Pod 的 YAML 文件中,我设置了一组 IP 和 hostname 的数据。这样,这个 Pod 启动后,/etc/hosts 文件的内容将如下所示:

cat /etc/hosts

#Kubernetes-managed hosts file.
127.0.0.1 localhost
...
10.244.135.10 hostaliases-pod
10.1.2.3 foo.remote
10.1.2.3 bar.remote

ImagePullPolicy

它定义了镜像拉取的策略。而它之所以是一个 Container 级别的属性,是因为容器镜像本来就是 Container 定义中的一部分。

ImagePullPolicy 的值默认是 Always,即每次创建 Pod 都重新拉取一次镜像。另外,当容器的镜像是类似于 nginx 或者 nginx:latest 这样的名字时,ImagePullPolicy 也会被认为 Always。

Lifecycle

它定义的是 Container Lifecycle Hooks。顾名思义,Container Lifecycle Hooks 的作用,是在容器状态发生变化时触发一系列“钩子”。我们来看这样一个例子:

Pending 这个状态意味着,Pod 的 YAML 文件已经提交给了 Kubernetes,API 对象已经被创建并保存在 Etcd 当中。但是,这个 Pod 里有些容器因为某种原因而不能被顺利创建。比如,调度不成功。

Running 这个状态下,Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都已经创建成功,并且至少有一个正在运行中。

Succeeded 这个状态意味着,Pod 里的所有容器都正常运行完毕,并且已经退出了。这种情况在运行一次性任务时最为常见。

Failed 这个状态下,Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出。这个状态的出现,意味着你得想办法 Debug 这个容器的应用,比如查看 Pod 的 Events 和日志。

Unknown 这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。

除了上面的字段,Pod还有一组Condition,它们主要用于描述造成当前 Status 的具体原因是什么。

Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True

作业

查看Pods其他字段

1、下载k8s源码

mkdir -p $GOPATH/src/k8s.io

2、进入目录$GOPATH/src/k8s.io,执行以下命令即可开始下载:

git clone https://github.com/kubernetes/kubernetes -b release-1.13

3、下载完毕后,k8s.io目录下出现一个名为kubernetes的文件夹。

cat $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/api/core/v1/types.go

观察pod

使用kubectl命令,观察你目前用的测试环境某个服务的pod信息

kubectl命令表

http://docs.kubernetes.org.cn/683.html

Pod其他属性

# yaml格式的pod定义文件完整内容:
apiVersion: v1          #必选,版本号,例如v1
kind: Pod             #必选,Pod
metadata:             #必选,元数据
  name: string          #必选,Pod名称
  namespace: string       #必选,Pod所属的命名空间
  labels:             #自定义标签
    - name: string       #自定义标签名字
  annotations:          #自定义注释列表
    - name: string
spec:                #必选,Pod中容器的详细定义
  containers:           #必选,Pod中容器列表
  - name: string        #必选,容器名称
    image: string       #必选,容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent]  #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]       #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]         #容器的启动命令参数列表
    workingDir: string      #容器的工作目录
    volumeMounts:         #挂载到容器内部的存储卷配置
    - name: string         #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string     #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean     #是否为只读模式
    ports:              #需要暴露的端口库号列表
    - name: string         #端口号名称
      containerPort: int    #容器需要监听的端口号
      hostPort: int        #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string      #端口协议,支持TCP和UDP,默认TCP
    env:              #容器运行前需设置的环境变量列表
    - name: string        #环境变量名称
      value: string       #环境变量的值
    resources:          #资源限制和请求的设置
      limits:           #资源限制的设置
        cpu: string       #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string      #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests:         #资源请求的设置
        cpu: string       #Cpu请求,容器启动的初始可用数量
        memory: string      #内存清楚,容器启动的初始可用数量
    livenessProbe:        #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:             #对Pod容器内检查方式设置为exec方式
        command: [string]   #exec方式需要制定的命令或脚本
      httpGet:            #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:            #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0   #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0      #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0       #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged: false
    restartPolicy: [Always | Never | OnFailure] #Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject     #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:         #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork: false        #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:              #在该pod上定义共享存储卷列表
    - name: string          #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}          #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string        #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string        #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:             #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:          #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string

你可能感兴趣的:(Testops之路6.Kubernetes之Pod)