Kubernetes Pod 调度基础

目录

一:Replication controller 和 Replicaset

1:Replication controller

2:标签与标签选择器

3:ReplicaSet

二:无状态应用管理 Deployment

三:有状态应用管理 statefulset

四:守护进程集 Daemonset

1:什么是 Daemonset

2:定义一个 Daemonset

3:创建 DaemonSet

4:查看 DaemonSet

5:查看 pod 所在的节点

6:删除 DaemonSet

五:CronJob


一:Replication controller 和 Replicaset

1:Replication controller

    Replication Controller(复制控制器,RC)

    RC 用来确保 Pod 副本数达到期望值,这样可以确保一个或多个同类 Pod 总是可用的。

    如果存在的 Pod 数量大于设定的值,Replication Controller 将终止额外的 Pod,如果太少,Replication Controller 将会启动更多的 Pod 用于保证达到期望值。与手动创建 Pod 不同的是,用 Replication Controller 维护的 Pod 在失败、删除或终止时会自动替换。因此,即使应用程序只需要一个 Pod,也应该使用 Replication Controller 或其他方式管理。

Replication Controller 类似于进程管理程序,但是 Replication Controller 不是监视单个节点上的各个进程,而是监视多个节点上的多个 Pod。

    Replication Controller 的使用如下列示例。

编辑Replicationcontroller 文件

vim replicationcontroller-nginx.yaml

apiVersion: v1

kind: ReplicationController

metadata:
  name: nginx

spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

创建Replicationcontroller

kubectl apply -f replicationcontroller-nginx.yaml

kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
nginx-9g78r   1/1     Running   0          11m
nginx-bbtqj   1/1     Running   0          11m
nginx-w28bq   1/1     Running   0          11m

kubectl get rc
NAME      DESIRED   CURRENT   READY   AGE
nginx     3         3         3       116s

删除一个 pod 并立即查看 pod 状态

kubectl delete pod nginx-9878r -n default

kubectl get pod
NAME          READY   STATUS              RESTARTS   AGE
nginx-bbtqj   1/1     Running             0          12m
nginx-qqjs4   0/1     ContainerCreating   0          2s
nginx-w28bq   1/1     Running             0          12m

删除Replicationcontroller

kubectl delete -f replicationcontroller-nginx.yaml

2:标签与标签选择器

类别 内容
标签
定义 用于标识Kubernetes对象的一组键值对,便于筛选或管理对象。
Key规则 - 必须唯一
- 不超过63个字符
- 以字母或数字开头和结尾
- 可包含字母、数字、-_.等字符
- 前缀可选,格式为DNS子域名(如kubernetes.io/),用/分隔前缀与标签名。
Value规则 - 若不为空,不超过63个字符
- 以字母或数字开头和结尾
- 可包含字母、数字、-_.等字符。
标签选择器
基于等式的选择器 - 操作符:===(相等)、!=(不等)
- 示例:date=day1,name!=build(选择dateday1name不为build的对象)。
基于集合的选择器 - 操作符:innotinexists
- 示例:
date in (day1, day2, day3)
name notin (build, pipeline)
test(存在test标签)
!test(不存在test标签)。
示例对比
基于等式的选择器示例 yaml
selector:
component: redis
基于集合的选择器示例 yaml
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
注意事项 matchLabels{key: value}的简单映射,等价于matchExpressions中的{key: key, operator: In, values: [value]}
- 所有条件需同时满足才能匹配。

3:ReplicaSet

    ReplicaSet(复制集,RS)是支持基于集合的标签选择器的下一代 Replication Controller,它主要用于 Deployment 协调创建、删除和更新 Pod。ReplicaSet 与 Replication Controller 的唯一区别是支持更灵活的标签选择器。

    在实际应用中,虽然 ReplicaSet 可以单独使用,但一般建议使用 Deployment 来自动管理 ReplicaSet,除非自定义的 Pod 不需要更新或有其他特殊编排需求。
编辑 Replicaset 文件

# replicaset-example.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
      - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
        - name: php-redis
          image: nginx:1.7.9
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
          env:
            - name: GET_HOSTS_FROM
              value: dns
          ports:
            - containerPort: 80
  • matchExpressions 是一个列表,其中可以包含多个匹配表达式。这里的例子只包含了一个表达式。
  • - 表示列表中的一个条目。
  • {key:tier,operator:In,values:[frontend]}这是一个具体的匹配表达式,它包含以下几个部分:
  • key:标签键(label key),这里是 tier。
  • operator:匹配操作符,在这里为In,表示“在...之中”
  • values:匹配值列表,这里只有一个值[frontend]
  • requests:代表容器启动请求的资源限制,分配的资源必须要达到此要求
  • limits:代表最多可以请求多少资源

