侧边栏壁纸
  • 累计撰写 51 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

K8s Pod 和 Service 1

zhanjie.me
2020-11-04 / 0 评论 / 0 点赞 / 1 阅读 / 0 字

1.1 Pod 简介

一个 Pod 是 Kubernetes 最基本的构建单元,也是最小、最简单的构建单元。Pod 也是扩缩容的基本单位,Kubernetes 的扩容和缩容都是直接对 Pod 进行操作的,直接增加 Pod 或是减少 Pod。

一个 Pod 包含一个应用容器(有的时候有多个)、存储资源、唯一的网络 IP、以及其它容器运行所必须的资源。

Pod 在 Kubernetes 集群中主要有两种使用方式:

  • 运行一个单独的容器:这是最常用的方式;在这种情况下,可以认为一个 Pod 封装了一个单独的容器,Kubernetes 是对 pod 进行管理,而不是直接对容器进行管理。
  • 运行耦合度高的多个容器:Pod 也可能包含多个容器,这些容器之间关联紧密需要共享资源。将多个容器添加到单个 Pod 的主要原因是应用可能由一个主进程和一个或多个辅助进程组成。在实践中,把一个进程放到一个容器中运行是最好的。

在本实验中,我们只讲解单容器 Pod 的情况。

每个 Pod 意味着运行了一个单独的应用实例,如果你想要运行多个应用实例对应的就应该使用多个 Pod。

image-nlwvhjju.png

Nodes 与 Pods

Pod 是运行在 Node 上的。一个 Node 是 Kubernetes 上的工作节点,它可能是虚拟出来的节点或者是物理节点,这取决于集群的部署方式。每个 Node 节点都被 Master 节点所管理,一个 Node 节点可以运行多个 Pod,在集群中,Kubernetes Master 节点通过 Node 节点自动管理 Pods。

每个 Nodes 运行至少需要两个组件:

  • Kubelet:负责 Master 和 Node 之间的通信,用于管理节点上的 Pod。
  • Docker:负责从仓库拉取容器镜像,运行应用等。

image-bbonnanz.png


1.2 操作 Pod

虽然在实际的生产过程中,我们常常使用的是部署(Deployment)来管理 Pod,但是了解这些操作可以帮助我们更好的理解 Pod。

创建 Pod

Pod 和其他 Kubernetes 资源通过向 Kubernetes REST API 提供 JSON 或 YAML 描述文件来创建,由于 YAML 格式具有更好的可读性,kubectl 在请求 API 时会从配置文件中读取 YAML 格式内容并转换为 JSON 格式后再发送给 API Server。

编写 YAML 描述文件

编写一个 YAML 文件有 4 个重要的组成部分:

  • apiVersion: YAML 描述文件所使用的 Kubernetes API 版本
  • kind: Kubernetes 对象/资源类型
  • metadata: Pod 元数据(名称、命名空间、标签、注解等)
  • spec: Pod 规格/内容(容器列表、存储卷等)

新建 nginx-manual.yaml 文件,并向该文件中写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-manual
spec:
  containers:
    - image: nginx:1.9.1
      name: nginx
      ports:
        - containerPort: 80
          protocol: TCP

上面的这个 YAML 文件定义了我们要创建一个名为 nginx-manual 的 Pod,这个 Pod 中运行了一个基于 nginx:1.9.1 镜像构建的名为 nginx 的容器,默认监听在 80 端口。

如果不清楚有哪些可用属性,可以使用 kubectl explain 来查看:

# 查看 pods 有哪些属性
$ kubectl explain pods
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
...
# 查看具体的属性
$ kubectl explain pod.spec
KIND:     Pod
VERSION:  v1

RESOURCE: spec <Object>

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

     PodSpec is a description of a pod.

FIELDS:
   activeDeadlineSeconds    <integer>
     Optional duration in seconds the pod may be active on the node relative to
     StartTime before the system will actively try to mark it failed and kill
     associated containers. Value must be a positive integer.

...

执行创建

