1、 k8s核心资源之Pod概念及入门使用

1.1 什么是Pod?

官方文档:https://kubernetes.io/docs/concepts/workloads/pods/

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

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

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

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

1.2 Pod如何管理多个容器?

image

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

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

1.3 Pod网络

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

1.4 Pod存储

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

1.5 Pod工作方式

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

1.5.1 自主式Pod

① 所谓的自主式Pod,就是直接定义一个Pod资源,如下:yaml文件内容编写在后面会有讲解

[root@k8s-master1 kubenetes-han]# vim pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
  name: tomcat-test
  namespace: default
  labels:
    app:  tomcat
spec:
  containers:
  - name:  tomcat-java
    ports:
    - containerPort: 8080
    image: hxu/tomcat-8.5-jre8:v1
  imagePullPolicy: IfNotPresent

② 上传镜像到node节点,步骤省略
③ 更新资源清单文件yaml文件创建pod

[root@k8s-master1 kubenetes-han]# kubectl apply -f pod-tomcat.yaml 
pod/tomcat-test created
查看pod
[root@k8s-master1 kubenetes-han]# kubectl get pod
tomcat-test                   1/1     Running   0          5s

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

[root@k8s-master1 kubenetes-han]# kubectl delete pods tomcat-test
pod "tomcat-test" deleted

查看pod是否还在kubectl get pods -l app=tomcat
结果是空,说明pod已经被删除了
通过上面可以看到,如果直接定义一个Pod资源,那Pod被删除,就彻底被删除了,不会再创建一个新的Pod,这在生产环境还是具有非常大风险的,所以今后我们接触的Pod,都是控制器管理的。

1.5.2 控制器管理的Pod

常见的管理Pod的控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。
控制器管理的Pod可以确保Pod始终维持在指定的副本数运行。
如,通过Deployment管理Pod

① 更新资源清单文件

#更新资源清单文件
[root@k8s-master1 kubenetes-han]#  kubectl apply -f nginx-deploy.yaml
#查看Deployment
[root@k8s-master1 kubenetes-han]# kubectl get deploy -l app=nginx-deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test   2/2     2            2           8d
[root@k8s-master1 kubenetes-han]# kubectl get rs -l app=nginx
NAME                    DESIRED   CURRENT   READY   AGE
nginx-test-57f9f5b6d7   2         2         2       8d
#查看pod
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide -l app=nginx
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-test-57f9f5b6d7-dqm8h   1/1     Running   0          8d    10.244.1.17   k8s-node1   <none>           <none>
nginx-test-57f9f5b6d7-fxsw5   1/1     Running   0          8d    10.244.1.16   k8s-node1   <none>           <none>
#删除nginx-test-57f9f5b6d7-dqm8h这个pod
[root@k8s-master1 kubenetes-han]# kubectl delete pods nginx-test-57f9f5b6d7-dqm8h
pod "nginx-test-57f9f5b6d7-dqm8h" deleted
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide -l app=nginx
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-test-57f9f5b6d7-8zt7x   1/1     Running   0          16s   10.244.1.19   k8s-node1   <none>           <none>
nginx-test-57f9f5b6d7-fxsw5   1/1     Running   0          8d    10.244.1.16   k8s-node1   <none>           <none>
#发现重新创建一个新的pod是nginx-test-57f9f5b6d7-8zt7x

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

1.6 创建Pod流程

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

第一步:
客户端提交创建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。

2、Pod资源清单yaml文件内容详细解读

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数
        memory: string     #内存限制,单位可以为Mib/Gib
      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

3、如何编写资源清单YAML文件?

示例:

# vim pod-tomcat.yaml
apiVersion: v1  #api版本
kind: Pod       #创建的资源
metadata:    
  name: tomcat-test  #Pod的名字
  namespace: default   #Pod所在的名称空间
  labels:
    app:  tomcat     #Pod具有的标签
spec:
  containers:
  - name:  tomcat-java   #Pod里容器的名字
    ports:
    - containerPort: 8080  #容器暴露的端口
    image: hxu/tomcat-8.5-jre8:v1  #容器使用的镜像
  imagePullPolicy: IfNotPresent    #镜像拉取策略

