Skip to content

Pod理论-企业实战案例讲解-资源清单编写技巧

Pod基本介绍

Pod概念

  • 在·Kubernetes·中,Pod·是最小的调度单元,是容器的逻辑宿主机。Pod·可以包含一个或多个紧密关联的容器,这些容器共享同一个网络命名空间、存储卷以及主机名。通常情况下,这些容器会协同工作来提供一个完整的应用服务。(微念·批建行和段誉限落居中
  • Pod·是·Kubernetes·中的一个重要概念,因为它为多个容器提供了一个共享的上下文和环境。Pod中的容器可以直接相互通信,它们之间的交互和通信可以通过本地主机的网络端口进行。Pod·还提供了一些共享的资源,如存储卷和命名空间等,可以使容器之间共享数据和状态。
  • Pod·是·Kubernetes·中应用部署和管理的基本单元。当需要部署一个应用时,可以将所有相关的容器打包在同一个·Pod·中,然后通过·Kubernetes·控制器进行管理和调度。Pod·也是·Kubernetes的一种扩展点,可以通过定义自定义资源(Custom·Resources)来扩展·Pod·的功能和能力。
Pod:
  container:
    image: nginx
  container:
    image: tomcat

Pod、容器、节点关系:

  • 在·Kubernetes·中,容器是部署和运行应用程序的主要载体,而·Pod·则是用来管理容器的。每个Pod·都可以包含一个或多个容器,这些容器共享同一个网络命名空间、存储卷以及主机名,它们在·Pod中是处于相同的生命周期和调度环境下的。也就是说,当一个·Pod·被创建时,它里面的所有容器都会被一起创建,而当·Pod·被删除时,里面的所有容器也会被一起删除。
  • 节点是·Kubernetes·集群中的一台服务器,它是·Pod·的宿主机。当·Pod·被创建时,Kubernetes·调度器会选择一个节点来运行该·Pod,然后在该节点上启动·Pod·中的所有容器。Pod·可以被调度到任意一个节点上运行,也可以在不同节点之间自由迁移。

自主式Pod和控制器管理的Pod

自主式 pod:

  • 在k8s中,我们部署pod的时候,基本上都是使用控制器管理,那如果不使用控制器,也可以直接定义一个pod资源,那么就是pod自己去控制自己,这样的pod称为自主式pod。

互动1:如何创建一个自主式Pod?

# 查看k8s哪些资源
$ kubectrl api-resources
# 查看控制节点描述
$ kubectrl describe nodes xuegod63
...
# 污点 起到保护作用,如果不能容忍污点,其调度器不会将pod调度过来
Taints:             node-role.kubernetes.io/control-plane:NoSchedule
# 工作节点都要得到镜像
$ ctr -n k8s.io images pull docker.io/library/tomcat:8.5-jre8-alpine
  • 编写pod

vim pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: tomcat-pod
  namespace: default
  # 定义了标签
  labels: 
    tomcat: tomcat-pod
spec:
  containers:
  - name: tomcat-pod-java
    ports: 
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
  • 使用
$ kubectl apply -f pod.yaml
# 查看pod
$ kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
tomcat-pod   1/1     Running   0          42s
# 查看标签为 tomcat-pod 的 tomcat pod有哪些
$ kubectl get pod -l tomcat=tomcat-pod
NAME         READY   STATUS    RESTARTS   AGE
tomcat-pod   1/1     Running   0          96s
  • 上面实验可以看到,当我们把pod删除之后,pod不会再创建一个新的pod,而是彻底从机器上删除了,这种自主式pod适合测试环境或者非核心业务场景,如果生产环境用自主式pod部署应用,那是存在风险的,所以,我们平时管理Pod都是通过控制器去管理的。

控制器管理的Pod

控制器可以根据不同的需求来创建和管理·Pod,例如: 1、Deployment·控制器:用于创建和管理可扩展的·Pod·集合,支持滚动升级和回滚操作。 2、StatefulSet·控制器:用于管理有状态的应用程序,支持有序部署和扩缩容操作。 3、DaemonSet·控制器:用于在每个节点上运行一组·Pod,以支持集群级别的后台任务等。 4、Job&&Cronjob 5、 Replicaset

当使用这些控制器来创建和管理·Pod·时,控制器会监视·Pod的状态并确保其持续满足用户的期望状态。如果·Pod·的状态发生变化,例如某个容器挂掉了,控制器会自动进行故障恢复操作,以确保Pod·的期望状态能够得到恢复。

示例:通过Deployment创建一个pod资源

vim deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
  • 运行及查看
$ kubectl apply -f deployment.yaml 
deployment.apps/my-nginx created
$ kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
my-nginx   2/2     2            2           24s
# deployment 资源会自动创建 replicaset 资源
$ kubectl get rs
NAME                 DESIRED   CURRENT   READY   AGE
my-nginx-5f7668c4b   2         2         2       2m10s
# 查看 replicaset 创建的pod
$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
my-nginx-5f7668c4b-j66rv   1/1     Running   0          3m29s
my-nginx-5f7668c4b-qbrxn   1/1     Running   0          3m29s
# 删除一个pod
$ kubectl delete pod my-nginx-5f7668c4b-j66rv 
pod "my-nginx-5f7668c4b-j66rv" deleted
# 会马上新建一个pod
$ ubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
my-nginx-5f7668c4b-qbrxn   1/1     Running   0          4m36s
my-nginx-5f7668c4b-z5lfk   1/1     Running   0          6s
# 删除deployment
$ kubectl delete deploy my-nginx
  • 如果更改了镜像版本,apply后会自主删除更新pod

Pod资源清单的定义方法

  • 配置命令自动补全 参考 https://kubernetes.io/zh-cn/docs/reference/kubectl/quick-reference/
    $ yum install -y bash-completion
    $ source /usr/share/bash-completion/bash_completion
    $ kubectl completion bash > ~/.kube/completion.bash.inc
    $ source '/root/.kube/completion.bash.inc'
    

创建Pod资源技巧

在创建pod的时候,可以通过写资源清单文件去实现,Pod资源清单文件中有几个重要的部分:apiVersion、kind、metadata、spec 以及 status,其中 apiVersion 和kind 是比较固定的,status是运行时的状态,不需要我们自己定义,所以最重要的就是metadata和spec两个部分。

# 查看帮助
$ kubectl explain pod

apiVersion:v1

在·Kubernetes·中,每个资源都有一个apiVersion字段,它用于标识·APl·中的不同版本。apiVersion·字段由两个部分组成,用斜杠分隔:group/version。其中,group·表示·APl·组的名称,version·表示·API·版本号。

对于·Pod·资源来说,它的·apiVersion·字段通常是·v1,即·Kubernetes·的核心组的版本

# 查看 api-version 支持的版本
$ kubectl api-versions
admissionregistration.k8s.io/v1
apiextensions.k8s.io/v1
apiregistration.k8s.io/v1
apps/v1
authentication.k8s.io/v1
authorization.k8s.io/v1
autoscaling/v1
autoscaling/v2
batch/v1
certificates.k8s.io/v1
coordination.k8s.io/v1
crd.projectcalico.org/v1
discovery.k8s.io/v1
events.k8s.io/v1
flowcontrol.apiserver.k8s.io/v1beta2
flowcontrol.apiserver.k8s.io/v1beta3
networking.k8s.io/v1
node.k8s.io/v1
policy.networking.k8s.io/v1alpha1
policy/v1
rbac.authorization.k8s.io/v1
scheduling.k8s.io/v1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

kind: Pod

在Kubernetes中,每个资源定义都包含一个·kind·字段,用于指定该资源的类型或种类

metadata

# 查看帮助
$ kubectl explain pod.metadata
name:资源名称

用于唯一标识该资源。

namespace:命名空间
  • 用于将资源隔离和分类到不同的逻辑空间中,以避免命名冲突。
  • namespace是k8s集群级别的资源,可以给不同的用户、利租户、环境或项目创建对应的名称空间,例如,可以为development、qa、和production应用环境分别创建各自的名称空间。
  • k8s的绝大多数资源都属于名称空间级别,同一名称空间内的同一类资源名必须是唯一的,但跨名称空间时并无此限制。k8s还有一些资源属于集群级别的,如node、namespace、PersistentVolume等资源,它们不属于任何名称空间,因此资源对象的名称必须全局唯一。

1、查看名称空间及其资源对象 - k8s集群默认提供了几个名称空间用于特定目的,例如,kube-system主要用于运行系统级资源,而default则为那些未指定名称空间的资源操作提供一个默认值。 - 使用kubectl·get·namespace或者kubectl·get·ns可以查看namespace资源,使用kubectl·describe·namespace·$NAME可以查看特定的名称空间的详细信息。 2、管理namespace资源namespace是k8s·api的标准资源类型之一,namespace资源属性较少,通常只需要指定名称即可创建,如“kubectlcreate·namespace·qa"。namespace资源的名称仅能由字母、数字、下划线、连接线等字符组成。删除namespace资源会级联删除其包含的所有其他资源对象:

# 查看名称空间
$ kubectl get namespaces --show-labels
NAME              STATUS   AGE   LABELS
default           Active   30h   kubernetes.io/metadata.name=default
kube-node-lease   Active   30h   kubernetes.io/metadata.name=kube-node-lease
kube-public       Active   30h   kubernetes.io/metadata.name=kube-public
kube-system       Active   30h   kubernetes.io/metadata.name=kube-system
# 查看描述
$ kubectl describe namespace
# 创建名称空间
$ kubectl create namespace qa
  • 不要轻易执行的命令
kubectI delete TYPE RESOURCE -n NS # 删除指定名称空间内的指定资源
kubectl delete TYPE --all -n NS # 删除指定名称空间内的指定类型的所有资源
kubectl delete all -n NS # 删除指定名称空间内的所有资源
kubectl delete all --all # 删除所有名称空间中的所有资源
kubectl get all # 列出指定名称空间的所有资源,除了个别的资源,如 sa 等不会列出来,大部分都会列出来
kubectl get all -A #列出来所有名称空间的所有资源,除了个别的资源,如 sa 等不会列出来,大部分都会列出来
labels:标签

用于对资源进行分类和组织。可以通过标签选择器进行资源筛选和操作。

# 查看名称空间有哪些标签
$ kubectl get pods -n kube-system --show-labels
# 查看自己创建pod有哪些标签
$ kubectl get pods --show-labels
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-5f7668c4b-qbrxn   1/1     Running   0          46m   pod-template-hash=5f7668c4b,run=my-nginx
my-nginx-5f7668c4b-z5lfk   1/1     Running   0          42m   pod-template-hash=5f7668c4b,run=my-nginx
# 根据标签筛选 
$ kubectl get pods -l run=my-nginx
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-5f7668c4b-qbrxn   1/1     Running   0          46m   pod-template-hash=5f7668c4b,run=my-nginx
my-nginx-5f7668c4b-z5lfk   1/1     Running   0          42m   pod-template-hash=5f7668c4b,run=my-nginx
# 给pod添加标签
$ kubectl label pod my-nginx-5f7668c4b-qbrxn release=canary
pod/my-nginx-5f7668c4b-qbrxn labeled
# 筛选release 标签
$ kubectl get pods -l release --show-labels
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-5f7668c4b-qbrxn   1/1     Running   0          49m   pod-template-hash=5f7668c4b,release=canary,run=my-nginx
# 删除标签
$ kubectl label pod my-nginx-5f7668c4b-qbrxn release- 
# 没有了
$ kubectl get pods -l release --show-labels
No resources found in default namespace.
# 没有了
$ kubectl get pods --show-labels
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-5f7668c4b-qbrxn   1/1     Running   0          53m   pod-template-hash=5f7668c4b,run=my-nginx
my-nginx-5f7668c4b-z5lfk   1/1     Running   0          48m   pod-template-hash=5f7668c4b,run=my-nginx

nodes 标签语法与pod相同

  • annotations:注释,用于存储一些关于资源的元数据信息,如描述、版本、维护信息等,不影响·Kubernetes·的管理和操作。
  • 1、·annotations: 假设你有一个·Kubernetes·集群,上面部署了一个·Web·应用,这个应用运行在一个·Pod·中。你想要记录该应用的版本号和部署时间,方便日后进行排查和版本管理。一种方案是将版本号和部署时间存储在·Pod·的·annotations·中。Pod·的定义文件可能如下所示

pod示例

demo-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  containers:
  - name: tomcat
    image: tomcat:8.5-jre8-alpine
    ports:
    - containerPort: 8080
    imagePullPolicy: IfNotPresent
  - name: busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 3600"]
  • 查看
$ kubectl apply -f demo-pod.yaml
# 查看日志
$ kubectl logs demo-pod
# 查看特定容器日志
$ kubectl logs demo-pod -c tomcat
# 进入pod默认容器(第一个container)
$ kubectl exec -it demo-pod -- /bin/sh
# 进入指定容器
$ kubectl exec -it demo-pod -c busybox -- /bin/sh
# 删除方式1
$ kubectl delete -f demo-pod.yaml
# 删除方式1 强制删除
$ kubectl delete -f demo-pod.yaml --force --grace-period=0
# 删除方式2
$ kubectl delete pod demo-pod

pod.spec 字段

$ kubectl explain pod.spec

参数解释说明: 1、activeDeadlineSeconds:它定义了一个·Pod·的运行时最长时间。一旦·Pod·的运行时间超过 这个时间,Kubernetes·就会自动终止·Pod,然后将其删除。这个参数可以用来避免某些应用程序的错 误或异常导致·Pod·的生命周期过长,占用集群资源,影响其他应用程序的性能。

  • eg: 举个例子,假设你有一个应用程序在·Kubernetes·中运行,这个应用程序可能因为某种原因陷入死循环或者其它异常情况,导 致它的生命周期无限延长。如果你没有设置·activeDeadlineSeconds,那么这个应用程序将会一直运行 下去,直到你手动停止它或者·Kubernetes·集群自动终止它为止。 如果你设置了·activeDeadlineSeconds,那么这个应用程序的生命周期将会被限制在指定的时间 内。一旦应用程序运行的时间超过了这个时间,Kubernetes·就会自动终止它,然后删除它。这样可以 避免应用程序的错误或异常对集群造成过多的负荷,保护集群的稳定性和安全性。

  • 如果·Pod·需要一直提供服务,那么·activeDeadlineSeconds·参数就不再适用了,因为它的作用 是限制·Pod·生命周期最长时间。在这种情况下,你可以将·activeDeadlineSeconds·设置为一个非常 大的值,比如·100·天,以确保它不会影响你的服务稳定性。

  • 需要注意的是,即使你将·activeDeadlineSeconds·设置为一个非常大的值,Pod·仍然可能会在某 些情况下被终止,比如它所在的节点发生故障,或者你手动将它删除。因此,为了保证服务的高可用性, 建议使用·Kubernetes·的高可用性特性,比如·Pod·的复制集、服务发现、自动扩展等,来确保服务的 稳定性和可用性。

2、 dnsConfig·字段用于设置·Pod·内部·DNS·解析的相关参数,可以通过该字段来配置·Pod·的 DNS·解析方式,包括·DNS·服务器地址、搜索域、是否启用·DNS·传输层安全(DNS-OVer-TLS)等 选项。

  • 具体来说,dnsConfig·字段包含以下字段: nameservers:指定·DNS·服务器的·IP·地址列表 searches:指定·DNS·解析时的搜索域列表。

  • 在·Kubernetes·中,通常情况下·Pod·内部的·DNS·解析是自动进行的,而且已经默认配置了一个 DNS·服务器(通常是·kube-dns·或·CoreDNS),以供·Pod·内部进行·DNS·解析。然而,在一些特 定的场景下,比如需要使用特定的·DNS·服务器或者搜索域时,就可以使用·dnsConfig·字段来进行配 置。

  • 需要注意的是,dnsConfig·字段只对·Pod·内部的·DNS·解析生效,如果你需要在·Pod·外部访问 该·Pod,则需要通过·Service·或者·Ingress·等资源进行暴露,而不是通过·dnsConfig·字段进行配置。

eg:

alt text

  • 什么使搜索域? 搜索域(Search·Domain)是指在·DNS·解析时,当查询的主机名(Hostname)不是一个完全合 格的域名(Fully·Qualified·Domain·Name,FQDN)时,系统会自动在查询之前加上一个默认的域名 后缀,尝试解析完整的主机名。 例如,假设你的应用程序要连接一个名为·db·的数据库服务。如果你的主机名为·myapp,而搜索 域设置为·example.com,那么在·DNs·解析时会自动将主机名解析为·db.example.com

3、dnsPolicy: dnsPolicy·是·Kubernetes·中用来指定·Pod·的·DNS·解析策略的一个字段,它的值可以是Default、ClusterFirst、ClusterFirstWithHostNet、None。具体各个取值的含义如下: - Default:继承自所在·Node·的·DNS·配置。这是默认的·DNS·策略。 - ClusterFirst:在·Pod·的·DNS·解析中,优先使用·Kubernetes·集群内部的·DNS·解析服务(kube-dns·或·CoreDNS),如果解析失败,则使用·Node·的·DNS·解析服务。 - ClusterFirstWithHostNet:当pod共享物理机网络时,它将首先查找集群内部的DNS服务来解析域名。如果无法解析,则尝试使用主机上的DNS解析· - None:禁用·Pod·的·DNS·解析功能,由用户自己负责配置。

具体的应用场景: - 如果一个·Pod·需要访问其他·Pod,且需要使用·Kubernetes·集群内部的·DNS·服务解析主机名,那么可以将·dnsPolicy·设置为·ClusterFirst。 - 如果一个·Pod·需要使用本地主机的·DNS·服务解析主机名,那么可以将·dnsPolicy·设置为 Default. - 如果一个·Pod·需要直接访问本地主机的·DNS·服务,那么可以将·dnsPolicy·设置为 ClusterFirstWithHostNet. 需要注意的是,在设置·dnsPolicy·时,需要根据具体的应用场景和网络环境来选择合适的值,以确保·DNS·解析的正确性和性能

4、hostAliases

它允许在·Pod·内部定义一个主机别名列表,以便在·Pod·内部解析主机名时使用。每个别名都是由一个IP·地址、一个主机名列表和一个可选的·IP·地址类型组成。例如:

5、hostNetwork: 如果一个·Pod·的·hostNetwork·参数设置为·true,那么这个·Pod·中的容器将会和宿主机共享网络命 名空间,即它们将会使用宿主机的网络配置,而不是·Kubernetes·中的网络配置。使用·hostNetwork 参数可以让容器直接访问宿主机上的网络资源,而无需通过·Kubernetes·网络插件进行网络转发和转 换。但同时,使用·hostNetwork·参数也会存在一些安全和隔离性问题,因为容器和宿主机共享同一个 网络命名空间,容器的网络流量也将会被宿主机上的其他进程所共享。因此,在使用·hostNetwork·参 数时需要仔细权衡安全和性能等方面的因素。

6.containers: containers → <[]object>·-required- containers是一个对象列表,,下面有很多对象,containers下的字段用-连接

查看containers下有哪些字段:

$ kubectl explain pods.spec.containers
containers下的字段解释说明: 1) name:在Kubernetes中,每个容器都需要有一个名称,该名称在定义Pod时被指定,使用name 字段指定容器的名称。该字段必须是唯一的,即Pod中不允许存在相同名称的容器。

