K8s Pod和namespace

作者: AlienPaul | 来源:发表于2020-02-03 17:28 被阅读0次

    什么是Pod

    Pod是Kubernetes中可以创建和部署的最小单位。

    Pod为一个或多个container的组合,K8s为了便于管理container,将他们封装为pod。

    Pod的特点

    Pod的特点:

    • Pod包含1到多个container
    • 同一Pod中的container只会运行在同一个节点中。不可能跨节点。

    每个container只运行一个应用进程。如果应用包含多个进程,需要使用多个container。Pod将这些相关的container组合到一起。

    一个Pod中的所有container:

    • 使用同一个namespace
    • 共享同一个hostname和网络接口
    • 文件系统完全隔离,不共享

    同一pod的container如果绑定同一个端口会存在端口冲突。但不同的pod中的container不会存在此问题。

    pod是kubernetes管理的最小单位。pod当然也是应用水平扩展(运行多个实例)时的最小单位。

    多层应用需要拆分到多个pod。

    同一个pod包含的container用途需要紧密相关。

    pod没有自愈能力,也没有横向扩展能力。因此生产中pod需要和controller配合使用。

    在K8s中,pod被认为是一种临时的对象。

    数据卷(volume)和pod具有相同的生命周期,如果pod删除后重新创建,这个pod关联的数据卷也会删除并重建。

    网络

    每一个pod分配一个独立的IP地址。同一个pod使用同一个网络namespace。位于同一个pod内的所有container都是用相同的网络namespace,包括IP地址和端口号。这些container可以通过localhost的方式访问其他的container。

    存储

    可以为pod指定一个或多个共享的数据卷(volume)。pod内的所有container都可以访问这个数据卷。

    Pod终止过程

    以pod的删除过程为例说明下pod是终止过程。

    1. 用户发出删除pod指令,默认pod删除宽限时间为30秒。
    2. API server中该pod的状态被更新。Pod在宽限时间之后会被认为dead。
    3. Pod进入Terminating状态。
    4. 和步骤3同时进行。当kubelet发现API server中Pod被标记为terminating,开始终止pod的过程。如果pod定义了preStop hook,调用preStop hook的逻辑。如果preStop过程在宽限时间到之后仍在运行,稍后步骤运行,并多出2秒宽限时间。接下来发送TERM信号到container。
    5. 和步骤3同时进行。pod从endpoint中移除。service不会再转发流量到这个pod。并且controller不再认为这个pod处于运行状态。
    6. 当宽限时间到达之时,发送SIGKILL指令到pod中所有进程。
    7. Kubelet完成删除pod过程,告诉API server设置宽限时间为0,意味着立即删除。Pod消失,再也不会被客户端查询到。

    可以使用

    kubectl delete pod ... --grace-period=<seconds>
    

    覆盖默认的宽限时间。

    可以使用如下命令强制删除pod

    kubectl delete pod ... --grace-period=0 --force
    

    Pod描述文件模板

    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp-pod
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: busybox
        command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    
    apiVersion: v1
    kind: Pod
    metadata:
        name: kubia-manual
    spec:
        containers:
            - image: luksa/kubia
              name: kubia
              ports:
              - containerPort: 8080
                protocol: TCP
    

    注意:修改pod template不会对已经创建出的pod生效。

    Pod Phase

    PodStatus(pod 状态)具有一个phase字段。

    PodPhase的可能值和解释:

    描述
    Pending k8s已接收到,但是container没有被创建。pod被调度或者在下载镜像的时候也是Pending状态
    Running pod被分配到某个node,pod中所有container都被创建。至少一个container在运行中,或者处于启动中,重启中状态
    Succeeded pod中所有的container以succeeded状态结束,不会再重启
    Failed 所有的container已终止运行,其中至少一个container以failed状态结束
    Unknown 无法获取pod状态,典型的情况为和pod所在主机通信异常

    Pod Condition

    PodStatus有一个PodConditions字段。该字段是一个数组,有如下6个部分:

    • lastProbeTime: 上一次更新pod情况的时间。
    • lastTransitionTime: 上一次pod状态变更的时间。
    • message: 状态变更的详细描述。
    • reason: 一个驼峰命名的单词描述上次状态变更的原因。
    • status: True False或Unknown。
    • type: 有如下值
      • PodScheduled: pod被调度到了node
      • Ready: pod可以接受请求。归service的负责均衡管理。
      • Initialized: 所有的init container启动成功。
      • Unschedulable: pod无法被调度,比如说资源不足或其他原因。
      • ContainersReady: 所有的container启动成功。

    Container probes

    Probe是kubelet针对container周期性触发的诊断操作。Kubelet调用container的handler进行诊断操作。Handler有如下三种类型:

    • ExecAction: 在container执行特定命令。命令的退出状态码为0会被人为诊断无异常。
    • TCPSocketAction: 发送TCP请求。如果目标端口开放则诊断无异常。
    • HTTPGetAction: 发送HTTP GET请求。返回200到400之间(包括200)的状态码表示诊断无异常。

    Probe有3种:

    • livenessProbe: 检查container是否在运行。如果liveness probe失败,kubelet会kill掉container。接下来container会根据restartPolicy确定是否重启。如果没配置livenessProbe,默认状态是Success。
    • readinessProbe: 检查pod是否已就绪对外提供服务。如果fail,endpoint会移除该pod的IP地址。在initial delay之前,此probe的默认值为Failure。如果没配置readinessProbe,默认状态为Success。
    • startupProbe: 检查pod是否已启动。如果配置了startupProbe,其他的probe会被禁用,直到startupProbe状态为Success才会启用其他的probe。如果startupProbe失败,kubelet会kill掉container。接下来container会根据restartPolicy确定是否重启。如果没有配置startupProbe,默认状态为Success。

    livenessProbe的例子

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: liveness
      name: liveness-http
    spec:
      containers:
      - args:
        - /server
        image: k8s.gcr.io/liveness
        livenessProbe:
          httpGet:
            # when "host" is not defined, "PodIP" will be used
            # host: my-host
            # when "scheme" is not defined, "HTTP" scheme will be used. Only "HTTP" and "HTTPS" are allowed
            # scheme: HTTPS
            path: /healthz
            port: 8080
            httpHeaders:
            - name: X-Custom-Header
              value: Awesome
          initialDelaySeconds: 15
          timeoutSeconds: 1
        name: liveness
    

    Container States

    可以使用

    kubectl describe pod [POD_NAME]
    

    来查看container state。

    Container state有如下值:

    • Waiting: container state默认值。如果container既没有运行又没有终止,它处于waiting状态。
    • Running: container在运行,没遇到任何问题。
    • Terminated: container运行完毕,已经终止。运行完毕成功退出或者运行失败都是Terminated状态。

    Restart Policy

    具有三个值:

    • Always
    • OnFailure
    • Never

    RestartPolicy位于PodSpec配置中,对pod内所有的container生效。

    Container的重启延迟时间会指数级增长(最多为5分钟),启动成功10分钟之后,重启延迟时间重置。

    Init Container

    Init Container在应用程序container之前运行。

    一个pod可以具有一个或多个init container。

    Init container具有如下特点:

    • 总是会运行完毕退出。
    • 每个init container依次运行,一个运行成功再运行下一个。

    如果init container运行失败,kubenetes会反复重启pod直到运行成功。如果RestartPolicy配置为Never,pod不会被重启。

    Init Container和应用Container的不同之处

    1. 资源限制不同,详情参见https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#resources
    2. 不支持ReadinessProbe

    Init Container使用例子

    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; do echo waiting for myservice; sleep 2; done;']
      - name: init-mydb
        image: busybox:1.28
        command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
    

    Init Container的行为

    如果pod的RestartPolicy为Always,它所有init container的RestartPolicy为OnFailure。

    如果pod重启,pod的init container必须要重新执行。

    使用activeDeadlineSeconds或livenessProbe避免init container永无休止的fail。

    Pod重启的原因

    • pod参数更新导致init container的image改变。
    • pod基础container重启。这种情况不常见。
    • pod的所有container都已停止,同时RestartPolicy设置为Always

    Pod的操作

    获取pod信息

    kubectl get po pod_name -o yaml
    

    创建pod

    kubectl create -f kubia-manual.yaml
    

    其中kubia-manual.yaml为pod描述文件。

    获取所有pod

    kubectl get pods
    

    查看更详细的pod信息列表

    kubectl get pods -o wide
    

    获取pod的日志

    kubectl logs pod_name
    

    如果pod内存在多个container,可以使用如下命令获取某一个特定container内的日志

    kubectl logs pod_name -c container_name
    

    删除pod

    kubectl delete po kubia-gpu
    

    向pod发送请求

    绑定宿主机和pod端口的方式:

    • 使用k8s service(推荐)
    • 使用port forwarding

    Port forwarding方式

    kubectl port-forward kubia-manual 8888:8080
    

    Label(标签)

    label是key/value pair。可以对k8s中的资源对象(pod,controller,service等)进行分类和标记,供其他资源对象的相关selector进行操作。

    label相关操作

    创建带有label的pod

    yaml

    apiVersion: v1
    kind: Pod
    metadata:
        name: kubia-manual-v2
        labels:
            creation_method: manual
            env: prod
    spec:
        containers:
        - image: luksa/kubia
          name: kubia
          ports:
          - containerPort: 8080
            protocol: TCP
    

    查看pod的label信息

    kubectl get po --show-labels
    

    将指定label分列显示

    kubectl get po -L creation_method,env
    

    新增标签

    kubectl label po kubia-manual creation_method=manual
    

    修改标签

    kubectl label po kubia-manual-v2 env=debug --overwrite
    

    使用label selector列出pod信息

    精确匹配

    kubectl get po -l creation_method=manual
    

    列出包含env标签的pod

    kubectl get po -l env
    

    列出不包含env标签的pod

    kubectl get po -l '!env'
    

    使用label selector删除pod

    kubectl delete po -l creation_method=manual
    

    label selector的运算符

    • creation_method!=manual 否定
    • env in (prod,devel) 范围
    • env notin (prod,devel) 范围否定
    • app=pc,rel=beta 使用多个selector

    节点标签配置

    可以为集群中的节点增加标签,这样就可以使用pod spec中的nodeSelector人工干预pod的schedule过程,控制pod可运行到哪些节点上。

    节点操作

    节点增加标签

    kubectl label node gke-kubia-85f6-node-0rrx gpu=true
    

    使用label selector列出节点

    kubectl get nodes -l gpu=true
    

    创建node时使用node selector。(以下pod中的container仅会在label为gpu=true的节点下运行)

    apiVersion: v1
    kind: Pod
    metadata:
        name: kubia-gpu
    spec:
        nodeSelector:
            gpu: "true"
        containers:
          - image: luksa/kubia
          name: kubia
    

    查看pod描述

    kubectl describe pod kubia-manual
    

    Annotation

    Annotation通常来说不会被k8s直接使用,主要为了便于集群维护者查看。

    有一个例外是对于一些alpha或者beta的API,它们会从annotation中读取一些配置。

    Annotation相关操作

    增加annotation

    kubectl annotate pods kubia-manual mycompany.com/someannotation="foo bar"
    

    删除kubia-manual这个pod上key为description的annotation

    kubectl annotate pods kubia-manual description-
    

    Namespace

    Namespace用于对k8s中资源对象的分组。namespace之间没有嵌套或层级关系。一个资源对象只能属于一个namespace。不同组之间的对象是隔离的,互相不可见。

    Namespace 适合用于隔离不同用户创建的资源。

    注意:namespace无法保证网络的隔离性,比如说service可以跨namespace访问。

    默认来说Kubernetes具有如下3个namespace:

    • default: k8s默认的namespace,如果操作如果不指明namespace,默认会操作名为default的namespace。
    • kube-system: k8s系统自己运行所需的资源对象所在的namespace。
    • kube-public: k8s自动创建的namespace,对所有用户可见。适合放置集群范围都可见的服务。

    namespace相关操作

    列出所有的namespace

    kubectl get ns
    

    获取指定namespace下的所有pod

    kubectl get po --namespace kube-system
    # 或
    kubectl get po -n kube-system
    

    创建namespace

    custom-namespace.yaml

    apiVersion: v1
    kind: Namespace
    metadata:
        name: custom-namespace
    
    kubectl create -f custom-namespace.yaml
    

    或者使用

    kubectl create namespace custom-namespace
    

    在指定namespace下创建资源

    kubectl create -f kubia-manual.yaml -n custom-namespace
    

    k8s快速切换namespace

    alias kcd='kubectl config set-context $(kubectl config currentcontext) --namespace '
    
    kcd some-namespace
    

    执行如下命令验证

    kubectl config view --minify | grep namespace:
    

    删除整个namespace,这样namespace下的所有pod都会被删除

    kubectl delete ns custom-namespace
    

    删除整个namespace下的所有pod,但不删除namespace

    kubectl delete po --all
    

    删除namespace中所有的资源

    kubectl delete all --all
    

    相关文章

      网友评论

        本文标题:K8s Pod和namespace

        本文链接:https://www.haomeiwen.com/subject/nzwtxhtx.html