#更新资源清单文件
# kubectl apply -f pod-tomcat.yaml 

# Pod资源清单编写技巧
通过kubectl explain 查看定义Pod资源包含哪些字段。
# 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.metadata字段如何定义
# kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1
RESOURCE: metadata <Object>

# metadata是对象<Object>,下面可以有多个字段

DESCRIPTION:
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
     ObjectMeta is metadata that all persisted resources must have, which
     includes all objects users must create.

FIELDS:
   annotations	<map[string]string>
     Annotations is an unstructured key value map stored with a resource that
     may be set by external tools to store and retrieve arbitrary metadata. They
     are not queryable and should be preserved when modifying objects. More
     info: http://kubernetes.io/docs/user-guide/annotations
# annotations是注解,map类型表示对应的值是key-value键值对,<string,string>表示 key和value都是String类型的
"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}
用Annotation来记录的信息包括:
build信息、release信息、Docker镜像信息等,例如时间戳、release id号、镜像hash值、docker registry地址等;
日志库、监控库、分析库等资源库的地址信息;
程序调试工具信息,例如工具名称、版本号等;
团队的联系信息,例如电话号码、负责人名称、网址等。

   clusterName	<string>
     The name of the cluster which the object belongs to. This is used to
     distinguish resources with same name and namespace in different clusters.
     This field is not set anywhere right now and apiserver is going to ignore
     it if set in create or update request.
#对象所属群集的名称。这是用来区分不同集群中具有相同名称和命名空间的资源。此字段现在未设置在任何位置,apiserver将忽略它,如果设置了就使用设置的值

   creationTimestamp	<string>
   deletionGracePeriodSeconds	<integer>
   deletionTimestamp	<string>
   finalizers	<[]string>
   generateName	<string>
   generation	<integer>
   labels	<map[string]string> #创建的资源具有的标签
Map of string keys and values that can be used to organize and categorize
     (scope and select) objects. May match selectors of replication controllers
     and services. More info: http://kubernetes.io/docs/user-guide/labels
#labels是标签,labels是map类型,map类型表示对应的值是key-value键值对,<string,string>表示 key和value都是String类型的
   managedFields	<[]Object>
   name	<string>           #创建的资源的名字
   namespace	<string>      #创建的资源所属的名称空间
Namespace defines the space within which each name must be unique. An empty
namespace is equivalent to the "default" namespace, but "default" is the
canonical representation. Not all objects are required to be scoped to a
namespace - the value of this field for those objects will be empty.
     Must be a DNS_LABEL. Cannot be updated. More info:
     http://kubernetes.io/docs/user-guide/namespaces
# namespaces划分了一个空间,在同一个namesace下的资源名字是唯一的,默认的名称空间是default。
   ownerReferences	<[]Object>
   resourceVersion	<string>
   selfLink	<string>
   uid	<string>****

查看pod.spec字段如何定义

# kubectl explain pod.spec
KIND:     Pod
VERSION:  v1
RESOURCE: spec <Object>
DESCRIPTION:
     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
     PodSpec is a description of a pod.
#Pod的spec字段是用来描述Pod的

FIELDS:
   activeDeadlineSeconds	<integer>
#表示Pod可以运行的最长时间,达到设置的值后,Pod会自动停止。
affinity	<Object>
  #定义亲和性的
   automountServiceAccountToken	<boolean>
   containers	<[]Object> -required-
#containers是对象列表,用来定义容器的,是必须字段。对象列表 表示下面有很多对象,对象列表下面的内容用 - 连接。
   dnsConfig	<Object>
   dnsPolicy	<string>
   enableServiceLinks	<boolean>
   ephemeralContainers	<[]Object>
   hostAliases	<[]Object>
   hostIPC	<boolean>
   hostNetwork	<boolean>
   hostPID	<boolean>
   hostname	<string>
   imagePullSecrets	<[]Object>
   initContainers	<[]Object>
   nodeName	<string>
   nodeSelector	<map[string]string>
   overhead	<map[string]string>
   preemptionPolicy	<string>
   priority	<integer>
   priorityClassName	<string>
   readinessGates	<[]Object>
   restartPolicy	<string>
   runtimeClassName	<string>
   schedulerName	<string>
   securityContext	<Object>
   serviceAccount	<string>
   serviceAccountName	<string>
   setHostnameAsFQDN	<boolean>
   shareProcessNamespace	<boolean>
   subdomain	<string>
   terminationGracePeriodSeconds	<integer>
   tolerations	<[]Object>
   topologySpreadConstraints	<[]Object>
   volumes	<[]Object>

