1、Kubernetes资源类别

  • 工作负载型资源对象:Pod,ReplicaSet,Deployment,StatefulSet、DaemonSet、Job、CronJob
  • 服务发现及均衡资源:Service, Ingress
  • 配置及存储对象:Volume,CSI(容器存储接口,可扩展第三方存储卷),ConfigMap,Secret,Label
  • 集群资源:NameSpace,Node,Role,ClusterRole
  • 元数据资源:HPA,PodTemplate,LimitRange

K8S中所有的配置都应该通过API对象的spec来设置的,也就是用户通过配置系统的理想状态来改变系统,这是K8S重要设计理念之一,既所有的操作都是声明示(Declarative)的而不是命令式(Imperative)的,声明式操作在分布式系统中的好处是稳定,不怕丢或运行多次。所以,上面这些资源除了之前的kubectl命令创建方式,还可以使用配置清单的方式创建。

2、K8S中Pod的管理

Pod是K8S创建和管理的最小单元,一个Pod由一个或多个容器组成,同一个Pod中的容器共享存储、网络。

2.1、Pod特点

  • 同一个Pod中无论有多少容器,都始终部署在一个Node上。
  • 同一个Pod中的容器共享存储、网络。
  • Kubernetes直接管理Pod,而不管理容器。

2.2、查看Pod的资源清单

  • 在K8s中一般通过yaml文件创建资源清单,而apiserver仅接收Json格式的资源定义,通过yaml格式提供配置清单,apiserver可自动将其转为JSON格式。
  • 可使用kubectl explain pods.spec命令来查看资源清单对应对象的帮助文档。
  1. $ kubectl get pod nginx-test-65bd7df976-lrcjl -o yaml
  2. # 大部分资源类别的配置清单都应该包含以下五个部分
  3. apiVersion: v1 # api群组和版本
  4. kind: Pod # 资源类别
  5. metadata: # 元数据(嵌套字段)
  6. ...
  7. spec: # 定义目标规范(如定义容器如何创建)
  8. ...
  9. status: # 资源类别的状态(无需手动定义)
  10. ...

2.2.1、apiVersion版本
  • ApiVersion支持多个Api版本,通过分组的方式来管理版本,可通过kubectl API-versions查看。
$ kubectl api-versions
# 版本表示方式为group/version
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

2.2.2、Kind资源类别
  • Kind表示需要创建的资源类别,资源类别既上面提到的,大多是系统内置的资源类别,支持自定义。如Pod、Service等。

2.2.3、metadata元数据
  • metadata既资源的元数据
metadata:
  labels:  # 标签
    pod-template-hash: 65bd7df976
    run: nginx-test
  annotations:
  name: nginx-test-65bd7df976-lrcjl  # 资源名称,在同一个namespace中不可重名
  namespace: default # 定义名称空间
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: nginx-test-65bd7df976
    uid: 9d198fe8-658b-4683-b992-287dd45bbc8c
  resourceVersion: "156132"
  selfLink: /api/v1/namespaces/default/pods/nginx-test-65bd7df976-lrcjl  # 资源引用路径
  uid: b363f3ac-ff22-4276-862c-8be6c7014679

2.2.4、spec目标状态
  • spec是资源清单中最重要的字段,用来定义用户期望的目标状态disired state
spec:
  containers:
  - image: nginx:1.15-alpine 
    imagePullPolicy: IfNotPresent
    name: nginx-test
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-4ctfx
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: node2.larryyu.com
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: default-token-4ctfx
    secret:
      defaultMode: 420
      secretName: default-token-4ctfx

2.2.5、Status状态
  • 当前状态,由K8s集群维护,用户不能手动改变。创建时不能指定。

2.3、示例一:利用资源清单创建Pod示例

$ vim kube-test.yaml
apiVersion: v1  # 指定apiVersion版本
kind: Pod  # 指定资源类别
metadata:
  name: pod-demo
  namespace: default
  labels: # 定义资源标签
    app: myapp
    tier: frontend
    Created: liangliang.yu