创建 RS

kubectl create -f replicaset-example.yaml

kubectl get pod

kubectl delete -f replicaset-example.yaml

二:无状态应用管理 Deployment

无状态服务的定义

    无状态服务(Stateless Service)是指处理请求时不依赖其他请求或本地存储的状态,所有必要信息都包含在请求中或从外部存储(如数据库)获取。服务器本身不保留任何与请求相关的数据。

无状态服务的特点

  • 数据管理

    • 不在本地存储持久化数据,多个实例共享相同的外部数据源(如数据库或分布式缓存)。

  • 请求处理

    • 同一请求的多个实例返回的响应完全一致。

  • 实例关系

    • 实例之间无依赖关系,动态启停某个Pod不会影响其他Pod。

  • 示例

    • 常见的无状态服务包括Nginx、Tomcat、Web应用等。

Kubernetes 相关资源

  • ReplicaSet

    • 确保指定数量的Pod副本始终运行。

  • ReplicationController(旧版)

    • 功能类似ReplicaSet,但逐步被淘汰。

  • Deployment(推荐)

    • 管理ReplicaSet,提供声明式更新、滚动升级、回滚等高级功能,适合生产环境。

无状态Pod的特性

  • 创建与命名

    • Pod的创建没有固定顺序,名称随机生成。

    • 重启后Pod的名称和IP会发生变化。

  • 存储

    • 多个Pod共享外部存储(如PVC或分布式文件系统)。

  • 扩缩容

    • 扩容时随机创建Pod,缩容时随机删除Pod(因所有实例无状态差异)。

Deployment 的核心优势

  • 声明式管理

    • 通过YAML定义Pod和ReplicaSet,由Kubernetes自动维护状态。

  • 滚动更新与回滚

    • 支持无缝升级版本,失败时可快速回滚到上一版本。

  • 自动扩缩容

    • 根据负载动态调整Pod数量(结合HPA)。

  • 故障恢复

    • 自动替换异常Pod,确保服务可用性。

无状态服务的应用场景

  • 微服务架构

    • 如Spring Cloud、Dubbo等服务,适合无状态化部署。

  • 静态资源服务

    • Web前端、API网关等。

  • 实时计算任务

    • 无状态数据处理(如日志分析、实时流计算)。

创建 Deployment

vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - name: nginx
          containerPort: 80
  • replicas: pod 的副本数
  • selector: 定义 Deployment 如何找到要管理的 Pod,与 template 的 label 标签对应。
  • template:
  • app: nginx 使用 label 标记 pod
  • spec: 定义 pod 的详细信息
  • name: nginx 表示 pod 运行一个名字为 nginx 的容器
  • image: 运行此 pod 使用的镜像
  • port: 容器用于发送和接收流量的端口
使用 kubectl create 创建此 Deployment

kubectl create -f nginx-deployment.yaml

查看 Deployment 的状态

kubectl get deploy

使用 rollout 查看整个 Deployment 的创建过程状态

kubectl rollout status deployment/nginx-deployment

查看这个 Deployment 对应的 RS

kubectl get rs -1 app=nginx

查看此 Deployment 创建的 pod

kubectl get pods --show-labels

更新 Deployment

(1) 更新pod的image

kubectl set image deployment nginx-deployment nginx=nginx:1.9.1 --record

kubectl set image deployment nginx-deployment nginx=nginx:1.12.0 --record

(2) 查看更新过程

kubectl rollout status deployment.v1.apps/nginx-deployment

(3) 此时的RS有新的和旧的

kubectl get rs

NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-6cf9b75cdd   0         0         0       3m57s
nginx-deployment-7569c477b6   0         0         0       3m8s
nginx-deployment-96bfc8b67    2         2         2       3m4s

(4) 通过 describe 查看 deployment 的详细信息

kubectl describe deploy nginx-deployment

回滚 deplovment

(1) 多更新几次 deployment

kubectl set image deployment nginx-deployment nginx=dotballo/canary:v1 --record
kubectl set image deployment nginx-deployment nginx=dotballo/canary:v2 --record