使用如下命令可以创建 Pod:

$ kubectl create -f nginx-manual.yaml
pod/nginx-manual created

在 Pod 列表中查看新创建的 Pod:

$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
nginx-manual   1/1     Running   0          25s

可以看到这个 Pod 已经创建成功并在运行中。

Pod 在整个生命周期中存在各种状态,常见的状态如下所示:

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

另外 Pod 的重启策略(RestartPolicy)有 3 种,分别为:

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

查看运行中的 Pod 完整定义

查看一个 Pod 的 YAML 描述文件:

$ kubectl get pod nginx-manual -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/podIP: 10.20.177.117/32
    kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu, memory request for container
      nginx; cpu, memory limit for container nginx'
...
# 也可以查看 json 格式的
$ kubectl get pod nginx-manual -o json
{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "annotations": {
            "cni.projectcalico.org/podIP": "10.20.177.117/32",
            "kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu, memory request for container nginx; cpu, memory limit for container nginx"
        },
...

这个 Pod 是处于运行状态,最终获取到的信息会比较多,可以看到前面我们定义的 4 个部分都展示了出来,这里额外还显示了一个部分:

  • status: 运行中的 Pod 及其内容容器当前的详细状态(Pod 所处的条件、每个容器的状态、内部 IP 等)

注意:status 是运行的 Pod 在查询时刻的资源状态,所以在编写 YAML 文件的时候不需要这个属性。

查看日志

如果 Pod 上只包含一个容器,想要查看该容器的日志,就可以通过如下命令查看日志:

$ kubectl logs nginx-manual

如果 Pod 上包含多个容器,在查询具体容器的日志时,需要指定参数 -c 容器名 进行查询,比如:

$ kubectl logs nginx-manual -c nginx

需要注意的是:每天或是每次日志文件达到 10M 大小之后,容器日志会自动轮替,kubectl logs 命令只显示最后一次轮替后的日志。

测试 Pod 端口是否可用

Pod 运行之后想要测试(调试)一下是否可用,怎么办呢?可以使用 kubectl port-forward 命令来执行端口转发,将本地的 8080 端口转发到 nginx-manual 的 80 端口,执行如下命令:

$ kubectl port-forward nginx-manual 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

使用 curl 命令向 本地 8080 发送 HTTP 请求,新开一个标签,执行:

$ curl http://127.0.0.1:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

1.3 标签

当集群中的 Pod 数量越来越多时,想要有效的区分和管理这些 Pod 就成为了一个问题。可以通过标签来组织 Pod 和所有其他 Kubernetes 资源对象。通过标签划分组,这样就可以对属于某个组的所有 Pod 进行操作,而不需要单独为某个 Pod 执行操作。

标签是可以附加在 Kubernetes 资源对象的任意键值对,通过标签选择器可以选择具有该确切标签的资源。标签的 key 是唯一的,一个资源可以拥有多个标签。创建资源时可以将标签附加在资源上,也可以在现有的资源上添加标签或修改标签值。

创建时指定标签

尝试创建一个带有两个标签的新 Pod,新建 nginx-manual-with-labels.yaml 文件,并向其中写入如下代码:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-manual-v2
  labels:
    creation_method: manual
    rel: beta
spec:
  containers:
    - image: nginx:1.9.1
      name: nginx
      ports:
        - containerPort: 80
          protocol: TCP

然后执行如下命令创建 Pod:

$ kubectl create -f nginx-manual-with-labels.yaml
pod/nginx-manual-v2 created

查看 Pod 的标签可以使用 --show-labels 选项:

$ kubectl get pod --show-labels
NAME              READY   STATUS    RESTARTS   AGE   LABELS
nginx-manual      1/1     Running   0          142m   <none>
nginx-manual-v2   1/1     Running   0          10s   creation_method=manual,rel=beta

如果想要查看某个具体的标签可以使用 -L 选项指定:

$ kubectl get pod -L creation_method,rel
NAME              READY   STATUS    RESTARTS   AGE     CREATION_METHOD   REL
nginx-manual-v2   1/1     Running   0          3m13s   manual            beta

修改标签

标签也可以在现有的 Pod 上进行添加和修改。

先尝试向 nginx-manual 这个 Pod 添加一个标签,执行如下命令:

$ kubectl label pod nginx-manual creation_method=manual
pod/nginx-manual labeled

然后将 nginx-manual-v2 这个 Pod 上的 rel=beta 修改为 rel=stable,需要添加 --overwrite 选项,执行如下命令:

$ kubectl label pod nginx-manual-v2 rel=stable --overwrite
pod/nginx-manual-v2 labeled

现在来查看更新后的标签:

$ kubectl get pod -L creation_method,rel
NAME              READY   STATUS    RESTARTS   AGE     CREATION_METHOD   REL
nginx-manual      1/1     Running   0          85s     manual
nginx-manual-v2   1/1     Running   0          5m26s   manual            stable

1.4 标签选择器

标签通常与标签选择器结合在一起使用,标签选择器可以选择标记有特定标签的 Pod 子集,并对这些 Pod 执行操作。

标签选择器对于标签的使用一般有如下 3 种方式:

  • 包含或是不包含使用特定键的标签
  • 包含具有特定键和值的标签
  • 包含有特定键,值可以为任意值的标签

想要筛选出所有手动创建的 Pod:

$ kubectl get pod -l creation_method=manual
NAME              READY   STATUS    RESTARTS   AGE
nginx-manual      1/1     Running   0          3m21s
nginx-manual-v2   1/1     Running   0          7m22s

列出含有 rel 标签的所有 Pod:

$ kubectl get pod -l rel
NAME              READY   STATUS    RESTARTS   AGE
nginx-manual-v2   1/1     Running   0          8m31s

列出不含有 rel 标签的所有 Pod:

$ kubectl get pod -l '!rel'
NAME           READY   STATUS    RESTARTS   AGE
nginx-manual   1/1     Running   0          5m

还有一些其它的使用方式:

# 列出含有 creation_method 标签,但是其值不能为 manual 的 Pod
$ kubectl get pod -l 'creation_method!=manual'
# 列出含有 rel 标签,且其值为 beta 或是 stable 的 Pod
$ kubectl get pod -l 'rel in (beta,stable)'
# 列出含有 rel 标签,且其值不为 beta 和 stable 的 Pod
$ kubectl get pod -l 'rel notin (beta,stable)'
# 列出含有标签 creation_method=manual 和 rel=stable 的 Pod
$ kubectl get pod -l creation_method=manual,rel=stable

约束 Pod 调度

在 Kubernetes 中,Pod 通常都是随机调度到工作节点上的,这也是 Kubernetes 集群中正确的工作方式。但是在某些特定的情况下,我们会指定 Pod 的调度,这种需求不太常见,这里大家仅作为了解即可。

有的时候一个集群中的硬件基础设施会不一样,比如机器学习的环境中,有的使用 CPU 环境,有的是 GPU 环境,这两种环境的硬件不一样,会导致对应的计算速度也不同。如果想要将 Pod 调度到 GPU 的工作节点上,可以对相应的节点打上标签,然后在编写 yaml 文件时使用 nodeSelector 指定对应的节点标签。

首先查看环境中有几个节点:

$ kubectl get nodes
NAME           STATUS   ROLES    AGE   VERSION
kubesphere01   Ready    master   66d   v1.16.9
kubesphere02   Ready    <none>   66d   v1.16.9
kubesphere03   Ready    <none>   66d   v1.16.9

任意选择一个节点打上标签:

$ kubectl label node kubesphere02 gpu=true
node/kubesphere02 labeled

现在查看是否打上标签:

$ kubectl get nodes -l gpu=true
NAME           STATUS   ROLES    AGE   VERSION
kubesphere02   Ready    <none>   66d   v1.16.9

新建一个名为 nginx-gpu 的 Pod,新建 nginx-gpu.yaml 文件,并向其中写入如下代码:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-gpu
spec:
  nodeSelector:
    gpu: "true"
  containers:
    - image: nginx:1.9.1
      name: nginx
      ports:
        - containerPort: 80
          protocol: TCP

其中的 nodeSelector 字段表示在创建 Pod 时调度器只在包含 gpu=true 的工作节点中选择。
然后执行创建:

$ kubectl create -f nginx-gpu.yaml
pod/nginx-gpu created
$ kubectl get pods -o wide
NAME              READY   STATUS    RESTARTS   AGE    IP              NODE           NOMINATED NODE   READINESS GATES
nginx-gpu         1/1     Running   0          48s    10.20.138.42    kubesphere02   <none>           <none>

1.5 命名空间

由于标签和 Pod 是多对多的关系,使用标签可以将众多的 Pod 进行分组,这些组中的 Pod 有交叉重复的可能;使用命名空间就可以将对象分隔成完全独立且不重叠的组。Kubernetes 的命名空间为对象名称提供了一个作用域。对象名称只需要在一个命名空间内保持唯一,不同的命名空间可以包含同名的对象。

查看集群中所有的命名空间:
由于标签和 Pod 是多对多的关系,使用标签可以将众多的 Pod 进行分组,这些组中的 Pod 有交叉重复的可能;使用命名空间就可以将对象分隔成完全独立且不重叠的组。Kubernetes 的命名空间为对象名称提供了一个作用域。对象名称只需要在一个命名空间内保持唯一,不同的命名空间可以包含同名的对象。

查看集群中所有的命名空间:

$ kubectl get namespaces
NAME                           STATUS   AGE
default                        Active   66d
istio-system                   Active   65d
kube-node-lease                Active   66d
kube-public                    Active   66d
kube-system                    Active   66d
kubesphere-alerting-system     Active   65d
kubesphere-controls-system     Active   65d
kubesphere-devops-system       Active   65d
kubesphere-logging-system      Active   65d
kubesphere-monitoring-system   Active   65d
kubesphere-system              Active   65d
openpitrix-system              Active   65d
user-test                      Active   24d

如果没有指定命名空间,那么就是在 default 这个命名空间下进行的 Pod 创建等操作(我做了alias设置,alias kubectl='kubectl --namespace=user-test',所以之前一直是在user-test命名空间操作)。

可以查看一下其他命名空间中的 Pod:

$ /usr/bin/kubectl get pod -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-589b5f594b-g86zn   1/1     Running   0          66d
calico-node-5rpwf                          1/1     Running   0          66d
calico-node-66cl4                          1/1     Running   0          66d
calico-node-xqf6p                          1/1     Running   0          66d
coredns-67c766df46-4vg25                   1/1     Running   0          66d
coredns-67c766df46-wkwf5                   1/1     Running   0          66d
etcd-kubesphere01                          1/1     Running   0          66d
kube-apiserver-kubesphere01                1/1     Running   0          66d
kube-controller-manager-kubesphere01       1/1     Running   0          66d
kube-proxy-7gxj2                           1/1     Running   0          66d
kube-proxy-frjw4                           1/1     Running   0          66d
kube-proxy-tx6n7                           1/1     Running   3          66d
kube-scheduler-kubesphere01                1/1     Running   0          66d
metrics-server-66444bf745-7vwd5            1/1     Running   0          65d
nfs-client-provisioner-7f959768b5-vchmj    1/1     Running   0          66d
tiller-deploy-6d8dfbb696-r968q             1/1     Running   0          66d

可以看到 kube-system 命名空间下的 Pod 都是和 Kubernetes 系统相关的。

现在来新建一个命名空间,新建 test1-namespace.yaml 文件并向其中写入如下代码:

apiVersion: v1
kind: Namespace
metadata:
  name: test1-namespace

然后执行创建:

$ kubectl create -f test1-namespace.yaml
namespace/test1-namespace created

当然也可以使用命令直接创建新的命名空间:

$ kubectl create namespace test2-namespace
namespace/test2-namespace created

如果想要在新的命名空间中创建 Pod,有两种方式:

  • 在 yaml 文件的 metadata 字段中添加 namespace: test1-namespace 属性
  • 创建 Pod 时在命令中使用参数 -n 指定命名空间

比如使用前面的 nginx-manual.yaml 文件在 test1-namespace 命名空间中新建 Pod:

$ /usr/bin/kubectl create -f nginx-manual.yaml -n test1-namespace
pod/nginx-manual created

这样我们就有两个同名的 Pod 分别运行在两个不同的命名空间内。

$ /usr/bin/kubectl get pods --all-namespaces |grep nginx-manual
test1-namespace                nginx-manual                                                      1/1     Running     0          95s
user-test                      nginx-manual                                                      1/1     Running     0          153m
user-test                      nginx-manual-v2                                                   1/1     Running     0          157m

1.6 删除及更新 Pod

可以使用名称删除 Pod:

$ kubectl delete pod nginx-manual
pod "nginx-manual" deleted

也可以使用标签选择器删除 Pod:

$ kubectl delete pod -l creation_method=manual
pod "nginx-manual-v2" deleted

还可以通过删除整个命名空间的方式来删除 Pod(命名空间不存在的话,其中的 Pod 会自动被删除):

$ /usr/bin/kubectl delete ns test1-namespace
namespace "test1-namespace" deleted

如果想要更新 Pod,可以在修改 Pod 的配置文件之后执行 kubectl replace xxx.yaml --force 强制更新 Pod 的各种配置属性。


1.7 副本集 (RS)、后台支撑服务集 (DaemonSet)、任务 (Job)

使用前面的方法创建 Pod,如果该 Pod 所在的工作节点挂掉了,那么这个节点上的 Pod 会丢失,并且不会重新建立。

在实际的生产中,我们希望我们的部署可以自动运行、保持健康、工作节点挂掉之后 Pod 会自动迁移到新的节点,所以几乎不会手动创建 Pod,而是使用副本集 ReplicaSet 或部署 Deployment 来创建并管理 Pod。

副本集 (RS)

副本集 ReplicaSet 是一种 Kubernetes 资源对象,它可以保证 Pod 始终处于运行状态,如果 Pod 因任何原因消失,ReplicaSet 会注意到缺少了 Pod 并创建新的 Pod 进行替代。

ReplicaSet 主要用于创建和管理一个 Pod 的多个副本(replicas),核心标准是确保 Pod 的数量始终与其标签选择器匹配,它会持续监控正在运行的 Pod 列表,并保证带有对应标签的 Pod 数量与期望相符,如果运行的 Pod 太少会根据 Pod 模板创建新的副本;如果运行的 Pod 太多就会删除多余的副本。

因此 ReplicaSet 由 3 个部分组成:

  • 标签选择器(label selector): 确定 ReplicaSet 作用域中有哪些 Pod
  • 副本个数(replica count): 指定应运行的 Pod 数量
  • Pod 模板(pod template): 用于创建新的 Pod 副本

上述的 3 个部分都可以随时修改,只有副本个数的变更会影响到现有的 Pod,更改标签选择器和 Pod 模板对现有的 Pod 没有影响。如果更改标签选择器会使现有的 Pod 脱离 ReplicaSet 的范围,ReplicaSet 会停止关注它们;如果更改模板,只会对新创建的 Pod 应用新的模板,并不会影响现在存在的 Pod。

使用 ReplicaSet 有以下 3 大好处:

  • 保证 Pod 持续运行,如果现有 Pod 数量不符合预期将会自动调整 Pod 的数量;
  • 当集群节点发生故障时,在故障节点受 ReplicaSet 控制的所有 Pod 会被创建新的替代副本;
  • 可以轻松实现 Pod 的水平伸缩。

注意:这里的标签选择器可以匹配如下的标签:

  • 具有某个特定标签名和值的 Pod
  • 缺少某个标签的 Pod
  • 包含特定标签名,不管其值为多少的 Pod
  • 匹配多个标签,只要符合其中一个标签就认为是符合标准的

现在来创建一个 ReplicaSet,新建 nginx-replicaset.yaml 文件并向其中写入如下代码:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.9.1

执行创建:

$ kubectl create -f nginx-replicaset.yaml
replicaset.apps/nginx created

查看创建的 Pods 和 ReplicaSet:

$ kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
nginx-8nw85   1/1     Running   0          105s
nginx-chsv4   1/1     Running   0          105s
nginx-jg9ll   1/1     Running   0          105s
$ kubectl get rs
NAME    DESIRED   CURRENT   READY   AGE
nginx   3         3         3       113s

查看详细的描述:

$ kubectl describe rs
Name:         nginx
Namespace:    user-test
Selector:     app=nginx
Labels:       <none>
Annotations:  <none>
Replicas:     3 current / 3 desired
Pods Status:  3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.9.1

除了使用 matchLabels 属性外,还可以使用功能更加强大的 matchExpressions 属性,在这个属性中可以使用表达式,使标签匹配能够更加丰富。现在来改写上面的标签表达式:

selector:
  matchExpressions:
    - key: app
      operator: In
      values:
        - nginx

使用 matchExpressions 属性一般包含 3 个部分:一个 key、一个 operator(运算符)、以及可能还有一个 values 列表(这取决于运算符)。

operator 运算符一般有 4 种:

  • In: 标签的值必须与其中一个指定的 values 匹配
  • NotIn: 标签的值必须与指定的 values 不匹配
  • Exists: Pod 必须包含一个指定名称的标签(值不重要),这时候就不需要指定 values
  • DoesNotExist: Pod 不能够包含有指定名称的标签,这时候也不需要指定 values

如果指定了多个表达式或者同时混合使用了 matchLabels 和 matchExpressions 属性,这些表达式必须都为 true 才能和 Pod 进行匹配。

最后也可以删除定义的 ReplicaSet:

$ kubectl delete rs nginx
replicaset.apps "nginx" deleted

在删除 nginx ReplicaSet 时也会删除对应匹配的所有 Pod。


1.8 后台支撑服务集 (DaemonSet)

ReplicaSet 用于在 Kubernetes 集群上运行部署特定数量的 Pod,如果你希望在集群的每个 Node 上都运行某个 Pod,这个时候就需要使用到 DaemonSet 了,当有节点加入集群时,会为它们新增一个 Pod。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。通常这种情况下这种 Pod 都是执行系统级别与基础结构相关的操作,比如网络路由、存储、日志或是监控等。

DaemonSet 的使用情况分为两种:

  • 在每个节点上运行一个 Pod
  • 在特定的节点上运行一个 Pod

在每个节点上运行一个 Pod

新建 mysql-ds.yaml,并向其中写入如下代码:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: mysql-ds
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "Az123456_"

然后执行创建:

$ kubectl create -f mysql-ds.yaml
daemonset.apps/mysql-ds created

观察 Pod 是否分布到了每个节点上(此处只有node节点适于部署):

$ kubectl get nodes
NAME           STATUS   ROLES    AGE   VERSION
kubesphere01   Ready    master   66d   v1.16.9
kubesphere02   Ready    <none>   66d   v1.16.9
kubesphere03   Ready    <none>   66d   v1.16.9
$ kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
mysql-ds-4stkh   1/1     Running   0          73s   10.20.177.125   kubesphere03   <none>           <none>
mysql-ds-jt4f2   1/1     Running   0          73s   10.20.138.44    kubesphere02   <none>           <none>

在特定的节点上运行一个 Pod

如果想要使用 DaemonSet 只在特定的节点上运行 Pod,只需要在模板中的 nodeSelector 属性中指明即可。

环境中有两个节点,分别名为 kubesphere02 和 kubesphere03,我们先将 kubesphere02 打上标签 disk1=ssd1:

$ kubectl label node kubesphere02 disk1=ssd1
node/kubesphere02 labeled

然后新建 tomcat-ssd.yaml,并向其中写入如下代码:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: tomcat-ssd
spec:
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      nodeSelector:
        disk1: ssd1
      containers:
        - name: tomcat
          image: kubeguide/tomcat-app:v1

执行创建并观察新建的 ds 和 Pod:

$ kubectl create -f tomcat-ssd.yaml
daemonset.apps/tomcat-ssd created
$ kubectl get pods -o wide
NAME               READY   STATUS    RESTARTS   AGE     IP              NODE           NOMINATED NODE   READINESS GATES
mysql-ds-4stkh     1/1     Running   0          8m10s   10.20.177.125   kubesphere03   <none>           <none>
mysql-ds-jt4f2     1/1     Running   0          8m10s   10.20.138.44    kubesphere02   <none>           <none>
tomcat-ssd-vv7g6   1/1     Running   0          43s     10.20.138.45    kubesphere02   <none>           <none>

如果我们将 kubesphere02 这个节点上的标签修改为 disk1=hdd,使用 DaemonSet 创建的 Pod 将会被删除:

$ kubectl label node kubesphere02 disk1=hdd --overwrite
node/kubesphere02 labeled
$ kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
mysql-ds-4stkh   1/1     Running   0          10m   10.20.177.125   kubesphere03   <none>           <none>
mysql-ds-jt4f2   1/1     Running   0          10m   10.20.138.44    kubesphere02   <none>           <none>

1.9 任务 (Job)

前面 ReplicaSet 和 DaemonSet 监控管理的 Pod 会持续不断的运行任务,这样的任务是没有完成态的,如果其中的进程退出了 Pod 会重新启动。如果我们想要执行一个可完成的任务,当进程终止后 Pod 不再重新启动,那么就需要使用任务 (Job)。

当节点发生故障的时候,该节点上由 Job 管理的 Pod 会按照 ReplicaSet 的 Pod 的方式,重新安排到其它节点;如果进程异常退出,可以将 Job 配置为重新启动容器。

现在模拟一个任务,有一个构建在 busybox 上的容器,该容器会调用 sleep 命令休息20s,然后就正常退出。

新建 sleep.yaml 文件并向其中写入如下代码:

apiVersion: batch/v1
kind: Job
metadata:
  name: batch-job
spec:
  template:
    metadata:
      labels:
        app: batch-job
    spec:
      restartPolicy: OnFailure
      containers:
        - name: main
          image: luksa/batch-job

其中的 restartPolicy 属性定义了当容器中的进程运行结束时 Kubernetes 会如何做,默认的值为 Always,表示的是重新启动并运行;所以在使用 Job 时我们必须修改为 OnFailure 或是 Never。

执行创建:

$ kubectl create -f sleep.yaml
job.batch/batch-job created

查看 Job 和 Pod:

$ kubectl get jobs
NAME        COMPLETIONS   DURATION   AGE
batch-job   0/1           6s         6s
$ kubectl get pods
NAME              READY   STATUS              RESTARTS   AGE
batch-job-fw78q   0/1     ContainerCreating   0          10s
...
$ kubectl get pods
NAME              READY   STATUS              RESTARTS   AGE
batch-job-fw78q   0/1     ContainerCreating   0          21s
$ kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
batch-job-fw78q   1/1     Running   0          22s
...
$ kubectl get pods
NAME              READY   STATUS      RESTARTS   AGE
batch-job-fw78q   0/1     Completed   0          42s
$ kubectl get jobs
NAME        COMPLETIONS   DURATION   AGE
batch-job   1/1           37s        2m4s
$ kubectl get pods
NAME              READY   STATUS      RESTARTS   AGE
batch-job-2sm7c   0/1     Completed   0          2m23s

如果想要一项任务按顺序依次执行 10 次,可以使用 completions 属性:

spec:
  completions: 10
  template: ...

如果想要一项任务总共运行 10 次,每次可以并行执行 3 个 Pod,可以使用 parallelism 属性:

spec:
  completions: 10
  parallelism: 3
  template: ...
0

评论区