2) image:镜像,每个容器需要指定一个镜像

3) command 和 args: 在Kubernetes中,容器的启动命令可以通过command和args字段来定义。command定义容器启 动的命令,而args则指定命令的参数。

eg: ubuntu/dockerfile

FROM ubuntu
CMD ["echo", "Hello World"] 
docker build -t hello-world:1.0 .

这个·Dockerfile·文件的意思是,使用·ubuntu·镜像作为基础镜像,然后在容器启动时运行·echo "Hello·World"·命令。 接下来,我们可以使用这个·Dockerfile·构建一个·Docker·镜像,并启动一个容器:

$ docker build -t hello-world:1.0 .
$ docker run hello-world:1.0
Hello World

将其导入到 ctr 镜像

$ docker save -o ubuntu.tar.gz hello-world:1.0
# 工作节点导入镜像
$ ctr -n=k8s.io images import ubuntu.tar.gz

ubuntu.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:
  containers:
  - name: hello-world
    image: hello-world:1.0
    imagePullPolicy: IfNotPresent
$ kubectl apply -f ubuntu.yaml
# 可以看到运行结束了
$ kubectl get pods 
NAME          READY   STATUS             RESTARTS     AGE
hello-world   0/1     CrashLoopBackOff   1 (5s ago)   6s
# 查看日志是否打印
$ kubectl logs hello-world
Hello World

重新定义 yaml

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:
  containers:
  - name: hello-world
    image: hello-world:1.0
    imagePullPolicy: IfNotPresent
    command: ["/bin/bash"]
    args: ["-c", "echo 'Hello, Kubernetes'"] 

重新查看,结果为 Hello, Kubernetes

Comments