探索云原生技术之容器编排引擎-Kubernetes/K8S详解(3)

基本理论介绍

什么是云原生

Pivotal公司的Matt Stine于2013年首次提出云原生(Cloud-Native)的概念;2015年,云原生刚推广时,Matt Stine在《迁移到云原生架构》一书中定义了符合云原生架构的几个特征:12因素、微服务、自敏捷架构、基于API协作、扛脆弱性;到了2017年,Matt Stine在接受InfoQ采访时又改了口风,将云原生架构归纳为模块化、可观察、可部署、可测试、可替换、可处理6特质;而Pivotal最新官网对云原生概括为4个要点:DevOps+持续交付+微服务+容器

总而言之,符合云原生架构的应用程序应该是:采用开源堆栈(K8S+Docker)进行容器化,基于微服务架构提高灵活性和可维护性,借助敏捷方法、DevOps支持持续迭代和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。

此处摘选自《知乎-华为云官方帐号》

在这里插入图片描述

什么是kubernetes

kubernetes,简称K8s,是用8代替8个字符"ubernete"而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了应用部署,规划,更新,维护的一种机制

传统的应用部署方式:是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。

新的部署方式:是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。

容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更"透明",这更便于监控和管理。

Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。

在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。

此处摘选自《百度百科》

kubernetes核心功能
  • 存储系统挂载(数据卷):pod中容器之间共享数据,可以使用数据卷
  • 应用健康检测:容器内服务可能进程阻塞无法处理请求,可以设置监控检查策略保证应用健壮性
  • 应用实例的复制(实现pod的高可用):pod控制器(deployment)维护着pod副本数量(可以自己进行设置,默认为1),保证一个pod或一组同类的pod数量始终可用,如果pod控制器deployment当前维护的pod数量少于deployment设置的pod数量,则会自动生成一个新的pod,以便数量符合pod控制器,形成高可用。
  • Pod的弹性伸缩:根据设定的指标(比如:cpu利用率)自动缩放pod副本数
  • 服务发现:使用环境变量或者DNS插件保证容器中程序发现pod入口访问地址
  • 负载均衡:一组pod副本分配一个私有的集群IP地址,负载均衡转发请求到后端容器。在集群内部其他pod可通过这个clusterIP访问应用
  • 滚动更新:更新服务不会发生中断,一次更新一个pod,而不是同时删除整个服务。
  • 容器编排:通过文件来部署服务,使得应用程序部署变得更高效
  • 资源监控:node节点组件集成cAdvisor资源收集工具,可通过Heapster汇总整个集群节点资源数据,然后存储到InfluxDb时序数据库,再由Grafana展示。
  • 提供认证和授权:支持角色访问控制(RBAC)认证授权等策略
Pod详解
Pod的结构

在这里插入图片描述

  • 每一个Pod里面都至少有1个或者n个容器,其中有两类容器:
    • 普通容器(用户容器):普通容器就是我们可见的容器、就是我们在创建Pod所指定的容器。
    • Pause容器(根容器):系统自带的容器,每一个Pod都会有一个Pause容器:
      • Pause容器的健康状态可以代表整个Pod的健康状态,所以可以用Pause容器的健康状态来判定Pod是否存活之类的数据。
      • 可以给Pause容器设置IP地址,那么整个Pod的其他容器可以使用这个Pause容器的IP地址,以实现Pod内部的网络通信(这里是Pod内部的通讯,Pod之间的通讯采用虚拟二层网络技术来实现,我们当前环境使用的是Flannel)
Pod的yaml文件定义
apiVersion: v1     #必选,版本号,例如v1
kind: Pod         #必选,资源类型,例如 Pod
metadata:         #必选,元数据
  name: string     #必选,Pod名称
  namespace: string  #Pod所属的命名空间,默认为"default"
  labels:           #自定义标签列表
    - name: string                 
spec:  #必选,Pod中容器的详细定义
  containers:  #必选,Pod中容器列表
  - name: string   #必选,容器名称
    image: string  #必选,容器的镜像名称
    imagePullPolicy: [ Always|Never|IfNotPresent ]  #获取镜像的策略,Always是一直从DockerHub上拉取、Never只拉取本机Docker镜像、IfNotPresent是如果本地有这个镜像则拉取本地的镜像,如果本地没有则去DockerHub上拉取
    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 #内存请求,容器启动的初始可用数量
    lifecycle: #生命周期钩子
		postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
		preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
    livenessProbe:  #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
      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是一直都会重启,知道成功。Never是永不重启。
  nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
  nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
  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的存储卷,挂载集群与定义的secret对象到容器内部
      scretname: string  
      items:     
      - key: string
        path: string
    configMap:         #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
      name: string
      items:
      - key: string
        path: string

查看k8s各种资源的yaml配置项

kubectl explain 资源名称
  • 例如:查看Pod的yaml的可配置项(可以通过点(.)去查看下一级的可配置项):
[root@k8s-master ~]# 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.

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

   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

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#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

   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
  • 例如:查看Pod的yaml的的metadata可配置项
[root@k8s-master ~]# kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1

