• (K8s学习笔记五)Pod的使用详解


    1.Pod用法

    K8s里使用的容器不能使用启动命令是后台执行程序,如:nohup ./start.sh &,该脚本运行完成后kubelet会认为该Pod执行结束,将立刻销毁该Pod,如果该Pod定义了RC/RS,则执行完该脚本,系统监控会认为该Pod已经终止,之后根据RC/RS定义中的副本数量生成一个新的Pod,一旦创建新的Pod,就在执行完启动命令后陷入无限循环的过程中,所以,K8s里使用的容器只能是前台命令作为启动命令。对于无法改为前台执行的应用,可以使用Supervisor工具辅助进行前台运行。

    一个Pod由两个容器应用为紧耦合示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-tomcat
      labels:
        name: test
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
      - name: tomcat
        image: tomcat:latest
        ports:
        - containerPort: 8080

     属于同一个Pod的多个容器应用间相互访问仅需通过localhost,一个Pod里多个容器时kubectl get pods时READY会按容器数量显示值,例如上例会显示2/2

    2.创建静态Pod

    静态Pod是由kubelet进行创建和管理的仅存放于特定的Node上的Pod,不能通过API Server管理,无法与RC/RS、Deployment或DaemonSet进行关联,且kubelet无法对它们进行健康检查。

    1)配置文件方式:需设置kubelet启动参数"--config",指定kubelet需要监控的配置文件所在目录,kubelet会定期扫描该目录,并根据目录下的.yaml或.json文件进行创建,例如,配置文件目录/opt/files,配置启动参数"--config=/opt/files",在该目录下放入.yaml文件。

    静态Pod在Master上执行删除会显示Pending状态,且不会被真正删除,只能到该Pod所在的Node上将其.yaml或.json文件从扫描目录下删除即可。

    2)HTTP方式:需设置kubelet启动参数"--manifest-url",kubelet将定期从该url地址下载Pod的定义文件,并以.yaml或.json的格式进行解析,然后创建Pod,删除方方法通配置文件方式。

    3.Pod容器共享Volume

    同一个Pod中的多个容器能共享Pod级别的存储卷Volume,如例:

    apiVersion: v1
    kind: Pod metadata: name: nginx
    -busybox labels: name: test spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 volumeMounts: - name: app-logs mountPath: /var/log/nginx - name: busybox image: busybox:latest command: ["sh","-c","tail -f /logs/access.log"] volumeMounts: - name: app-logs mountPath: /logs volumes: - name: app-logs emptyDir: {}

    # 查看busybox容器的输出
    kubectl logs nginx-busybox -c busybox

    # 登录nginx容器进行查看
    kubectl exec -it nginx-busybox -c nginx -- ls /var/log/nginx/access.log
    kubectl exec -it nginx-busybox -c nginx -- tail /var/log/nginx/access.log

    定义的Volume名为app-logs,挂载到nginx容器内的/var/log/nginx目录,同时挂载到busybox容器的/logs目录,nginx容器启动后会想/var/log/nginx目录里写入文件,busybox容器就可读取其中的文件。

    4.configMap使用

    configMap的用法

    • 生成为容器内的环境变量
    • 设置容器启动命令的启动参数(需设置为环境变量)
    • 以Volume的形式挂载为容器内部的文件或目录

    1)通过YAML文件方式创建

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cm-appconfig
    data:
      apploglevel: info
      appdatadir: /var/log/data
    
    # 创建该ConfigMap
    kubectl create -f cm-appconfig.yaml
    
    # 查看该ConfigMap
    kubectl get configmap
    kubectl describe configmap cm-appconfig
    
    # 以yaml形式输入详细内容
    kubectl get configmap cm-appconfig -o yaml
    
    # 将两个配置文件server.xml和logging.properties定义为ConfigMap的用法,设置key为配置文件的别名,value则是配置文件的全部文本内容
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cm-configfiles
    data:
      key-serverxml: |
        .............
      key-loggingproperties: | 
        ...........

    2)通过kubectl命令行方式创建

    通过kubectl create configmap创建,可使用参数--from-file或--from-literal指定内容,且可以在一行命令中指定多个参数

    # 通过--from-file参数从文件中进行创建,可以指定key的名称,也可以在一个命令行创建包含多个key的ConfiMap
    kubectl create configmap {NAME} --from-file=[key=]source --from-file=[key=]source
    
    # 通过--from-file参数从目录中进行创建,该目录下的每个配置文件名都被设置为key,文件的内容被设置为value
    kubectl create configmap {NAME} --from-file={config file dir}
    
    # 使用--from-literal时会从文本中进行创建,直接将指定的key#=value#创建为ConfigMap的内容
    kubectl create configmap {NAME} --from-literal={key1}={value1} --from-literal={key2}={value2} 
    
    # 示例:
    在当前目录下含有server.xml时
    kubectl create configmap cm-server.xml --from-file=server.xml
    kubectl describe configmap cm-server.xml
    
    在/opt/configfiles目录下包含两个文件server.xml和logging.properties时
    kubectl create configmap cm-appconf --from-file=/opt/configfiles
    kubectl describe configmap cm-appconf
    
    使用from-literal参数创建
    kubectl create configmap cm-appenv --from-literal=loglevel=info --from-literal=appdatadir=/var/log/data

    5.在Pod中使用configMap

    1)通过环境变量的方式使用

    # vi cm-appconfig.yaml    # 创建ConfigMap
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cm-appconfig
    data:
      apploglevel: info
      appdatadir: /opt/data
    
    # vi test-pod.yaml        # 创建Pod
    apiVersion: v1 
    kind: Pod
    metadata:
      name: test-pod
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command: ["bin/sh", "-c", "env | grep APP"]
        env:
        - name: APPLOGLEVEL     # 定义环境变量名称
          valueFrom:            # key "apploglevel"对应的值
            configMapkeyRef:
              name: cm-appconfig     # 环境变量的值取自cm-appconfig
              key: apploglevel       # key为apploglevel
        - name: APPDATADIR      # 定义环境变量的名称
          valueFrom:            # key "appdatadir"对应的值
            configMapKeyRef:
              name: cm-appconfig     # 环境变量的值取自cm-appconfig
              key: appdatadir        # key为appdatadir
    
    或着使用自动生成环境变量的方法
    # vi test-pod.yaml        # 创建Pod
    apiVersion: v1 
    kind: Pod
    metadata:
      name: test-pod
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command: ["bin/sh", "-c", "env | grep APP"]
        envFrom:                  # 根据cm-appconfig中的key=value自动生成环境变量 
        - configMapRef:
          name: cm-appconfig  

    2)通过volumeMount使用ConfigMap

    在ConfigMap文件中包含两个定义文件server.xml和logging.properties
    # vi cm-appconfig.yaml    # 创建ConfigMap
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cm-appconfig
    data:
      key-serverxml: |
      ...........
      key-loggingproperties: .......
    
    将ConfigMap中的内容以文件的形式mount到容器内部的/config_files目录下
    # vi test-pod.yaml        # 创建Pod
    apiVersion: v1 
    kind: Pod
    metadata:
      name: test-pod
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command: ["bin/sh", "-c", "env | grep APP"]
        volumeMounts:
        - name: serverxml             # 引用volume的名称
          mountPath: /config_files    # 挂载到容器内的目录
      volumes:
      - name: serverxml               # 定义volume的名称
        configMap:
          name: cm-appconfig          # 使用ConfigMap文件
          items:
          - key: key-serverxml        # key=key-serverxml
            path: server.xml          # value将server.xml文件名进行挂载
          - key: key-loggingproperties
            path: logging.properties
    
    或者不指定items,在容器内的目录下为每个item都生成一个文件名为key的文件
    # vi test-pod.yaml        # 创建Pod
    apiVersion: v1 
    kind: Pod
    metadata:
      name: test-pod
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command: ["bin/sh", "-c", "env | grep APP"]
        volumeMounts:
        - name: serverxml             # 引用volume的名称
          mountPath: /config_files    # 挂载到容器内的目录
      volumes:
      - name: serverxml               # 定义volume的名称
        configMap:
          name: cm-appconfig          # 使用ConfigMap文件
    
    此时在容器内的/config_files目录下会生成key-serverxml和key-loggingproperties两个key文件,内容为ConfigMap文件中的value值

    注:ConfigMap文件必须在创建Pod文件前创建;ConfigMap只能在同一Namespace中使用;静态Pod不能使用ConfiMap;ConfigMap挂载到容器内的指定目录时会覆盖目录内的其他问题,如要保留挂载目录的原文件,可将ConfigMap先挂载到临时目录,然后通过启动脚本cp或link命令到指定目录中。

    6.在Pod容器内部或得Pod名称、Pod IP、所在Namespace等信息(Downward API)

    1)环境变量注入方式

    将Pod信息(Pod IP、名称和所在Namespace)注入为环境变量
    # dapi-pod-vars.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: dapi-pod-vars
    spec:
      containers:
        - name: busybox
          image: busybox:latest
          command: ["/bin/sh", "-c", "env"]
          env:
            - name: MY_POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name     # 获取生成Pod后的name
            - name: MY_POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace   # 获取Pod所在的namespace
            - name: MY_POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP      # 获取生存Pod后Pod IP
    
    将容器的资源请求和限制信息注入到容器的环境变量中
    # dapi-pod-vars.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: dapi-pod-vars
    spec:
      containers:
        - name: busybox
          image: busybox:latest
          command: ["/bin/sh", "-c"]
          args:
          - while true; do
              echo -en '
    ';
              printenv MY_CPU_REQUEST MY_CPU_LIMIT;
              printenv MY_MEM_REQUEST MY_MEM_LIMIT;
              sleep 3600;
            done;
          resources:
            requests:
              memory: "16Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "800m"
          env:
            - name: MY_CPU_REQUEST
              valueFrom:
                resourceFieldRef:
                  containerName: busybox
                  resource: requests.cpu         # 获取容器CPU的请求值
            - name: MY_CPU_LIMIT
               valueFrom:
                resourceFieldRef:
                  containerName: busybox
                  resource: limits.cpu           # 获取容器CPU的限制值
            - name: MY_MEM_REQUEST
              valueFrom:
                resourceFieldRef:
                  containerName: busybox
                  resource: requests.memory      # 获取容器内存的请求值
            - name: MY_MEM_LIMIT
               valueFrom:
                resourceFieldRef:
                  containerName: busybox
                  resource: limits.memory        # 获取容器内存的限制值

    2)Volume挂载注入方式

    将Pod的Label、Annotation声明通过Volume挂载为容器中的一个文件,容器使用echo命令将文件内容输出
    # dapi-pod-volume.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: dapi-pod-volume
      labels:
        zone: test-zone01
        cluster: test-cluster
        rack: rack-01
      annotations:
        build: one
        builder: jason
    spec:
      containers:
        - name: busybox
          image: busybox:latest
          command: ["/bin/sh", "-c"]
          args:
          - while true; do 
              if [[ -e /etc/labels ]]; then 
                echo -en '
    
    '; cat /etc/labels; fi;
              if [[ -e /etc/annotations ]]; then 
                echo -en '
    
    '; cat /etc/annotations; fi;
              sleep 3600;
            done;
          volumeMounts:
            - name: pod-info
              mountPath: /etc
              readOnly: false
      volumes:
        - name: pod-info
          downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels   # 获取容器metadata.labels的信息
              - path: "annotations"
                fieldRef:
                  fieldPath: metadata.annotations   # 获取容器metadata.annotations的信息
    系统根据items.path的名称在
    /etc目录下生成文件

    7.Pod的生命周期和重启策略

    1)Pod的状态说明:

    • Pending:创建Pod后,在Pod内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程
    • Running:Pod内所有容器均已创建,且至少有一个容器处于正在运行或正在重启状态
    • Succeeded:Pod内所有容器均成功执行后退出,且不会再重启
    • Failed:Pod内所有容器均已退出,但至少有一个容器退出失败
    • Unknown:由于某种原因无法获取该Pod的状态,可能由于网络不畅导致

    2)Pod的重启策略(RestartPolicy)

    • Always:当容器失败时,由kubelet自动重启该容器
    • OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器
    • Never:不论容器运行状态如何,kubelet都不会重启该容器

    3)每种控制器对Pod重启策略的要求

    • RC/RS和DaemonSet:必须设置为Always,需要保证该容器持续运行
    • Job:OnFailure或Never,确保容器执行完成后不再重启
    • kubelet:在Pod失效时自动重启,不论RestartPolicy设为何值,且也不会对Pod进行健康检查

    8.Pod健康和服务可用性检查

    1)kubelet诊断容器健康状态探针

    • LivenessProbe探针:用于判断容器是否是Running状态,如果不是则kubelet会杀掉该容器,并根据RestartPolicy值处理容器。如果容器不包含此探针,那么kubelet认为该容器LivenessProbe返回值永远是Success
    • ReadinessProbe探针:用于判断容器是否时Ready状态,如果在运行中Ready状态变为False,则系统自动将其从Service的后端Endpoint列表中隔离出去,后续再把恢复Ready状态的Pod加回后端Endpoint列表,这样就能保证访问Service是流量不会被转发到不可用的Pod上

    2)LivenessProbe和ReadinessProbe可配置三种实现方式

    1.ExecAction方式:在容器内部执行一条命令,如果该命令的返回码为0,则表明容器健康
    apiVersion: v1 
    kind: Pod
    metadata:
      name: liveness-exec-test
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        args:
        - /bin/sh
        - -c 
        - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 300;
        livenessProbe:
          exec:
            command:
            - cat 
            - /tmp/health 
          initialDelaySeconds: 15    # 启动容器后进行首次chk的等待时间,单位s
          timeoutSeconds: 1          # 健康检查发送请求后等待响应的超时时间,单位s,如超级,kubelet会认为容器无法服务,将会重启容器
    cat /tmp/health命令判读容器状态,在Pod运行后,创建完/tmp/health文件后10s将其删除,livenessProbe的探测时间initialDelaySeconds为15s,探测结果Ready
    
    2.TCPsocketAction方式:通过容器的IP和Port执行TCP检查,如果能建立TCP连接,则表明容器健康
    apiVersion: v1 
    kind: Pod
    metadata:
      name: healthcheck-test
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        livenessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 15 # 每隔15s chk容器内localhost:80,如存活则表明容器健康
          timeoutSeconds: 1
    
    3.HTTPGetAction方式:通过容器的IP、Port和路径调用HTTP Get方式,如果返回码>=200且<400,则认为容器健康
    apiVersion: v1 
    kind: Pod
    metadata:
      name: healthcheck-test
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
          - containerPort: 80
          livenessProbe:
            httpGetL:
              path: /chk_test/test.html
              port: 80
            initialDelaySeconds: 15 # 每隔15s chk容器内localhost:80/chk_test/test.html,如返回码200则表明容器健康
            timeoutSeconds: 1
    一入运维深似海,从此不见彼岸花
  • 相关阅读:
    从零开始学JavaScript(一)- 理解函数
    Mootools--学习笔记(1)
    JS详解Date应用+定时器原理+计时器案例
    原生JS写伪验证码(加详细注释)~~~~~~~~~~~~~~~~
    详解JavaScript字符串!!!!!!!!和相关demo详解
    模拟children方法,实现获取指定元素下元素节点!
    关于数组去重的两种写法的思想!!!!!!
    冒泡排序的写法!!!!!
    开始写博客啦,不为出名,只为记录点滴的学习日常,留给未来的的自己
    跨平台渲染框架尝试
  • 原文地址:https://www.cnblogs.com/cn-jasonho/p/13285562.html
Copyright © 2020-2023  润新知