在 Kubernetes 中,一个重要的概念就是 Pod(豆英),Kubernetes 并不是直接管理容器的,他的最小管理单元叫做 Pod。
        在 Docker 的应用中,我们把一个应用程序封装在一个镜像中,之后启动这个镜像并映射个宿主机端口号,就能访问这个应用。既然单个容器就可以部署这个应用,为什么 Kubernetes不直接管理容器,而是要设计一个 Pod 呢?

一、什么是 Pod

        Pod 是一个或多个容器的组合。这些容器共享存储、网络和命名空间,以及运行规范。在 Pod中,所有容器都被统一安排和调度,并运行在共享的上下文中。对于具体应用而言,Pod 是它们的逻辑主机,Pod 包含业务相关的多个应用容器。所以,Pod 是一组具有共享命名空间、IP 地址和端口的容器的集合。

备注:
共享上下文是一种基于线程的内存位置

1.从使用的角度来看

        在实际的使用时,单个容器是无法单独来支撑我们的应用的,往往需要很多微服务才能组成一个系统,并且还会存在A服务依赖B服务,B服务需要和C服务共用某个目录。另外,在使用裸容器时,很难实现对容器内进行健康检査以及横向扩容等操作,而 Pod 可以轻松解决这些问题。

2.从Kubernetes 的角度来看

        Docker 只是容器 Runtime(运行时)的一种们还有很多容器 Runtime,比如 Rkt、CRI-0等,而 Kubernetes 作为目前最流行的容器编排工具,需要支持各个 Runtime 并且不依赖于底层Runtime 的实现技术,于是就抽象出了 Pod 这个概念,用于管理多个紧密相连的符合 CRI 标准的容器。

        Pod 可以简单的理解为一组、一个或多个容器,每个 Pod 还包含一个 Pause 容器,Pause 容器是 Pod 的父容器,主要负责僵尸进程的回收管理。同时,通过 Pause 容器可以使同一个 Pod里面的不同容器共享存储、网络、PID、IPC等,容器之间可以使用 Localhost:Port 的方式相互访问,可以使用 volume 实现数据共享。根据 Docker 的构造,Pod 可以被创建为一组具有共享命名空卷、IP 地址和端口的容器。

Pod 有两个必须知道的特点:
        网络:每一个 Pod 都会被指派一个唯一的 Ip 地址,在 Pod 中的每一个容器共享网络命名空间,包括 p 地址和网络端口。在同一个 Pod 中的容器可以同 1ocahost 进行互相通信。当 Pod中的容器需要与 Pod 外的实体进行通信时,则需要通过端口等共享的网络资源。
        存储:Pod 能够被指定共享存储卷的集合,在 Pod 中所有的容器能够访问共享存储卷,允许这些容器共享数据。存储卷也允许在一个 Pod 持久化数据,以防止其中的容器需要被重启。

3.Pod的状态

(1)kubectl 命令创建 pod
kubectl run nginx --image=nginx:1.7.9 --labels="app=nginx'
(2)查看 pod
kubectlget pods -n default
NAME        READY        STATUS        RESTARTS        AGE
nginx        1/1        Running        0                78s
(3)显示 Pod 的更多信息
kubectl get pod nginx  -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP      NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          54s   10.244.219.65   node02   <none>           <none>
(4)查看 pod日志
curl 10.244.58.195
kubectl logs nginx
(5)以 yaml格式显示 Pod 详细信息
kubectl get pod nginx-o yaml
(6)显示资源的详细描述信息
kubectl describe pod nginx

备注:

  • kubectl get:常用于査看同一资源类型的一个或多个资源对象,可以使用-0 参数自定义输出格式。
  • kubectl describe:侧重于描述指定资源的各方面的详细信息,不仅会返回节点信息,还会返回在其上运行的 Pod 的摘要、节点事件等信息。
(7)在 Pod 的容器中执行命令
kubectl exec nginx -c nginx-- date

备注:
-c:指定 Pod 中容器的名字

(8)登录到 Pod 中的容器中
kubectl exec it nginx-c nginx -- bash

备注:
kubectl exec it nginx-- bash
如果登录的时候不指定容器,就登录到Pod 中的第一个容器中。

(9)在线编辑运行中的资源对象
kubectl edit pod nginx
(10)将 pod 的端口映射到宿主机
kubectl port-forward --address 0.0.0.0 pod/nginx 8080:80
Forwarding from 0.0.0.0:8080->80

其他主机访问测试:
curl 192.168.10.101:8080
注意:
此命令会在前台运行,此时就可以在其他客户端用该 k8s 主机的 IP 地址和 8080 的端口号进行访问了,Ctrl+c停止,但停止后就没有这个映射了。