(2) 查看更新历史

kubectl rollout history deployment/nginx-deployment

备注:
最后的一个版本是当前版本

(3) 查看某次更新的详情
kubect1 rollout history deployment/nginx-deployment --revision=2

(4) 回滚到指定版本
kubect1 rollout undo deployment/nginx-deployment --to-revision=2

查看回滚结果:
kubect1 rollout history deployment/nginx-deployment

(5) 回滚到上次版本
kubect1 rollout undo deployment/nginx-deployment

查看回滚结果:
kubect1 rollout history deployment/nginx-deployment

扩容 deployment

调整 pod 的副本数

kubectl scale deployment.v1.apps/nginx-deployment --replicas=3

查看扩容结果:
kubectl get pods

删除 Deployment

kubectl delete -f nginx-deployment.yaml

三:有状态应用管理 statefulset

特性 无状态服务(Deployment) 有状态服务(StatefulSet)
定义 不依赖本地状态,请求可被任意实例处理,数据存储在外部(如DB、Redis)。 依赖本地状态,Pod 有唯一标识,数据持久化存储,适用于分布式数据库、消息队列等。
适用场景 Web 服务(Nginx、Tomcat)、无状态微服务、API 网关。 数据库(MySQL、MongoDB)、消息队列(Kafka、RabbitMQ)、协调服务(ZooKeeper、ETCD)。
Pod 特性
命名规则 随机生成(如 web-1234),重启后变化。 固定序号(如 mysql-0mysql-1),名称不变。
网络标识 动态 IP 和 DNS,重启后可能变化。 固定 DNS(..namespace.svc.cluster.local),Pod 重新调度后仍可访问。
存储 无本地存储,依赖外部存储(如云存储、数据库)。 每个 Pod 绑定独立的 PV(持久卷),数据持久化,重启后仍挂载原存储。
扩缩容行为
扩容 随机创建新 Pod,无顺序要求。 按顺序创建(如先 mysql-0,再 mysql-1)。
缩容 随机删除 Pod,无数据风险。 按逆序删除(先删 mysql-1,再 mysql-0),需手动清理 PVC 避免数据残留。
更新策略 支持滚动更新(RollingUpdate),可一键回滚。 按顺序更新(先更新从节点,再更新主节点),需确保数据兼容性。
典型控制器 Deployment(管理 ReplicaSet)。 StatefulSet(管理有状态 Pod)。
高可用与数据一致性 无状态,请求可被任意实例处理,适合水平扩展。 需考虑数据一致性(如主从同步、选举机制),Pod 故障可能导致数据不一致。
运维复杂度 简单,适合快速扩缩容和自动化运维。 复杂,需管理存储、备份、节点拓扑关系。

编写 statefulset 资源文件

(1) 定义一个 statefulset 资源文件
vim redis-statefulset.yaml

apiVersion: v1
kind: Service
metadata:
    name: redis-svc
spec:
    selector:
    app: redis-sts
ports:
    - port: 6379
    protocol: TCP
    targetPort: 6379
apiVersion: apps/v1
kind: StatefulSet
metadata:
    name: redis-sts
spec:
    serviceName: redis-svc
replicas: 2
selector:
    matchLabels:
    app: redis-sts

template:
    metadata:
    labels:
    app: redis-sts
spec:
    containers:
    - image: redis:5-alpine
    name: redis
    ports:
    - containerPort: 6379

备注:

  • kind:Service 定义了一个名字为redis-svc 的服务:
  • kind: statefulset 定义了一个名字为redis-sts 的 Statefulset,replicas 表示部署 Pod的副本数。
(2) 创建 statefulSet

kubectl create -f redis-statefulset.yaml

(3) 查看 statefilset 状态

kubectl get sts

(4) 查看群集状态

kubectl get service

kubectl get po -1 app=redis-sts

NAME    READY   STATUS   RESTARTS   AGE
redis-sts-0  1/1   Running  0    5m38s
redis-sts-1  1/1   Running  0    4m55s
  • -l:指定标签(label)

    注意 NAME 列,名称是 sts 的 name-序号,这里序号越小则说明创建的越早从 AGE 列也可以看出来,这就解决了有状态应用中的启动顺序问题,比如可以让 redis-sts-0作为redis 的主节点,redis-sts-1作为从节点

statefulset扩容