spec:
  containers:
  - name: myapp # 定义第一个容器
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    - name: https
      protocol: TCP
      containerPort: 443
  - name: busybox  # 定义第二个容器
    image: busybox:latest
    command: ["/bin/sh","-c","sleep 3600"]
$ kubectl create -f kube-test.yaml  # 使用yaml文件创建资源
pod/pod-demo created
$ kubectl get pods
NAME                          READY   STATUS              RESTARTS   AGE
nginx-test-65bd7df976-lrcjl   1/1     Running             0          17h
nginx-test-65bd7df976-prqb4   1/1     Running             0          17h
nginx-test-65bd7df976-rc24n   1/1     Running             0          17h
pod-demo                      0/2     ContainerCreating   0          5s # 可以看到pod-demo正在创建,其中包含两个容器

2.4、K8S中的Label标签

Label是Kubernetes系统中的一个核心概念。
Label以key/value键值对的形式附加到各种对象上,如Pod、Service、RC、Node等。
Label定义了这些对象的可识别属性,用来对它们进行管理和选择。Label可以在创建时附加到对象上,也可以在对象创建后通过API进行管理。

2.4.1、标签组成

key=value

  • key:只能使用 字母 数字 _ - . (只能以字母数字开头,不能超过63给字符)
  • value: 可以为空 只能使用 字母 数字开头

2.4.2、定义标签
kubectl get pods --show-labels  #查看pod所有标签信息
kubectl get pods -l app  #过滤包含app的标签
kubectl get pods -L app    #过滤包含app的标签及显示值
kubectl label pods pod-demo release=canary  #给pod-demo增加标签
kubectl label pods pod-demo release=stable --overwrite  #修改标签

2.4.3、标签选择器

给资源打上标签后,可以使用标签选择器过滤指定的标签

标签选择器目前有两个:基于等值关系和基于集合关系

  • 等值关系操作符:=, == , !=
#使用格式
kubectl get pods -l run=myapp
kubectl get pods -l run=myapp --show-labels
kubectl get pods -l run!=client --show-labels
  • 集合关系的操作符:in,notin,exists
#使用格式
kubectl get pods -l "run in (client,myapp,alpha)" --show-labels   #三个值有一个匹配上都可以
kubectl get pods -l "run notin (client,myapp,alpha)" --show-labels

另外许多资源支持内嵌字段

matchLabels: 直接给定键值

matchExpressions: 基于给定的表达式来定义使用标签选择器,{key:”KEY”,operator:”OPERATOR”,values:[V1,V2,….]}

操作符: in not in:Values字段的值必须是非空列表 Exists NotExists: Values字段的值必须是空列表

2.4.4、示例二:将pod绑定在磁盘类型为ssd的节点
# 给节点打标签
$ kubectl label nodes node1.larryyu.com disktype=ssd
# 修改yaml文件,配置清单
$ vim kube-test.yaml
apiVersion: v1  # 指定apiVersion版本
kind: Pod  # 指定资源类别
metadata:
  name: pod-demo
  namespace: default
  labels: # 定义容器资源标签
    app: myapp
    tier: frontend
    Created: liangliang.yu
spec:
  containers:
  - name: myapp # 定义容器
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    - name: https
      protocol: TCP
      containerPort: 443
    command: ["/bin/sh","-c","sleep 3600"]
  nodeSelector: # 指定选择标签
    disktype: ssd

2.5、spec参数