RESOURCE: 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

   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.

   creationTimestamp	<string>
     CreationTimestamp is a timestamp representing the server time when this
     object was created. It is not guaranteed to be set in happens-before order
     across separate operations. Clients may not set this value. It is
     represented in RFC3339 form and is in UTC. Populated by the system.
     Read-only. Null for lists. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   deletionGracePeriodSeconds	<integer>
     Number of seconds allowed for this object to gracefully terminate before it
     will be removed from the system. Only set when deletionTimestamp is also
     set. May only be shortened. Read-only.

   deletionTimestamp	<string>
     DeletionTimestamp is RFC 3339 date and time at which this resource will be
     deleted. This field is set by the server when a graceful deletion is
     requested by the user, and is not directly settable by a client. The
     resource is expected to be deleted (no longer visible from resource lists,
     and not reachable by name) after the time in this field, once the
     finalizers list is empty. As long as the finalizers list contains items,
     deletion is blocked. Once the deletionTimestamp is set, this value may not
     be unset or be set further into the future, although it may be shortened or
     the resource may be deleted prior to this time. For example, a user may
     request that a pod is deleted in 30 seconds. The Kubelet will react by
     sending a graceful termination signal to the containers in the pod. After
     that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL)
     to the container and after cleanup, remove the pod from the API. In the
     presence of network partitions, this object may still exist after this
     timestamp, until an administrator or automated process can determine the
     resource is fully terminated. If not set, graceful deletion of the object
     has not been requested. Populated by the system when a graceful deletion is
     requested. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   finalizers	<[]string>
     Must be empty before the object is deleted from the registry. Each entry is
     an identifier for the responsible component that will remove the entry from
     the list. If the deletionTimestamp of the object is non-nil, entries in
     this list can only be removed. Finalizers may be processed and removed in
     any order. Order is NOT enforced because it introduces significant risk of
     stuck finalizers. finalizers is a shared field, any actor with permission
     can reorder it. If the finalizer list is processed in order, then this can
     lead to a situation in which the component responsible for the first
     finalizer in the list is waiting for a signal (field value, external
     system, or other) produced by a component responsible for a finalizer later
     in the list, resulting in a deadlock. Without enforced ordering finalizers
     are free to order amongst themselves and are not vulnerable to ordering
     changes in the list.

   generateName	<string>
     GenerateName is an optional prefix, used by the server, to generate a
     unique name ONLY IF the Name field has not been provided. If this field is
     used, the name returned to the client will be different than the name
     passed. This value will also be combined with a unique suffix. The provided
     value has the same validation rules as the Name field, and may be truncated
     by the length of the suffix required to make the value unique on the
     server. If this field is specified and the generated name exists, the
     server will NOT return a 409 - instead, it will either return 201 Created
     or 500 with Reason ServerTimeout indicating a unique name could not be
     found in the time allotted, and the client should retry (optionally after
     the time indicated in the Retry-After header). Applied only if Name is not
     specified. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency

   generation	<integer>
     A sequence number representing a specific generation of the desired state.
     Populated by the system. Read-only.

   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

   managedFields	<[]Object>
     ManagedFields maps workflow-id and version to the set of fields that are
     managed by that workflow. This is mostly for internal housekeeping, and
     users typically shouldn't need to set or understand this field. A workflow
     can be the user's name, a controller's name, or the name of a specific
     apply path like "ci-cd". The set of fields is always in the version that
     the workflow used when modifying the object.

   name	<string>
     Name must be unique within a namespace. Is required when creating
     resources, although some resources may allow a client to request the
     generation of an appropriate name automatically. Name is primarily intended
     for creation idempotence and configuration definition. Cannot be updated.
     More info: http://kubernetes.io/docs/user-guide/identifiers#names

   namespace	<string>
     Namespace defines the space within 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

   ownerReferences	<[]Object>
     List of objects depended by this object. If ALL objects in the list have
     been deleted, this object will be garbage collected. If this object is
     managed by a controller, then an entry in this list will point to this
     controller, with the controller field set to true. There cannot be more
     than one managing controller.

   resourceVersion	<string>
     An opaque value that represents the internal version of this object that
     can be used by clients to determine when objects have changed. May be used
     for optimistic concurrency, change detection, and the watch operation on a
     resource or set of resources. Clients must treat these values as opaque and
     passed unmodified back to the server. They may only be valid for a
     particular resource or set of resources. Populated by the system.
     Read-only. Value must be treated as opaque by clients and . More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency

   selfLink	<string>
     SelfLink is a URL representing this object. Populated by the system.
     Read-only. DEPRECATED Kubernetes will stop propagating this field in 1.20
     release and the field is planned to be removed in 1.21 release.

   uid	<string>
     UID is the unique in time and space value for this object. It is typically
     generated by the server on successful creation of a resource and is not
     allowed to change on PUT operations. Populated by the system. Read-only.
     More info: http://kubernetes.io/docs/user-guide/identifiers#uids

Pod的基本配置
  • 创建yaml文件
vim pod01.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod01-label
   name: pod01
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container
     - image: ubuntu:22.10
       name: ubuntu-container
  • 创建Pod
[root@k8s-master ~]# kubectl apply -f pod01.yaml
namespace/test created
pod/pod01 created
  • 查看Pod信息