查看pod.spec.containers字段如何定义

# kubectl explain pod.spec.containers
KIND:     Pod
VERSION:  v1

RESOURCE: containers <[]Object>
DESCRIPTION:
     List of containers belonging to the pod. Containers cannot currently be
     added or removed. There must be at least one container in a Pod. Cannot be
     updated.
     A single application container that you want to run within a pod.
#container是定义在pod里面的,一个pod至少要有一个容器。

FIELDS:
   args	<[]string>
   command	<[]string>
   env	<[]Object>
   envFrom	<[]Object>
   image	<string>
#image是用来指定容器需要的镜像的
   imagePullPolicy	<string>
#镜像拉取策略,pod是要调度到node节点的,那pod启动需要镜像,可以根据这个字段设置镜像拉取策略,支持如下三种:
Always:不管本地是否存在镜像,都要重新拉取镜像
Never: 从不拉取镜像
IfNotPresent:如果本地存在,使用本地的镜像,本地不存在,从官方拉取镜像

   lifecycle	<Object>
   livenessProbe	<Object>
   name	<string> -required-
#name是必须字段,用来指定容器名字的
   ports	<[]Object>
#port是端口,属于对象列表
   readinessProbe	<Object>
   resources	<Object>
   securityContext	<Object>
   startupProbe	<Object>
   stdin	<boolean>
   stdinOnce	<boolean>
   terminationMessagePath	<string>
   terminationMessagePolicy	<string>
   tty	<boolean>
   volumeDevices	<[]Object>
   volumeMounts	<[]Object>
   workingDir	<string>

查看pod.spec.container.ports字段如何定义

# kubectl explain pod.spec.containers.ports
KIND:     Pod
VERSION:  v1
RESOURCE: ports <[]Object>
DESCRIPTION:
     List of ports to expose from the container. Exposing a port here gives the
     system additional information about the network connections a container
     uses, but is primarily informational. Not specifying a port here DOES NOT
     prevent that port from being exposed. Any port which is listening on the
     default "0.0.0.0" address inside a container will be accessible from the
     network. Cannot be updated.

     ContainerPort represents a network port in a single container.
FIELDS:
   containerPort	<integer> -required-
     Number of port to expose on the pod's IP address. This must be a valid port
     number, 0 < x < 65536.
#containerPort是必须字段, pod中的容器需要暴露的端口。

   hostIP	<string>
     What host IP to bind the external port to.
#将容器中的服务暴露到宿主机的端口上时,可以指定绑定的宿主机 IP。
   hostPort	<integer>
     Number of port to expose on the host. If specified, this must be a valid
     port number, 0 < x < 65536. If HostNetwork is specified, this must match
     ContainerPort. Most containers do not need this.
#容器中的服务在宿主机上映射的端口
   name	<string>
     If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
     named port in a pod must have a unique name. Name for the port that can be
     referred to by services.
#端口的名字
   protocol	<string>
     Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP".

通过资源清单文件创建第一个Pod(如上文的1.5.1章节)

#查看pod日志
kubectl logs pod-first

#查看pod里指定容器的日志
kubectl logs pod-first  -c tomcat-first

#进入到刚才创建的pod,刚才创建的pod名字是web
kubectl exec -it pod-first  -- /bin/bash

#假如pod里有多个容器,进入到pod里的指定容器,按如下命令:
kubectl exec -it pod-first  -c  tomcat-first -- /bin/bash

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

通过kubectl run创建Pod

kubectl run tomcat --image=hxu/tomcat-8.5-jre8:v1  --image-pull-policy='IfNotPresent'  --port=8080
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