(1) 扩容,将副本数修改为 3

kubectl scale sts redis-sts --replicas=3

ku get pod

NAME    READY   STATUS   RESTARTS   AGE
redis-sts-0    1/1    Running   0    7m50s
redis-sts-1    1/1    Running   0    7m7s
redis-sts-2    1/1    Running   0    6s

缩容

(1) 打开第二个终端,动态显示缩容流程

kubectl get pods -w -l app=redis-sts

备注:

-w: 动态监听所有的 pod

(2) 在原来第一个终端修改副本数为 2

19

kubectl patch sts redis-sts -p '{"spec":{"replicas":2}}'

注意:

此时可以查看第二个终端上的变化

(3)在第一个终端上查看最终结果

kubectl get pods -1 app=redis-sts

非级联删除 statefulset

    删除 statefulset 有两种方式:级联删除和非级联删除。

    使用非级联方式删除 statefulset 时,statefulset 的 Pod 不会被删除。使用级联方式删除Statefulset 时,statefulset 和它的Pod 都会被删除。

(1)采用非级联删除

kubectl delete statefulset redis-sts --cascade=false

查看删除结果:

kubectl get sts

(2)查看管理的 pod

kubectl get po

发现 pod 并没有被删除

(3)删除 pod

kubectl delete po redis-sts-0

kubectl delete po redis-sts-1

级联删除 statefulset

(1) 先创建出 statefulset

kubectl create -f redis-statefulset.yaml

(2) 级联删除

kubectl delete statefulset redis-sts

查看
kubectl get po

两个 pod 全都没了

(3) 删除 redis 服务

kubectl delete -f redis-statefulset.yaml

四:守护进程集 Daemonset

1:什么是 Daemonset

    有时候我们需要在每个 Kubernetes 节点或符合条件的节点上都部署某个应用,那么就可以使用Kubernetes 的 Daemonset 调度 Pod。Daemonset 确保全部(或符合条件)的节点上运行一个 Pod 副本当有新的节点加入集群时,也会为他们新增一个 Pod,当节点从集群中移除时,这些 Pod 会被回收,删除Daemonset 将会删除它创建的所有的 Pod。

2:定义一个 Daemonset

cat daemonset-nginx.yaml

apiVersion: apps/v1

kind: DaemonSet

metadata:
  name: pod-controlled
  namespace: dev
  labels:
    controller: daemonset

spec:
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP

3:创建 DaemonSet

kubectl create namespace dev
kubectl create -f daemonset-nginx.yaml

4:查看 DaemonSet

kubectl get ds -n dev -o wide

NAME          DESTRED    CURRENT    READY    UP-TO-DATE    AVAILABLE    NODE SELECTOR    AGE     CONTAINERS    IMAGES         SELECTOR
pod-controller    3        3        3        3            3                     3m8s    nginx        nginx:latest    app=nginx-pod

5:查看 pod 所在的节点

kubectl get pod -n dev -o wide

6:删除 DaemonSet

kubectl delete ds pod-controller -n dev

五:CronJob

    Cronjob(计划任务,缩写为 cj)用于以时间为基准的周期性地执行任务,这些自动化任务和运行在 Linux 系统上的 cronJob 一样。

创建 CronJob

(1)编辑 Cronjob 文件

cat cronjob-example.yaml

apiVersion: batch/v1 #1.21 版本以上  改为 batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * * "
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:v1
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

备注:

    这个案例会在每分钟执行一次计划任务,

    并输出当前时间和“Hello from the Kubernetes cluster

(2) 创建 Cronjob

kubectl create -f cronjob-example.yaml

(3) 查看创建结果

kubectl get cj

NAME    SCHEDULE    SUSPEND   ACTIVE   LAST  SCHEDULE   AGE
hello  */1  *  *  *  False    0    485    945

等待一会后可以查看生成的 pod

kubectl get jobs

NAME    COMPLETIONS   DURATION   AGE
hello-27743514  1/1    20s    74s
hello-27743515  0/1    14s    14s

(4) 查看生成的 pod,并查看 pod 的执行日志

kubect1 get pod

kubect1 logs -f hello-27743522-crnf8

Sat Oct  1 08:02:16 UTC 2022
Hello from the Kubernetes cluster

(5) 删除 Cronjob

kubect1 delete cronjob hello

你可能感兴趣的:(Kubernetes Pod 调度基础)