跳转至

17-k8sPOD入门-单master

Pod是什么

Pod是Kubernetes中的最小调度单元,k8s是通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定一个镜像,这样就可以用来运行具体的服务。一个Pod封装一个容器(也可以封装多个容器),Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

image-20220424102201137

Pod是需要调度到k8s集群的工作节点来运行的,具体调度到哪个节点,是根据scheduler调度器实现的。

白话解释: 可以把pod看成是一个“豌豆荚”,里面有很多“豆子”(容器)。一个豌豆荚里的豆子,它们吸收着共同的营养成分、肥料、水分等,Pod和容器的关系也是一样,Pod里面的容器共享pod的网络、存储等。

image-20220424104332939

pod相当于一个逻辑主机--比方说我们想要部署一个nginx应用,如果不用容器,我们可能会部署到物理机、虚拟机或者云主机上,那么出现k8s之后,我们就可以定义一个pod资源,在pod里定义一个nginx容器,所以pod充当的是一个逻辑主机的角色。

Pod的管理

image-20220424102256472

Pod中可以同时运行多个容器。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境,它们总是被同时调度,在一个Pod中同时运行多个容器是一种比较高级的用法,只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件。

一些Pod有init容器和应用容器。 在应用程序容器启动之前,运行初始化容器。

Pod的网络

Pod是有IP地址的,每个pod都被分配唯一的IP地址(IP地址是靠网络插件calico、flannel、weave等分配的),POD中的容器共享网络名称空间,包括IP地址和网络端口。 Pod内部的容器可以使用localhost相互通信。 Pod中的容器也可以通过网络插件calico与其他节点的Pod通信。

Pod的存储

创建Pod的时候可以指定挂载的存储卷。 POD中的所有容器都可以访问共享卷,允许这些容器共享数据。 Pod只要挂载持久化数据卷,Pod重启之后数据还是会存在的。

Pod创建流程

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

image-20220424103007319

创建pod流程:

image-20220424103029052

master节点:kubectl -> kube-api -> kubelet -> CRI容器环境初始化

第一步: 客户端提交创建Pod的请求,可以通过调用API Server的Rest API接口,也可以通过kubectl命令行工具。如kubectl apply -f filename.yaml(资源清单文件)

第二步: apiserver接收到pod创建请求后,会将yaml中的属性信息(metadata)写入etcd。

第三步: apiserver触发watch机制准备创建pod,信息转发给调度器scheduler,调度器使用调度算法选择node,调度器将node信息给apiserver,apiserver将绑定的node信息写入etcd

调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。

scheduler 查看 k8s api ,类似于通知机制。 首先判断:pod.spec.Node == null? 若为null,表示这个Pod请求是新来的,需要创建;因此先进行调度计算,找到最“闲”的node。 然后将信息在etcd数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点)

ps:同样上述操作的各种信息也要写到etcd数据库中中

第四步: apiserver又通过watch机制,调用kubelet,指定pod信息,调用Docker API创建并启动pod内的容器。

第五步: 创建完成之后反馈给kubelet, kubelet又将pod的状态信息给apiserver, apiserver又将pod的状态信息写入etcd。

Pod资源清单

编写技巧

通过kubectl explain 查看定义Pod资源包含哪些字段

[root@master1 ~]# kubectl explain pod
KIND:     Pod
VERSION:  v1
DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.
[Pod是可以在主机上运行的容器的集合。此资源是由客户端创建并安排到主机上。]

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
[APIVersion定义了对象,代表了一个版本。]
   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
[Kind是字符串类型的值,代表了要创建的资源。服务器可以从客户端提交的请求推断出这个资源。]
   metadata <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
[metadata是对象,定义元数据属性信息的]
   spec <Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
[spec制定了定义Pod的规格,里面包含容器的信息]
   status   <Object>
     Most recently observed status of the pod. This data may not be up to date.
     Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
[status表示状态,这个不可以修改,定义pod的时候也不需要定义这个字段]

资源清单创建Pod

通过资源清单文件创建第一个Pod

cat >nginx-pod.yaml<<\EOF
apiVersion: v1  #api版本
kind: Pod       #创建的资源
metadata:    
  name: nginx-pod  #Pod的名字
  namespace: default   #Pod所在的名称空间
  labels:
    app:  nginx     #Pod具有的标签
spec:
  containers:
  - name:  nginx-pod   #Pod里容器的名字
    ports:
    - containerPort: 80  #容器暴露的端口
    image: nginx:latest  #容器使用的镜像
    imagePullPolicy: IfNotPresent    #镜像拉取策略
EOF

更新资源清单文件

kubectl apply -f nginx-pod.yaml

查看pod是否创建成功

[root@master1 ~]# kubectl get pods -o wide -l app=nginx
NAME        READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          2m10s   10.244.135.56   node3   <none>           <none>

我们上面创建的pod是一个自主式pod,也就是通过pod创建一个应用程序,如果pod出现故障停掉,那么我们通过pod部署的应用也就会停掉,不安全, 还有一种控制器管理的pod,通过控制器创建pod,可以对pod的生命周期做管理,可以定义pod的副本数,如果有一个pod意外停掉,那么会自动起来一个pod替代之前的pod,之后会讲解pod的控制器

清理环境

kubectl delete -f nginx-pod.yaml
rm -f nginx-pod.yaml