(11)在宿主机和 Pod 的容器之间拷贝文件
kubectl cp nginx:etc/fstab /opt/aaa.txt
kubectl cp /opt/aaa.txt nginx:etc/bbb.txt
(12)Pod 的状态
kubectlget pods -n default
NAME    READY    STATUS    RESTARTS    AGE
nginx    1/1    Running     0         29m

可以看到此时的 Pod 的状态是 Running,Pod 的状态不仅仅只有 Running,常见的其他状态如表1 所示:

(13)删除 Pod
kubectl delete pod nginx

二、Pod 探针

        在生产环境中,进程正常启动并不代表应用能正常处理请求,所以合理的设计应用的健康检查尤其重要。在使用裸机或裸容器部署时,一般很难对应用做很完善的健康检査,而 Pod 提供的探针可以很方便的用来检测容器的应用是否正常。目前探针有3种检测方式,可以根据不同的场景选择合适的健康检查方式。检查方式如表2所示。

        上述的检查方式可以被周期性的执行,每次检查容器后可能得到的容器状态如表3所示。

        Pod 探针有三类,分别是:1ivenessProbe(存活探针)、readinessProbe(就绪探针)、startupProbe(启动探针)。

  • livenessProbe (存活探针):判断容器是否正常运行,如果失败则杀掉容器(不是 pod),再根据重启策略决定是否重启容器
  • readinessProbe(就绪探针):判断容器是否能够进入ready 状态,探针失败则进入noready 状态,并从service的endpoints 中剔除此容器
  • startupProbe(启动探针): 判断容器内的应用是否启动成功,在 success 状态前,其它探针都处于无效状态

三、Pod镜像拉取策略和重启策略

        在发布应用或者更改控制器配置时,会触发Pod 的滚动更新,此时针对容器的镜像有不同的拉取方式。如表 4所示。

指定拉取策略:

kubectl run nginx --image=nginx:1.7.9--labels="app=nginx" --image-pull-policy=Never

        Pod 进行部署或者运行时,难免会出现故障,对于故障。,Pod也有不同的处理方式,如表5 所示。

指定重启策略:

kubectl delete pod nginx
kubectl run nginx --image=nginx:1.7.9 --labels="app=nginx" --restart=OnFailure

四、创建一个简单的 Pod

1.编写一个简单的 Pod

vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
 name: nginx
 labels:
  name:nginx
spec:
 containers:
 -name:nginx
 image: nginx:1.7.9
 ports :
 -containerPort:80

2.编写 Pod 配置文件 frontend-localredis-pod.yaml

cat<<E0F>frontend-localredis-pod.yam1
apiVersion: v1
kind: Pod
metadata:
 name: redis-php
 labels :
  name: redis-php
spec:
 containers:
 -name:frontend
 image: kubeguide/guestbook-php-frontend:localredis
 imagePullPolicy: IfNotPresent
 livenessProbe:
  tcpSocket:
     port:80
  initialDelaySeconds:1
  periodseconds:3
  timeoutseconds:1
ports:
 - containerPort:80
- name: redis
 image:kubeguide/redis-masterimagePullPolicy:IfNotPresent
 ports:
- containerPort:6379
  restartPolicy: OnFailure
EOF

备注:

3.Pod文件语法

(1)Pod 文件的一级属性

一级属性主要包含5部分:

  • apiversion<string〉版本,由 kubernetes 内部定义,版本号必须可以用 kubectlapi-versions 查询到
  • kind <string〉类型,由 kubernetes 内部定义,版本号必须可以用 kubect1api-resources 查询到
  • metadata<0bject>元数据,主要是资源标识和说明,常用的有 name、namespace、labels等
  • spec<Object〉描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述
  • status <0bject>状态信息,里面的内容不需要定义,由kubernetes 自动生成
(2)spec(规格)属性