[root@k8s-master ~]# kubectl get pods -n test 
NAME    READY   STATUS             RESTARTS   AGE
pod01   1/2     CrashLoopBackOff   2          36s
[root@k8s-master ~]# kubectl describe pod pod01 -n test
Name:         pod01
Namespace:    test
Priority:     0
Node:         k8s-slave02/192.168.184.102
Start Time:   Wed, 08 Jun 2022 21:43:47 +0800
Labels:       app=pod01-label
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"pod01-label"},"name":"pod01","namespace":"test"},"spec":{"co...
Status:       Running
IP:           10.244.2.3
IPs:
  IP:  10.244.2.3
Containers:
  nginx-container:
    Container ID:   docker://1994d2e990528ead9b5066be055a17f46748084f8f92bdb6379b4e7e7a0be664
    Image:          nginx:1.17
    Image ID:       docker-pullable://nginx@sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a6420d8ae16ef37c92d1eb26699
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 08 Jun 2022 21:43:48 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-wpxp2 (ro)
  ubuntu-container:
    Container ID:   docker://040e054a760cbb99943f41c52cb362bd2177e1f8f5f438261fd5cb8fe6d3e664
    Image:          ubuntu:22.10
    Image ID:       docker-
Events:
  Type     Reason     Age                From                  Message
  ----     ------     ----               ----                  -------
  Normal   Scheduled  56s                default-scheduler     Successfully assigned test/pod01 to k8s-slave02
  Normal   Pulled     55s                kubelet, k8s-slave02  Container image "nginx:1.17" already present on machine
  Normal   Created    55s                kubelet, k8s-slave02  Created container nginx-container
  Normal   Started    55s                kubelet, k8s-slave02  Started container nginx-container
  Normal   Pulled     10s (x4 over 55s)  kubelet, k8s-slave02  Container image "ubuntu:22.10" already present on machine
  Normal   Created    10s (x4 over 55s)  kubelet, k8s-slave02  Created container ubuntu-container
  Normal   Started    10s (x4 over 55s)  kubelet, k8s-slave02  Started container ubuntu-container
  Warning  BackOff    8s (x6 over 53s)   kubelet, k8s-slave02  Back-off restarting failed container

我们发现Ubuntu容器启动失败了(Back-off restarting failed container),k8s系统采取了默认的重启策略。上面也可以看到Pod的RESTARTS为2,说明已经重启了2次。

镜像拉取策略(imagePullPolicy)
  • imagePullPolicy(镜像拉取策略),kubernetes目前支持3种拉取策略:

    • Always:不管本地有没有这个镜像,k8s拉取这个镜像的时候都会从网上(例如:DockerHub上)下载
    • IfNotPresent:如果本地有这个镜像,k8s就会从本地拉取这个镜像,如果本地没有这个镜像,k8s才会从网上(例如:DockerHub上)下载
    • Never:不会从网上下载镜像。如果本地有这个镜像,k8s则会从本地拉取这个镜像,如果本地没有这个镜像,则直接报错。
  • 镜像拉取策略注意点:

    • 如果镜像tag指定为具体的版本号例如:nginx:1.17,默认策略是IfNotPresent。

    • 如果镜像tag为latest(最终版本)例如:nginx:latest,默认策略是Always。

  • 创建yaml文件

vim pod02.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod02-label
   name: pod02
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container2
       imagePullPolicy: Always
     - image: ubuntu:22.10
       name: ubuntu-container2
       imagePullPolicy: IfNotPresent #写不写都是一样,默认就是这个模式
  • 创建Pod
[root@k8s-master ~]# kubectl apply -f pod02.yaml
namespace/test created
pod/pod02 created
  • 使用kubectl describe去查看Pod
Events:
  Type     Reason     Age              From                  Message
  ----     ------     ----             ----                  -------
  Normal   Scheduled  20s              default-scheduler     Successfully assigned test/pod02 to k8s-slave02
  Normal   Pulling    20s              kubelet, k8s-slave02  Pulling image "nginx:1.17"
  Normal   Pulled     4s               kubelet, k8s-slave02  Successfully pulled image "nginx:1.17"
  Normal   Created    4s               kubelet, k8s-slave02  Created container nginx-container1
  Normal   Started    4s               kubelet, k8s-slave02  Started container nginx-container1
  Normal   Pulled     2s (x2 over 4s)  kubelet, k8s-slave02  Container image "ubuntu:22.10" already present on machine
  Normal   Created    2s (x2 over 4s)  kubelet, k8s-slave02  Created container ubuntu-container1
  Normal   Started    2s (x2 over 3s)  kubelet, k8s-slave02  Started container ubuntu-container1
  Warning  BackOff    0s (x2 over 1s)  kubelet, k8s-slave02  Back-off restarting failed container

可以看到我们的nginx镜像是重新从dockerhub上面拉取,而Ubuntu由于我们本地有所以就会从本地拉取。

启动命令(command )
  • 为什么在前面我们Ubuntu容器无法启动成功?

    • Ubuntu是一个Linux系统,kubernetes会在它启动之后立刻关闭掉它,解决的办法就是让这个Ubuntu持续工作,例如写一个shell程序一直让Ubuntu系统处于工作中状态即可。
    • command是在容器运行之后立刻执行的命令。
  • 创建yaml文件

vim pod03.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod03-label
   name: pod03
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container3
     - image: ubuntu:22.10
       name: ubuntu-container3
       command: ["/bin/sh","-c","touch /tmp/timelog.txt;while true;do echo $(date +%T) >> /tmp/timelog.txt ;sleep 3;done;"]
  • 创建Pod
[root@k8s-master ~]# kubectl apply -f pod03.yaml
namespace/test created
pod/pod03 created
  • 进入Pod名为pod03中的容器名为ubuntu-container3的容器内部:

格式:

kubectl exec -it pod的名称 -n 命名空间 --container=容器名称 /bin/sh
[root@k8s-master ~]# kubectl exec -it pod03 --container=ubuntu-container3 --namespace=test /bin/sh
  • 使用tail -f 以日志的形式查看内容:
# tail -f /tmp/timelog.txt
15:25:24
15:25:27
15:25:30
15:25:33
15:25:36
15:25:39
15:25:42
15:25:45
15:25:48
15:25:51

注意点:

  • 如果command和args均没有写,那么用Dockerfile的配置。

  • 如果command写了,但是args没有写,那么Dockerfile默认的配置会被忽略,执行注入的command。

  • 如果command没有写,但是args写了,那么Dockerfile中配置的ENTRYPOINT命令会被执行,使用当前args的参数。

  • 如果command和args都写了,那么Dockerfile中的配置会被忽略,执行command并追加上args参数。

环境变量(env)
  • 作用如下:(不推荐使用)

    • 为Pod容器设置环境变量(也可以作为全局变量)
  • 创建yaml文件

vim pod04.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod04-label
   name: pod04
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container4
     - image: ubuntu:22.10
       name: ubuntu-container4
       env:
         - name: "username"
           value: "root"
         - name: "password"
           value: "123456"
       command: ["/bin/sh","-c","touch /tmp/timelog.txt;while true;do echo $(date +%T) >> /tmp/timelog.txt ;sleep 3;done;"]
  • 创建Pod
kubectl apply -f pod04.yaml
  • 进入Pod名为pod04中的容器名为ubuntu-container4的容器内部:

格式:

[root@k8s-master ~]# kubectl exec -it pod04 --container=ubuntu-container4 --namespace=test /bin/sh
  • 输出一下环境变量:
# echo $username
root
# echo $password
123456

此种方式不推荐,推荐将这些配置单独存储在配置文件中。

设置端口(ports)

格式(只展示常用的):

KIND:     Pod
VERSION:  v1
RESOURCE: ports <[]Object>
FIELDS:
  name <string> # 端口名称,如果指定,必须保证name在pod中是唯一的,可以不指定。
  containerPort <integer> # 容器要监听的端口(0->65536)。
  protocol <string>  # 端口协议。必须是UDP、TCP或SCTP。默认为“TCP”        
  • 创建yaml文件
vim pod05.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod05-label
   name: pod05
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container5
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
  • 创建Pod
kubectl apply -f pod05.yaml
  • 访问Pod05中的nginx端口:
root@k8s-master ~]# kubectl get pods -n test -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
pod05   1/1     Running   0          11s   10.244.2.9   k8s-slave02   <none>           <none>
[root@k8s-master ~]# curl 10.244.2.9:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
资源配额(resources)
  • 为什么kubernetes会出现一个资源配额机制?

    • 例子:假设一台服务器内存只有1G、CPU只有1核,上面运行了一个Pod,这个Pod中有Nginx、Redis、MySQL容器,假设正常情况下这个Pod的容器一共占用500M,某一时刻突然有大量的流量通过Nginx容器,此时Nginx容器的内存、CPU占用势必会大大的提高,若我们对Pod中的容器不加以限制的话,Nginx容器的内存占用很容器就会到达1G,此时Pod中的Nginx、Redis、MySQL一共只有1G内存,而Nginx此时就已经占用1G,就会导致Redis和MySQL没有任何内存可以使用,从而导致Redis、MySQL服务宕机,然后就会导致整个微服务不可用。
    • 而引入了资源配额机制之后在上面同样的场景下给Nginx、Redis、MySQL各个都分配300M,此时不管流量有多大,都不会导致上面三个容器同时崩溃,最多会导致容器触发重启。
  • 资源配额:

    • limits:最大资源(CPU、memory)占用。如果容器占用资源超过(大于)这个设置的话,则会对这个容器进行终止并重启。
    • requests:最小资源(CPU、memory)占用。如果此时服务器的可使用资源低于(小于)这个设置的话,则容器将无法启动。
    • cpu:core核心数,可以为整数或小数。
    • memory:内存大小,可以使用Gi、Mi、G、M等形式。Mi表示(1Mi=1024x1024),M表示(1M=1000x1000)