从命令行创建pod

通过kubectl run创建Pod

kubectl run nginx-pod --image=nginx:latest  --image-pull-policy='IfNotPresent'  --port=80

查看pod是否创建成功

[root@master1 ~]# kubectl get pod|grep nginx
nginx-pod   1/1     Running   0          13s

清理环境

kubectl delete pod nginx-pod

简单管理使用pod

通过资源清单文件创建第一个Pod

cat >nginx-pod.yaml<<\EOF
apiVersion: v1  #api版本
kind: Pod       #创建的资源
metadata:    
  name: nginx-pod  #Pod的名字
  namespace: default   #Pod所在的名称空间
  labels:
    app:  nginx     #Pod具有的标签
spec:
  containers:
  - name:  nginx-pod-rongqi   #Pod里容器的名字
    ports:
    - containerPort: 80  #容器暴露的端口
    image: nginx:latest  #容器使用的镜像
    imagePullPolicy: IfNotPresent    #镜像拉取策略
EOF

更新资源清单文件

kubectl apply -f nginx-pod.yaml

查看pod日志

kubectl logs nginx-pod -n default

查看pod里指定容器的日志

kubectl logs nginx-pod  -c nginx-pod-rongqi

进入到刚才创建的pod,刚才创建的pod名字是web

kubectl exec -it nginx-pod   -- /bin/bash

假如pod里有多个容器,进入到pod里的指定容器,按如下命令:

kubectl exec -it nginx-pod  -c  nginx-pod-rongqi -- /bin/bash 

Pod工作方式

在K8s中,所有的资源都可以使用一个yaml文件来创建,创建Pod也可以使用yaml配置文件。或者使用kubectl run在命令行创建Pod(不常用)。

自主式Pod

所谓的自主式Pod,就是直接定义一个Pod资源,如下:

cat >nginx-pod.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: default
  labels:
    app:  nginx
spec:
  containers:
  - name:  nginx-pod
    ports:
    - containerPort: 80
    image: nginx:latest
    imagePullPolicy: IfNotPresent
EOF

更新资源清单文件

kubectl apply -f nginx-pod.yaml 

查看pod是否创建成功

[root@master1 ~]# kubectl get pods -o wide -l app=nginx
NAME        READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          25s   10.244.104.2   node2   <none>           <none> 

但是自主式Pod是存在一个问题的,假如我们不小心删除了pod:

[root@master1 ~]# kubectl delete pods nginx-pod
pod "nginx-pod" deleted

查看pod是否还在
[root@master1 ~]# kubectl get pods -l app=tomcat
No resources found in default namespace.
结果是空,说明pod已经被删除了

通过上面可以看到,如果直接定义一个Pod资源,那Pod被删除,就彻底被删除了,不会再创建一个新的Pod,这在生产环境还是具有非常大风险的,所以今后我们接触的Pod,都是控制器管理的。

清理环境

rm -f nginx-pod.yaml 

控制器Pod

常见的管理Pod的控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。

ReplicaSet: 代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。 ReplicaSet主要三个组件组成:   (1)用户期望的pod副本数量   (2)标签选择器,判断哪个pod归自己管理   (3)当现存的pod数量不足,会根据pod资源模板进行新建 帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。

Deployment:工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。

DaemonSet:用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务 特性:服务是无状态的 服务必须是守护进程

Job:只要完成就立即退出,不需要重启或重建。

Cronjob:周期性任务控制,不需要持续后台运行,

StatefulSet:管理有状态应用

控制器管理的Pod可以确保Pod始终维持在指定的副本数运行。 如,通过Deployment管理Pod

创建一个资源清单文件

cat >nginx-deployment.yaml<<\EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-deployment
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80       
EOF

更新资源清单文件

kubectl apply -f nginx-deployment.yaml

查看Deployment

[root@master1 ~]# kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           10s

[root@master1 ~]# kubectl get deploy -l app=nginx
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           35s

查看Replicaset

[root@master1 ~]# kubectl get rs -l app=nginx
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-66d78c88fb   2         2         2       48s

查看pod

[root@master1 ~]# kubectl get pods -o wide -l app=nginx
NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
nginx-deployment-66d78c88fb-4fvnv   1/1     Running   0          61s   10.244.135.40   node3   <none>           <none>
nginx-deployment-66d78c88fb-5qzt2   1/1     Running   0          61s   10.244.104.45   node2   <none>           <none>

删除nginx-test-75c685fdb7-9s95h这个pod

[root@master1 ~]# kubectl delete pods nginx-test-75c685fdb7-9s95h
[root@master1 ~]# kubectl get pods -o wide -l app=nginx
NAME                           READY   STATUS              IP                        
nginx-test-75c685fdb7-6d4lx    1/1       Running            10.244.102.69   
nginx-test-75c685fdb7-pr8gh    1/1      Running             10.244.102.70  

发现重新创建一个新的pod是nginx-test-75c685fdb7-pr8gh

通过上面可以发现通过deployment管理的pod,可以确保pod始终维持在指定副本数量

导出yaml清单文件

如何导出pod的yaml文件

kubectl get pod nginx-deployment-66d78c88fb-2c65q -o yaml

如何导出deployment的yaml文件

kubectl get deployment -o yaml

清理环境

kubectl delete deployment nginx-deployment