在一级属性中,spec是研究的重点,它的常见子属性有:

  • containers<[l0bject>容器列表,用于定义容器的详细信息
  • nodeName<string>根据 nodeName 的值将 pod 调度到指定的 Node 节点上
  • nodeselector <map[]>根据 Nodeselector 中定义的信息选择将该 Pod 调度到包含这些label的Node 上
  • hostNetwork<boolean>是否使用主机网络模式,默认为 false,如果设置为 true,表示使用宿主机网络
  • volumes<[]object>存储卷,用于定义 Pod 上面挂在的存储信息
  • restartPolicy<string〉重启策略,表示 Pod 在遇到故障的时候的处理策略
(3)通过 kubectl explain 命令来查看每种资源的可配置项
kubectl explain pod
kubectl explain deployment
kubectl explain service
kubectl explain pod.metadata
kubectl explain pod.spec.containers

备注:
查看某种资源可以配置的一级属性
# kubectl explain 资源类型
查看属性的子属性
# kubectl explain 资源类型.属性

4.运行 kubectl create 命令创建此 Pod

kubectl create -f frontend-localredis-pod.yaml

5.查看已经创建的 Pod

kubectl get pods
NAME    READY    STATUS    RESTARTS    AGE
redis-php    2/2  Running    0         119s

6.查看 pod 详细创建信息

kubectl describe pod redis-php

7.删除 pod

kubectl delete -f frontend-localredis-pod.yaml

五、Pod 的基本用法

1.编写 pod 文件,将两个容器放在同一个 pod 中

2.部署 nginx的 pod 文件

kubectl apply -f nginx-php.yaml
kubectl get pods
NAME    READY    STATUS    RESTARTS    AGE
nginx-php    2/2    Running   0       28s

备注:
此时可以看到 pod 中有两个容器处于 running 状态中

3.查看 pod 的详细信息

kubectl describe pod nginx-php

4.暴露端口

kubectl expose pod nginx-php --port=8080 --target-port=80 --type=NodePort --name=nginx-php

5.查看端口映射

kubectl get pod,svc nginx-php -o wide

6.测试访问

用外部主机,访问 master 的ip 地址:映射的端口

http://192.168.10.101:32598/

7.删除pod

kubectl delete -f nginx-php.yaml

六、静态 pod

        静态 Pod 是由 kubelet 进行管理的仅存在于各个 Node 上的 Pod。他们不能通过 API Server进行管理,无法于 Replicationcontroller、Deployment 或者 Daemonset 进行关联,并且kubelet 无法对他们进行健康检査。静态 Pod 总是由 kubelet 创建的,并且总在 kubelet 所在的 Node 上运行。

1.编写 yamal 文件

cat<<E0F>/etc/kubernetes/manifests/nginx-pod.yaml
apiVersion:v1
kind: Pod
metadata:
  name: static-web
  labels:
    name: static-web
spec:
  containers:
  -name:static-web
  image: nginx:1.7.9
  ports:
 -name:nginx
    containerPort:80
EOF

2.不需执行部署命令,过一会,查看 pod

kubectl get pod 
NAME        READY    STATUS        RESTARTS    AGE
nginx-php    2/2        Running    4(18m ago)   20m
static-web-k8s-master01    1/1     Running  0   20s

3.删除静态 pod 的方法

rm -rf /etc/kubernetes/manifests/nginx-pod.yam1

备注:
不能用如下语句删除
kubectl delete pod static-web-k8s-master01

这样删除,会让 pod 处于 pending 状态,但无法删除

七、Pod 启动阶段(相位 phase)

Pod 创建完之后,一直到持久运行起来,中间有很多步骤,也就有很多出错的可能,因此会有很多不同的状态

1.pod 的启动过程包含的步骤

(1)调度到某台 node 上。kubernetes 根据一定的优先级算法选择一台 node 节点将其作为Pod 运行的 node
(2)拉取镜像
(3)挂载存储配置等
(4)运行起来。如果有健康检查,会根据检查的结果来设置其状态

2.phase 的可能状态

(1)Pending:表示APIServer 创建了 Pod 资源对象并已经存入了 etcd 中,但是它并未被调度完成(比如还没有调度到某台 node 上),或者仍然处于从仓库下载镜像的过程中
(2)Running:Pod 已经被调度到某节点之上,并且 Pod 中所有容器都已经被 kubelet 创建。至少有一个容器正在运行,或者正处于启动或者重启状态(也就是说 Running 状态下的 Pod 不一定能被正常访问)
(3)succeeded:有些 pod 不是长久运行的,比如 job、cronjob,一段时间后 Pod 中的所有容器都被成功终止,并且不会再重启。需要反馈任务执行的结果

(4)Failed:Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止,比如command 写的有问题
(5)Unknown:表示无法读取 Pod 状态,通常是 kube-controller-manager 无法与 Pod 通信

八、故障排除步骤

査看 Pod 事件

kubectl describe TYPE NAME PREFIX

查看 Pod 日志(Failed 状态下)

kubectl logs <POD NAME>[-c Container NAME]

进入 Pod(状态为running,但是服务没有提供)

kubectl exec -it <POD NAME> bash

查看集群信息

kubectl get nodes

发现集群状态正常

kubectl cluster-info

查看 kubelet 日志发现

journalctl -xefu kubelet

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部