[root@k8s-master ~]# kubectl explain pods.spec.containers.resources
KIND:     Pod
VERSION:  v1

RESOURCE: resources <Object>

DESCRIPTION:
     Compute Resources required by this container. Cannot be updated. More info:
     https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

     ResourceRequirements describes the compute resource requirements.

FIELDS:
   limits	<map[string]string>
     Limits describes the maximum amount of compute resources allowed. More
     info:
     https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

   requests	<map[string]string>
     Requests describes the minimum amount of compute resources required. If
     Requests is omitted for a container, it defaults to Limits if that is
     explicitly specified, otherwise to an implementation-defined value. More
     info:
     https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
  • 创建yaml文件
vim pod06.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod06-label
   name: pod06
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container6
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
       resources:
          limits:  #最高
            cpu: "2"
            memory: "30Mi"
          requests: #最低
            cpu: "1"
            memory: "5Mi"
            
---
apiVersion: v1
kind: Service
metadata:
  name: service06
  namespace: test
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: pod06-label
  type: NodePort
  • 创建Pod
[root@k8s-master ~]# kubectl apply -f pod06.yaml
namespace/test created
pod/pod06 created
service/service06 created

如果资源达不到启动的要求时(启动需要资源大于requests设置的值时,会创建失败容器):

[root@k8s-master ~]# kubectl get pods -n test 
NAME    READY   STATUS                 RESTARTS   AGE
pod06   0/1     CreateContainerError   0          15s
Pod生命周期
概述
  • 什么是Pod的生命周期?

    • Pod的生命周期就是一个Pod从创建到终止的过程。
  • Pod的生命周期过程有哪些:

    • 1:Pod创建过程(下面会讲解)首先创建一个Pod但是这个Pod不能提供服务,因为里面没有容器,需要等待初始化容器和运行主容器等一系列操作);
    • 2:运行初始化容器initContainers初始化容器中严格按照从上往下的顺序来创建容器,只有当initContainers中的所有容器都运行成功,才会运行主容器mainContainers)。
    • 3:等到上面的初始化容器initContainers全部完成之后,运行主容器mainContainers(主容器就是Pod下面的spec的containers定义的容器)
      • 1.1:执行当前容器的两个钩子函数(分别是:容器启动之后的钩子PostStart容器终止之前的钩子PreStop
      • 1.2:进行容器探测(分别是:存活性探测liveness probe就绪性探测readiness probe
    • 4:Pod的终止过程。(下面会讲解)
  • 在整个Pod的生命周期中,Pod会出现如下几种状态:

    • 1:Pending(挂起):api server创建了该Pod资源并存入etcd中,但是该Pod没有完成调度
    • 2:ContainerCreating(容器创建中):该Pod已经完成了调度,被分到某个node节点上了,但是该Pod的容器正在创建中常常是该Pod的容器镜像正在下载中
    • 3:Running(运行中):Pod正常创建成功,并且能够对外提供服务。
    • 4:Succeeded(成功):Pod中所有容器都正常退出成功,并且不会发生重启。
    • 5:Failed(失败):所有容器都已经终止,但至少有一个容器终止失败,也就是说容器返回了非0值的退出状态或已经被系统终止
    • 6:Unknown(未知):获取不到该Pod的状态,所以状态为Unknown(未知),通常是网络通信失败导致。
Pod创建过程
  1. 用户通过kubernetes的客户端(例如kubectl发送一个创建Pod的请求给ApiServer
  2. ApiServer开始生成Pod的信息,并存入etcd中,然后立刻返回创建的结果(此时肯定没有创建好这个Pod,但是也会立刻返回一个结果给客户端)。
  3. 各个kubernetes组件通过监听(watch)的机制来监听ApiServer,ApiServer暴露这些Pod的信息状态。
  4. 当Scheduler监听到ApiServer要创建Pod的时候,就开始计算将要调度到的哪一个节点上,将计算出来的结果(调度到哪个节点)传给ApiServer,ApiServer又将存入etcd中进行持久化。
  5. 通过ControllerManager去给Scheduler计算出来的节点安排工作(通知指定的node节点)。
  6. 那个被Scheduler计算出来的节点上的kubelet收到通知后就会通过Docker去启动需要创建的Pod中的所有容器,并且把状态返回给ApiServer,ApiServer将信息存入etcd中。
Pod终止过程
  1. 用户通过kubernetes客户端(例如kubectl)发生一个删除Pod的请求给ApiServer。
  2. 该Pod对象信息在ApiServer中动态更新,在宽限期内(默认是30s),此时该Pod对象被视为dead。
  3. ApiServer把这个Pod对象的状态修改成terminating。
  4. kubelet监测到该Pod对象状态为terminating,此时开始将该Pod进行关闭。
  5. 端点控制器监控到Pod对象的关闭行为时会把service列表中所有有关该Pod的信息进行移除(因为该Pod已经被移除,如果不移除对应的service数据的话则会导致访问到这个无效的Pod)。
  6. 如果当前的Pod对象定义了preStop钩子函数,则在其标记为terminating后会以同步的方式启动执行。
  7. Pod对象中的容器进程收到停止信号。
  8. 在宽限期结束后,如果该Pod还是没有被完全删除,则Pod对象会收到立刻终止的信号(上面的删除操作都是优雅的删除,那么这步的操作将是粗暴的删除)。
  9. 因为在上面几步Pod已经被完全删除了,所以此时kubelet会请求ApiServer把这个Pod的宽限期修改成0,此时这个Pod不可用和不可见,这个Pod才算是真正意义上的被删除。
初始化容器
  • 概述:初始化容器执行的优先级是最高的。说白了就是初始化容器全部运行完成之后,才会运行主容器(pod.spec.containers定义的容器)。

    • 1:一定是先执行完全部初始化容器,才会执行主容器。只有初始化容器所定义的一组容器全部执行完成之后,才会运行Pod定义的主容器,如果初始化容器中的某一个容器启动失败,则kubernetes会一直重启,直至成功。
    • 2:初始化容器中执行的顺序性。我们在初始化容器中定义的一组容器会严格按照从上往下依次进行执行,且上一个容器没有执行成功后面一个容器不会执行,会阻塞在这个失败启动的容器上,直至重启成功。
  • 初始化容器的场景:

    • 1:提供主容器镜像中不具备的工具程序或自定义代码。
    • 2:延迟主容器的启动,直至准备工作全部完成。
  • 创建yaml文件

vim pod07.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod07-label
   name: pod07
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container7
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
  initContainers: # 初始化容器配置
    - name: init-container01
      image: ubuntu:22.10
      command: ["sh","-c","sleep 3;"]
      securityContext:
        privileged: true # 使用特权模式运行容器
    - name: init-container02
      image: ubuntu:22.10
      command: ["sh","-c","sleep 3;"]
  • 先开一个shell窗口,动态查看Pod:
[root@k8s-master ~]# kubectl get pods -n test -w
  • 创建Pod
kubectl apply -f pod07.yaml
  • 返回刚刚开的shell窗口,查看Pod信息:
[root@k8s-master ~]# kubectl get pods -n test -w
NAME    READY   STATUS    RESTARTS   AGE
pod07   0/1     Pending   0          0s
pod07   0/1     Pending   0          1s
pod07   0/1     Init:0/2   0          1s
pod07   0/1     Init:0/2   0          2s
pod07   0/1     Init:1/2   0          5s
pod07   0/1     Init:1/2   0          7s
pod07   0/1     PodInitializing   0          10s
pod07   1/1     Running           0          11s
[root@k8s-master ~]# kubectl describe pod pod07 -n test 
Events:
  Type    Reason     Age   From                  Message
  ----    ------     ----  ----                  -------
  Normal  Scheduled  18s   default-scheduler     Successfully assigned test/pod07 to k8s-slave02
  Normal  Pulled     18s   kubelet, k8s-slave02  Container image "ubuntu:22.10" already present on machine
  Normal  Created    18s   kubelet, k8s-slave02  Created container init-container01
  Normal  Started    18s   kubelet, k8s-slave02  Started container init-container01
  Normal  Pulled     14s   kubelet, k8s-slave02  Container image "ubuntu:22.10" already present on machine
  Normal  Created    13s   kubelet, k8s-slave02  Created container init-container02
  Normal  Started    13s   kubelet, k8s-slave02  Started container init-container02
  Normal  Pulled     9s    kubelet, k8s-slave02  Container image "nginx:1.17" already present on machine
  Normal  Created    9s    kubelet, k8s-slave02  Created container nginx-container7
  Normal  Started    9s    kubelet, k8s-slave02  Started container nginx-container7

可以看到是先执行init-container01再到init-container02最后到主容器。

钩子函数
  • kubernetes提供了两个钩子函数,分别是:
    • 1:postStart:指定的容器启动之后执行,如果失败则会重启容器。
    • 2:preStop:指定的容器终止之前执行,如果失败则删除不了容器,直到preStop执行成功。
[root@k8s-master ~]# kubectl explain pods.spec.containers.lifecycle
KIND:     Pod
VERSION:  v1

RESOURCE: lifecycle <Object>

DESCRIPTION:
     Actions that the management system should take in response to container
     lifecycle events. Cannot be updated.

     Lifecycle describes actions that the management system should take in
     response to container lifecycle events. For the PostStart and PreStop
     lifecycle handlers, management of the container blocks until the action is
     complete, unless the container process fails, in which case the handler is
     aborted.

FIELDS:
   postStart	<Object>
     PostStart is called immediately after a container is created. If the
     handler fails, the container is terminated and restarted according to its
     restart policy. Other management of the container blocks until the hook
     completes. More info:
     https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks

   preStop	<Object>
     PreStop is called immediately before a container is terminated due to an
     API request or management event such as liveness/startup probe failure,
     preemption, resource contention, etc. The handler is not called if the
     container crashes or exits. The reason for termination is passed to the
     handler. The Pod's termination grace period countdown begins before the
     PreStop hooked is executed. Regardless of the outcome of the handler, the
     container will eventually terminate within the Pod's termination grace
     period. Other management of the container blocks until the hook completes
     or until the termination grace period is reached. More info:
     https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks

posrStart

  • 方式1:exec命令。在容器中执行一次命令
……
  lifecycle:
     postStart: 
        exec:
           command:
             - cat
             - /tmp/hello.txt
……
  • 方式2: tcpSocket。在当前容器尝试访问指定的socket。
…… 
   lifecycle:
      postStart:
         tcpSocket:
            port: 80
……
  • 方式3:httpGet。在当前容器中向某url发起HTTP请求。
…… 
   lifecycle:
      postStart:
         httpGet:
            path: / #URI地址
            port: 80 #端口号
            host: 192.168.184.100 #主机地址  
            scheme: HTTP #支持的协议,http或者https
……

preStop

  • 方式1:exec命令。在容器中执行一次命令
……
  lifecycle:
     preStop: 
        exec:
           command:
             - cat
             - /tmp/hello.txt
……
  • 方式2: tcpSocket。在当前容器尝试访问指定的socket。
…… 
   lifecycle:
      preStop:
         tcpSocket:
            port: 80
……
  • 方式3:httpGet。在当前容器中向某url发起HTTP请求。
…… 
   lifecycle:
      preStop:
         httpGet:
            path: / #URI地址
            port: 80 #端口号
            host: 192.168.184.100 #主机地址  
            scheme: HTTP #支持的协议,http或者https
……

案例:

  • 创建yaml文件
vim pod08.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod08-label
   name: pod08
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container8
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
       lifecycle: #配置生命周期
        postStart: # 容器创建之后执行,如果失败会重启容器
          exec: # 在容器启动的时候,执行一条命令,修改掉Nginx的首页内容
            command: ["/bin/sh","-c","echo lifecycle-postStart ... > /usr/share/nginx/html/index.html"]
        preStop: # 容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作
          exec: # 在容器停止之前停止Nginx的服务
            command: ["/usr/sbin/nginx","-s","quit"]
  • 创建Pod
kubectl apply -f pod08.yaml
  • 查看ip并访问这个nginx
[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES
pod08   1/1     Running   0          2s    10.244.1.12   k8s-slave01   <none>           <none>
[root@k8s-master ~]# curl 10.244.1.12:80
lifecycle-postStart ...
容器探测(初级)
  • kubernetes提供了两种探针来实现容器探测,分别是:
    • 1:livenessProbes:存活性探测。如果探测失败,k8s会认为该容器没启动成功,所以会重启容器
    • 2:readinessProbes:就绪性探测。如果探测失败,则k8s不会把流量转给这个容器

livenessProbe:

[root@k8s-master ~]# kubectl explain pods.spec.containers.livenessProbe
KIND:     Pod
VERSION:  v1

RESOURCE: livenessProbe <Object>

DESCRIPTION:
     Periodic probe of container liveness. Container will be restarted if the
     probe fails. Cannot be updated. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes

     Probe describes a health check to be performed against a container to
     determine whether it is alive or ready to receive traffic.

FIELDS:
   exec	<Object>
     One and only one of the following should be specified. Exec specifies the
     action to take.

   failureThreshold	<integer>
     Minimum consecutive failures for the probe to be considered failed after
     having succeeded. Defaults to 3. Minimum value is 1.

   httpGet	<Object>
     HTTPGet specifies the http request to perform.

   initialDelaySeconds	<integer>
     Number of seconds after the container has started before liveness probes
     are initiated. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes

   periodSeconds	<integer>
     How often (in seconds) to perform the probe. Default to 10 seconds. Minimum
     value is 1.

   successThreshold	<integer>
     Minimum consecutive successes for the probe to be considered successful
     after having failed. Defaults to 1. Must be 1 for liveness and startup.
     Minimum value is 1.

   tcpSocket	<Object>
     TCPSocket specifies an action involving a TCP port. TCP hooks not yet
     supported

   timeoutSeconds	<integer>
     Number of seconds after which the probe times out. Defaults to 1 second.
     Minimum value is 1. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
  • 方式1:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常
……
  livenessProbe:
     exec:
        command:
          -	cat
          -	/tmp/probe.txt
……
  • 方式2:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常。
[root@k8s-master ~]# kubectl explain pods.spec.containers.livenessProbe.tcpSocket
KIND:     Pod
VERSION:  v1

RESOURCE: tcpSocket <Object>

DESCRIPTION:
     TCPSocket specifies an action involving a TCP port. TCP hooks not yet
     supported

     TCPSocketAction describes an action based on opening a socket

FIELDS:
   host	<string>
     Optional: Host name to connect to, defaults to the pod IP.

   port	<string> -required-
     Number or name of the port to access on the container. Number must be in
     the range 1 to 65535. Name must be an IANA_SVC_NAME.

可以看到host默认是Pod的IP地址。

……
   livenessProbe:
      tcpSocket:
         port: 8080
……
  • 方式3:调用容器内web应用的URL,如果返回的状态码在200和399之前,则认为程序正常,否则不正常。
[root@k8s-master ~]# kubectl explain pods.spec.containers.livenessProbe.httpGet
KIND:     Pod
VERSION:  v1

RESOURCE: httpGet <Object>

DESCRIPTION:
     HTTPGet specifies the http request to perform.

     HTTPGetAction describes an action based on HTTP Get requests.

FIELDS:
   host	<string>
     Host name to connect to, defaults to the pod IP. You probably want to set
     "Host" in httpHeaders instead.

   httpHeaders	<[]Object>
     Custom headers to set in the request. HTTP allows repeated headers.

   path	<string>
     Path to access on the HTTP server.

   port	<string> -required-
     Name or number of the port to access on the container. Number must be in
     the range 1 to 65535. Name must be an IANA_SVC_NAME.

   scheme	<string>
     Scheme to use for connecting to the host. Defaults to HTTP.
……
   livenessProbe:
      httpGet:
         path: / #URI地址
         port: 80 #端口号
         host: 192.168.184.100 #主机地址
         scheme: HTTP #支持的协议,http或者https
……

readinessProbe:

[root@k8s-master ~]# kubectl explain pods.spec.containers.readinessProbe
KIND:     Pod
VERSION:  v1

RESOURCE: readinessProbe <Object>

DESCRIPTION:
     Periodic probe of container service readiness. Container will be removed
     from service endpoints if the probe fails. Cannot be updated. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes

     Probe describes a health check to be performed against a container to
     determine whether it is alive or ready to receive traffic.

FIELDS:
   exec	<Object>
     One and only one of the following should be specified. Exec specifies the
     action to take.

   failureThreshold	<integer>
     Minimum consecutive failures for the probe to be considered failed after
     having succeeded. Defaults to 3. Minimum value is 1.

   httpGet	<Object>
     HTTPGet specifies the http request to perform.

   initialDelaySeconds	<integer>
     Number of seconds after the container has started before liveness probes
     are initiated. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes

   periodSeconds	<integer>
     How often (in seconds) to perform the probe. Default to 10 seconds. Minimum
     value is 1.

   successThreshold	<integer>
     Minimum consecutive successes for the probe to be considered successful
     after having failed. Defaults to 1. Must be 1 for liveness and startup.
     Minimum value is 1.

   tcpSocket	<Object>
     TCPSocket specifies an action involving a TCP port. TCP hooks not yet
     supported

   timeoutSeconds	<integer>
     Number of seconds after which the probe times out. Defaults to 1 second.
     Minimum value is 1. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
  • 方式1:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常
……
  readinessProbe:
     exec:
        command:
          -	cat
          -	/tmp/probe.txt
……
  • 方式2:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常。
……
   readinessProbe:
      tcpSocket:
         port: 8080
……
  • 方式3:调用容器内web应用的URL,如果返回的状态码在200和399之前,则认为程序正常,否则不正常。
……
   readinessProbe:
      httpGet:
         path: / #URI地址
         port: 80 #端口号
         host: 192.168.184.100 #主机地址
         scheme: HTTP #支持的协议,http或者https
……

方式1:exec案例

  • 创建yaml文件
vim pod09.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod09-label
   name: pod09
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container9
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
       livenessProbe:
          exec:
            command: ["/bin/sh",'-c','cat /tmp/probe.txt']
  • 创建Pod
kubectl apply -f pod09.yaml
  • 使用describe查看pod
[root@k8s-master ~]# kubectl describe pods pod09 -n test 
Name:         pod09
Events:
  Type     Reason     Age                From                  Message
  ----     ------     ----               ----                  -------
  Normal   Scheduled  43s                default-scheduler     Successfully assigned test/pod09 to k8s-slave02
  Normal   Pulled     17s (x2 over 43s)  kubelet, k8s-slave02  Container image "nginx:1.17" already present on machine
  Normal   Created    17s (x2 over 43s)  kubelet, k8s-slave02  Created container nginx-container9
  Normal   Started    17s (x2 over 42s)  kubelet, k8s-slave02  Started container nginx-container9
  Normal   Killing    17s                kubelet, k8s-slave02  Container nginx-container9 failed liveness probe, will be restarted
  Warning  Unhealthy  7s (x4 over 37s)   kubelet, k8s-slave02  Liveness probe failed: cat: /tmp/probe.txt: No such file or directory

可以看到下面的Liveness probe failed: cat: /tmp/probe.txt: No such file or directory。

  • 我们说过存活性探测如果失败会重启Pod,我们查看一下:
[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP            NODE          NOMINATED NODE   READINESS GATES
pod09   1/1     Running   3          101s   10.244.2.24   k8s-slave02   <none>           <none>

可以看到RESTARTS为3,说明Pod被重启了3次。

方式2:tcpSocket案例

  • 创建yaml文件
vim pod10.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod10-label
   name: pod10
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container10
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
       livenessProbe:
          tcpSocket: #本质上就是访问:Pod的IP:8081
             port: 8081
  • 创建Pod
kubectl apply -f pod10.yaml
  • 我们说过存活性探测如果失败会重启Pod,我们查看一下:
[root@k8s-master ~]# kubectl describe pod pod10 -n test
Name:         pod10
Events:
  Type     Reason     Age               From                  Message
  ----     ------     ----              ----                  -------
  Normal   Scheduled  19s               default-scheduler     Successfully assigned test/pod10 to k8s-slave01
  Normal   Pulled     18s               kubelet, k8s-slave01  Container image "nginx:1.17" already present on machine
  Normal   Created    18s               kubelet, k8s-slave01  Created container nginx-container10
  Normal   Started    18s               kubelet, k8s-slave01  Started container nginx-container10
  Warning  Unhealthy  5s (x2 over 15s)  kubelet, k8s-slave01  Liveness probe failed: dial tcp 10.244.1.13:8081: connect: connection refused

可以看到下面的Liveness probe failed: dial tcp 10.244.1.13:8081: connect: connection refused。

方式3:httpGet案例

  • 创建yaml文件
vim pod11.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod11-label
   name: pod11
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container11
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
       livenessProbe:
          httpGet: # 下面的httpGet本质上就是去请求http://192.168.184.101:80/probe
            host: 192.168.184.101
            path: /probe
            port: 80
            scheme: HTTP
  • 创建Pod
kubectl apply -f pod11.yaml

和上面测试方式一样。

容器探测(高级)

livenessProbes和readinessProbes下一级可配置的选项。

  1. exec

  2. tcpSocket

  3. httpGet

    上面三个已经讲解过了

  4. initialDelaySeconds 容器启动后等待多少秒执行第一次探测

  5. timeoutSeconds 探测超时时间。默认1秒,最小1秒

  6. periodSeconds 执行探测的频率。默认是10秒,最小1秒

  7. failureThreshold 连续探测失败多少次才被认定为失败。默认是3。最小值是1

  8. successThreshold 连续探测成功多少次才被认定为成功。默认是1

Pod的重启策略
  • 当Pod启动失败时会采用重启策略,例如上面所说的存活性探测livenessProbe,当探测失败后kubernetes就会采用重启策略,重启策略有3种,分别是:
    • Always:当Pod启动失败后自动重启。(默认值)
    • OnFailure:容器终止运行且退出码不为0时重启。
    • Never:永不重启Pod。
  • Pod重启是有延迟的,不是间隔相同的时间就会重启,延迟是10s、20s、40s、80s、160s和300s,300s是最大的延迟时长。
[root@k8s-master ~]# kubectl explain pods.spec
KIND:     Pod
FIELDS:
   restartPolicy	<string>
     Restart policy for all containers within the pod. One of Always, OnFailure,
     Never. Default to Always. More info:
     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
  • 创建yaml文件
vim pod12.yaml
  • 内容如下:
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
   labels:
     app: pod12-label
   name: pod12
   namespace: test
spec:
  containers:
     - image: nginx:1.17
       name: nginx-container12
       ports:
         - name: nginx-port
           containerPort: 80
           protocol: TCP
       livenessProbe:
          httpGet: # 下面的httpGet本质上就是去请求http://192.168.184.101:80/probe
            host: 192.168.184.101
            path: /probe
            port: 80
            scheme: HTTP
  restartPolicy: Never  #永不重启Pod
  • 创建Pod
kubectl apply -f pod12.yaml
  • 查看Pod
[root@k8s-master ~]# kubectl describe pod pod12 -n test 
Name:         pod12
Events:
  Type     Reason     Age                From                  Message
  ----     ------     ----               ----                  -------
  Normal   Scheduled  42s                default-scheduler     Successfully assigned test/pod12 to k8s-slave02
  Normal   Pulled     41s                kubelet, k8s-slave02  Container image "nginx:1.17" already present on machine
  Normal   Created    41s                kubelet, k8s-slave02  Created container nginx-container12
  Normal   Started    41s                kubelet, k8s-slave02  Started container nginx-container12
  Warning  Unhealthy  10s (x3 over 30s)  kubelet, k8s-slave02  Liveness probe failed: Get http://192.168.184.101:80/probe: dial tcp 192.168.184.101:80: connect: connection refused
  Normal   Killing    10s                kubelet, k8s-slave02  Stopping container nginx-container12

可以看到最下面的Stopping container nginx-container12,说明Pod没有发生重启。

❤️💛🧡本章结束,我们下一章见❤️💛🧡

  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼打酱油

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值