查看pod容器spec支持的参数字段,可以使用kubectl explain pods.spec来查看spec节点下参数,或者使用kubectl explain pods.spec.containers查看spec.containers子节点参数。

  • spec节点参数说明

    # kubectl explain pods.spec
    FIELDS:
     activeDeadlineSeconds    <integer>: 表示Pod可以运行的最长时间,到达该值后,Pod会自动停止。
     affinity    <Object>: 值为对象,如果指定则表示Pod受亲和性调度影响,允许以下调度策略。
       nodeAffinity: 主机亲和度,决定Pod要部署在哪些主机
         requiredDuringSchedulingIgnoredDuringExecution: 硬策略,调度过程必须满足
         preferredDuringSchedulingIgnoredDuringExecution: 软策略,调度过程尽量满足
       podAffinity: Pod亲和度,当前Pod部署到Node上,且此node上其他pod需要满足labelSelector指定的条件
       podAntiAffinity: Pod反亲和度,当前Pod部署到Node上,且此Node上其他Pod不满足labelSelector指定的条件
     automountServiceAccountToken    <boolean>: 表示是否将服务账号默认挂载到 Pod 中,默认是 true。通过kubectl exec spring-k8s -- ls -l /var/run/secrets/kubernetes.io/serviceaccount可以查看挂载信息。
     containers    <[]Object>: 必须选项,指定容器配置,可以为多个
     dnsConfig    <Object>: 指定Pod DNS服务器地址
    
     dnsPolicy    <string>: 字符串,指定Pod中DNS策略。有四种参数
       None: 无任何策略
       Default: 默认策略
       ClusterFirst: 集群DNS优先,默认策略
       ClusterFirstWithHostNet: 集群DNS优先,如无法解析则使用宿主机网络
     enableServiceLinks    <boolean>: 表示是否将 Service 的相关信息注入到 Pod 的环境变量中,默认是 true。可以使用kubectl exec spring-k8s -- printenv|grep PG查看。
     ephemeralContainers    <[]Object>: 临时容器,一般用于容器调试或排除故障等。
     hostAliases    <[]Object>: 设置主机别名,类似修改hosts文件,默认容器中无法修改主机名。
     hostIPC    <boolean>: 使用主机的ipc名称空间,默认为false
     hostNetwork    <boolean>: 是否允许Pod共享宿主机网络的命名空间,默认为false
     hostPID    <boolean>: 是否允许Pod共享宿主机的进程空间,默认为false
     hostname    <string>: 指定Pod主机名,如果未指定,则为系统自定义值。
     imagePullSecrets    <[]Object>: 私有docker仓库,需要用户认证后,才可拉取镜像。
     initContainers    <[]Object>: 初始化容器,在应用程序容器启动前运行,可包括一些应用程序中不存在的脚本和工具,来完成初始化工作,初始化完成后,此容器退出。
     nodeName    <string>: 指定Node节点名称,将Pod指定调度到指定Node上,不经过调度器,不受Taint限制。
     nodeSelector    <map[string]string>: 节点选择器,通过label标签等将Pod调度到符合条件的节点上。
     overhead    <map[string]string>: 启用Pod资源限制
     preemptionPolicy    <string>: 
     priority    <integer>: Pod资源使用优先级,值越高,优先级越高
     priorityClassName    <string>: Pod资源使用优先级类别,当节点没有足够资源调度Pod,Pod处于pending时,抢占逻辑触发,会尝试从一个节点删除优先级低的Pod,从而释放资源部署高优先级Pod。
          low-priority: 低优先级
       high-priority: 高优先级
     restartPolicy    <string>: pod重启策略,当容器异常退出或健康检测失败,kubelet根据此策略设置进行相应操作。
       Always: 当容器失效时,由kubelet自动重启
       OnFailure: 当容器终止运行且退出码不为0时,重启
       Never: 无论同期运行状态如何,都不重启
       # kubelet重新启动的已退出容器将以指数退避延迟(10秒,20秒,40秒......)重新启动,上限为五分钟,并在成功执行十分钟后重置
     schedulerName    <string>: 如果指定,将由指定的调度程序调度,如果不指定,则使用默认调度程序。
     securityContext    <Object>: Pod级别安全上下文,对内部所有容器均有效
       runAsUser: 以指定用户运行容器进程,默认由镜像中USER指定
       runAsGroup: 以指定用户组运行容器进程
       supplementalGroups: 为容器中1号进程附加一个附加组
       fsGroup: 为容器中1号进程附加一个专用组,功能类似于sgid
       runAsNoRoot: 是否以ROOT用户运行
       seLinuxOptions: Selinux配置
       sysctls: 应用到当前Pod上的名称空间级别的sysctl参数设置
       windowsOptions:  windows专用设置
     serviceAccount    <string>: 不推荐,改用serviceAccountName
     serviceAccountName    <string>: 用于运行此服务的ServiceAccount的名称
     setHostnameAsFQDN    <boolean>: 如果为true,pod的主机名将配置为pod的FQDN,默认为false
     shareProcessNamespace    <boolean>: 表示 Pod 中的容器需要共享命名空间。设置为true后,容器内启动进程PID不为1.
     terminationGracePeriodSeconds    <integer>: 定义优雅关闭的宽限期,即收到停止请求后,有多少时间释放资源,如果到了时间没有停止,则会强制结束。
     tolerations    <[]Object>: 指定Pod可以接受的污点
     topologySpreadConstraints    <[]Object>: 表示拓扑分布约束,可以控制 Pod 在某些节点的分布。
     volumes    <[]Object>: 存储卷设置
       emptyDir: 临时存储,当Pod从Node上删除后,emptyDir也同时删除。
       hostPath: 允许挂载宿主机上的文件系统到Pod里面去,数据保存在宿主机上
       gcePersistentDisk: 可以挂载GCE上的永久磁盘到容器,需要Kubernetes运行在GCE的VM中。
       awsElasticBlockStore: 可以挂载AWS上的EBS盘到容器,需要Kubernetes运行在AWS的EC2上。
       NFS: 将nfs等网络共享存储挂载到Pod中
    
  • spec.containers节点参数说明 ```yaml

    kubectl explain pods.spec.containers

    FIELDS: name : 字符串,指定pod名称 image : 字符串,指定镜像的路径 imagePullPolicy : 字符串,镜像的下载策略。有三种:

      Always(总是去仓库下载) 
      Never(从不去仓库下载) 
      IfNotPresent(如果本地没有就去仓库下载) 
      默认是"IfNotPresent"  但是,如果镜像的标签是latest,则总会是"Always"
    

    ports <[]Object>: 对象列表,容器公开的端口列表。在这里公开端口可以为系统提供关于容器使用的网络连接的额外信息,但主要是提供信息。在这里不指定端口不会阻止该端口被公开。

      name: 定义端口名称
      protocol: 端口协议,默认为TCP
      containerPort: 端口地址
    

    command <[]string>: 运行的程序,类似于docker中的entrypiont,并且这里的命令不会运行在shell中,如果没有这个字段docker镜像会运行自己entrypiont中的指令 args <[]string>: 向docker镜像中传递参数 如果定义了这个字段,docker镜像中cmd命令不会被执行,如果引用变量使用$(VAR_NAME)格式引用,如果想使用命令引用的的方式,需要使用$$(VAR_NAME)方式来引用 env: 配置环境变量 envFrom <[]Object>: lifecycle : pod中容器的生命周期,可以使用lifecycle来管理容器在运行前和关闭前的一些动作

      postStart: 容器创建成功后,运行前的任务,用于资源部署、环境准备等。
      preStop: 在容器被终止前的任务,用于优雅关闭应用程序、通知其他系统等等。 
    

    livenessProbe: 来确定何时重启容器 exec: 命令探针 httpGet: http get探针 tcpSocket: tcp socket探针 initialDealySeconds: 发起初次探测请求的延后时长 preiodSeconds: 请求周期 timeoutSeconds: 超时时长 successThreshold: 成功阈值,失败转为成功几次认为成功。 failureThreshold: 失败阈值 readinessProbe: 来确定容器是否已经就绪可以接受流量 securityContext : 容器级别安全上下文,对内部所有容器均有效 runAsUser: 以指定用户运行容器进程,默认由镜像中USER指定 runAsGroup: 以指定用户组运行容器进程 runAsNoRoot: 是否以ROOT用户运行 allowPrivilegeEscalation: 是否允许特权升级 capabilities: 于当前容器上添加或删除内核功能

     add: 添加由列表定义的各内核功能
     drop: 移除由列表定义的各内核功能
    

    privileged: 是否运行为特权容器 procMount: 设置容器的procMount类型,默认为DefaultProcMount readOnlyRootFilesystem: 是否将跟文件系统设置为只读模式 seLinuxOptions: Selinux配置 sysctls: 应用到当前Pod上的名称空间级别的sysctl参数设置 windowsOptions: windows专用设置

    
    <a name="89f4f668"></a>
    ##### 2.5.1、spec中command和args
    
    关于args和command的官方文档链接:[https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/)
    
    | Description | Docker中字段名 | Kubernetes中字段名 |
    | --- | --- | --- |
    | The command run by the container | Entrypoint | command |
    | The arguments passed to the command | Cmd | args |
    
    
    - 如果配置清单既没有提供command和args,则运行镜像中的Entrypoint和cmd
    - 如果提供了command但没有提供args,则只运行配置清单中的command,镜像中的Entrypoint和cmd均被忽略。
    - 如果只提供了args,则运行镜像中的Entrypoint和配置清单中的args,镜像中的Cmd将被忽略。
    - 如果同时提供command和args,则运行配置清单中的command和args,镜像中的Entrypoint和cmd均被忽略。
    | Image Entrypoint | Image Cmd | Container command | Container args | Command run |
    | --- | --- | --- | --- | --- |
    | `[/ep-1]` | `[foo bar]` |  |  | `[ep-1 foo bar]` |
    | `[/ep-1]` | `[foo bar]` | `[/ep-2]` |  | `[ep-2]` |
    | `[/ep-1]` | `[foo bar]` |  | `[zoo boo]` | `[ep-1 zoo boo]` |
    | `[/ep-1]` | `[foo bar]` | `[/ep-2]` | `[zoo boo]` | `[ep-2 zoo boo]` |
    
    
    <a name="1d8a8e6e"></a>
    #### 2.6、Pod健康检查和生命周期
    
    k8s管理支持pod生命周期管理,在资源清单中,在pods.spec.containers下有lifecycle.
    
    创建资源对象时,可以使用lifecycle来管理容器在运行前和关闭前的一些动作。
    
    lifecycle有两种回调函数:
    
    - PostStart:容器创建成功后,运行前的任务,用于资源部署、环境准备等。
    - PreStop:在容器被终止前的任务,用于优雅关闭应用程序、通知其他系统等等。
    
    <a name="3fb28911"></a>
    ##### 2.6.1、示例三:Pod生命周期示例
    
    ```yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: lifecycle-demo
    spec:
      containers:
      - name: lifecycle-container
        image: nginx
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo 'Hello Nginx Page' > /var/log/nginx/index.html"]
          preStop:
            exec:
              command: ["/bin/sh", "-c", "nginx -s quit; while killall -0 nginx; do sleep 1; done"]
    

    Kubernetes 在容器创建后立即发送 postStart 事件。然而,postStart 处理函数的调用不保证早于容器的入口点(entrypoint) 的执行。postStart 处理函数与容器的代码是异步执行的,但 Kubernetes 的容器管理逻辑会一直阻塞等待 postStart 处理函数执行完毕。只有 postStart 处理函数执行完毕,容器的状态才会变成 RUNNING。

    2.7、状态探测

    K8s中Pod状态监测主要分为两种,同时支持三种探测行为

    2.7.1、liveness probe存活探针

    来确定何时重启容器,当应用程序处于运行状态但无法做进一步操作,liveness探针将捕获到deadlock,重启处于该状态下的容器

    • exec:在容器内执行命令。返回状态0为成功
    • httpGet:访问容器的http服务,可以指定httpHeaders。返回200-400范围为成功
    • tcpSocket:访问容器的TCP端口,TCP Socket建立为成功

    2.7.2、readiness probe就绪探针

    来确定容器是否已经就绪可以接受流量,只有当Pod中的容器都处于就绪状态时kubelet才会认定该Pod处于就绪状态。该信号的作用是控制哪些Pod应该作为service的后端。如果Pod处于非就绪状态,那么它们将会被从service的load balancer中移除。

    • exec:在容器内执行命令。返回状态0为成功
    • httpGet:访问容器的http服务,可以指定httpHeaders。返回200-400范围为成功
    • tcpSocket:访问容器的TCP端口,TCP Socket建立为成功
      2.7.3、startup probe启动探针
      用来确认容器是否启动就绪,只有startup probe探测通过后才会进入liveness probe和readiness probe探针。

    2.7.3、示例四:Pod状态探测
    # 创建livenessprobe并使用exec监测
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: liveness
      name: liveness-exec
    spec:
      containers:
      - name: liveness-demo
        image: busybox
        args: ["/bin/sh", "-c", "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"]
        livenessProbe:  # 检测失败后重启容器
          exec:  # 执行命令探测
            command: ["cat", "/tmp/healthy"]
          initialDelaySeconds: 5   # Pod启动多久时间后进行健康检查,单位秒
          periodSeconds: 5    # 探测周期,单位秒
    
    # 创建livenessprobe并使用httpGet监测     
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: liveness
      name: liveness-http
    spec:
      containers:
      - name: liveness
        image: k8s.gcr.io/liveness
        args:
        - /server
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            httpHeaders:
            - name: Custom-Header
              value: Awesome
          initialDelaySeconds: 3
          periodSeconds: 3
     # 定义readiness探针
     readinessProbe:  # 检测失败后删除容器
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5
    

    2.7.4、配置Probe

    Probe中有很多精确和详细的配置,通过它们能准确的控制liveness和readiness检查:

    • initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
    • periodSeconds:执行探测的频率。默认是10秒,最小1秒。
    • timeoutSeconds:探测超时时间。默认1秒,最小1秒。
    • successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
    • failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。

    HTTP probe中可以给 httpGet设置其他配置项:

    • host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置”Host”而不是使用IP。
    • scheme:连接使用的schema,默认HTTP。
    • path: 访问的HTTP server的path。
    • httpHeaders:自定义请求的header。HTTP运行重复的header。
    • port:访问的容器的端口名字或者端口号。端口号必须介于1和65535之间。

    2.8、Pod中资源共享

    Docker中两个不同的容器因为命名空间的隔离是不可以互相访问存储和网络的,而同一个Pod中的多个容器存储与网络默认可以共享,这是由K8S实现的。

    2.8.1、存储共享

    存储共享通过emtryDir实现

    apiVersion: v1
    kind: Pod
    metadata:
      name: two-containers
    spec:
      restartPolicy: Never
      volumes:   # 创建存储卷名称为shared-data,类型为emptyDir
      - name: shared-data
        emptyDir: {}
      containers:
      - name: nginx-container
        image: nginx
        volumeMounts:  # nginx容器使用存储卷,并挂载到/usr/share/nginx/html
        - name: shared-data
          mountPath: /usr/share/nginx/html
      - name: debian-container
        image: debian
        volumeMounts:  # debian容器页使用存储卷,并挂载到/pod-data中,且在启动后运行args命令后终止。
        - name: shared-data
          mountPath: /pod-data
        command: ["/bin/sh"]
        args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]
    
    # debian容器退出后,nginx容器还在继续运行,而debian容器运行的args命令会写入存储卷,因此此时通过curl localhost向nginx发起请求,会得到echo Hello from the debian container的返回
    

    2.8.2、网络共享

    网络共享通过infra Container实现,不同 container 之间通过 infra container 的方式统一识别外部网络空间。

    2.9、Pod环境变量

    创建Pod时,可以为其中的容器设置环境变量,实现容器内应用程序获取Pod信息,容器内通过环境变量改变默认行为等。通过配置文件的 env 或者 envFrom 字段来设置环境变量。

    2.9.1、定义变量的方式
    • 自定义变量值
    apiVersion: v1
    kind: Pod
    metadata:
      name: envar-demo
      labels:
        purpose: demonstrate-envars
    spec:
      containers:
      - name: envar-demo-container
        image: gcr.io/google-samples/node-hello:1.0
        env:  # 设置自定义变量
        - name: Node_Name
          value: "K8s-Slave1"
        - name: NameSpace
          value: "default"
        command: ["echo"]
        args: ["$(Node_Name) $(NameSpace) $(NAME)"]   # 在args中使用变量
    

    通过kubectl exec envar-demo -- printenv查看Pod中的环境变量。

    • 从Pod属性中获取
    env:
      - name: MY_NODE_NAME   # 从spec.nodename获取变量值
        valueFrom:
          fieldRef:
            fieldPath: spec.nodename
    
    • 从Container属性中获取
    env:
      - name: MY_CPU_REQUEST  # 从requests.cpu获取变量值
        valueFrom:
          resourceFieldRef:
            containerName: test-container
            resource: requests.cpu
    
    • 从Secret、ConfigMap获取

    2.10、Init Container

    用于初始化工作,一般用来执行一次性任务,比如检查环境检查(确保应用容器依赖的服务启动后再启动应用容器)或初始化配置(给应用容器准备配置文件。)有以下特点:

    • 不支持健康检查和生命周期管理
    • 在应用容器前执行

    如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 “Never”,并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。

    2.10.1、示例:创建initContainer
    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp-pod
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: busybox:1.28
        command: ['sh', '-c', 'echo The app is running! && sleep 3600']
      initContainers:
      - name: init-myservice
        image: busybox:1.28
        command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
      - name: init-mydb
        image: busybox:1.28
        command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
    

    示例中创建后会等待第一个myservice启动完成,在等待第二个mydb启动完成,然后再启动应用容器。

    2.11、静态Pod

    2.11.1、静态Pod特点
    • 静态 Pod 在指定的节点上由 kubelet 守护进程直接管理,不需要API服务器监管。
    • 静态 Pod 永远都会绑定到一个指定节点上的 Kubelet。
    • 不能使用控制器。

    2.11.2、创建静态Pod

    声明式yaml文件无需apply,只需将文件放置在 Kubelet 配置文件 的 staticPodPath: <目录> 字段下即可

    cat /var/lib/kubelet/config.yaml
    ...
    staticPodPath: /etc/kubernetes/manifests
    ...
    

    kubelet 会定期的扫描这个文件夹下的 YAML/JSON 文件来创建/删除静态 Pod。 注意 kubelet 扫描目录的时候会忽略以点开头的文件。

    # 示例
    vim /etc/kubelet.d/static-web.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: static-web
      labels:
        role: myrole
    spec:
      containers:
        - name: web
          image: nginx
          ports:
            - name: web
              containerPort: 80
              protocol: TCP
    

    创建后kubelet会自动创建此Pod,使用kubectl get pod可以看到static-web-NodeName的Pod被创建。

    2.11.3、删除静态Pod

    使用kubectl执行删除Pod操作,虽然提示删除完成,但并不会删除静态Pod。

    # 调用API服务删除pod
    $ kubectl delete pod static-web-my-node1
    pod "static-web-my-node1" deleted
    # 并不能删除静态Pod
    $ kubectl get pods
    NAME                       READY     STATUS    RESTARTS   AGE
    static-web-my-node1        1/1       Running   0          12s
    

    手动停止docker容器,静态Pod会被kubelet自动重启。因此如果想删除静态Pod,只需要把yaml文件从配置目录移除,kubelet会在下次扫描时删除静态Pod。