k8s Pod控制器详解(服务发现,Deployment,StatefulSet,DaemonSet,Job,CronJob 控制器功能及部署 示例)

目录

一、pod控制器概念

pod和控制器的关系

作用

pod控制器的类型组成及特点

Pod控制器的类型:

Pod与控制器的关系:

[二、 k8s中的服务发现](#二、 k8s中的服务发现)

安装CoreDNS(仅二进制部署环境需要安装CoreDNS)

[方法一 下载并配置](#方法一 下载并配置)

[方法二 上传配置文件](#方法二 上传配置文件)

[三、 Deployment(更新资源)控制器](#三、 Deployment(更新资源)控制器)

[编辑和查看Kubernetes Deployment的配置和历史版本](#编辑和查看Kubernetes Deployment的配置和历史版本)

[四、 StatefulSet(管理有状态应用)控制器](#四、 StatefulSet(管理有状态应用)控制器)

常见应用场景:数据库

[StatefulSet 的三个关键组成部分及其作用](#StatefulSet 的三个关键组成部分及其作用)

清单定义StatefulSet

[创建、管理和删除 StatefulSet](#创建、管理和删除 StatefulSet)

[创建 StatefulSet:](#创建 StatefulSet:)

查看无头服务:

[查看 StatefulSet:](#查看 StatefulSet:)

[查看 PVC 绑定:](#查看 PVC 绑定:)

[查看 PV 绑定:](#查看 PV 绑定:)

[查看 Pod 信息:](#查看 Pod 信息:)

[删除 StatefulSet:](#删除 StatefulSet:)

[观察 Pod 删除过程:](#观察 Pod 删除过程:)

[重新创建 StatefulSet:](#重新创建 StatefulSet:)

[再次查看 PVC 绑定:](#再次查看 PVC 绑定:)

创建PV

创建共享目录:stor01节点

[配置 NFS 共享:](#配置 NFS 共享:)

[重启 NFS 服务:](#重启 NFS 服务:)

重新导出共享:

查看共享列表:

定义pv

创建

[应用 PV 定义:](#应用 PV 定义:)

[获取 PV 列表](#获取 PV 列表)

滚动更新

[修改 StatefulSet 配置:](#修改 StatefulSet 配置:)

应用更新:

观察滚动更新过程:

[在 Pod 内部解析其他 Pod 的名称:](#在 Pod 内部解析其他 Pod 的名称:)

[解析 Pod 名称到 IP 地址:](#解析 Pod 名称到 IP 地址:)

扩容和伸缩操作

[扩容 StatefulSet:](#扩容 StatefulSet:)

动态查看扩容过程:

[查看 PersistentVolumes (PV):](#查看 PersistentVolumes (PV):)

[缩容 StatefulSet:](#缩容 StatefulSet:)

动态查看缩容过程:

[无状态和有状态应用以及常规 Service 和 Headless Service 的区别总结](#无状态和有状态应用以及常规 Service 和 Headless Service 的区别总结)

[无状态应用(Stateless Applications):](#无状态应用(Stateless Applications):)

[有状态应用(Stateful Applications):](#有状态应用(Stateful Applications):)

[常规 Service(ClusterIP Service):](#常规 Service(ClusterIP Service):)

[Headless Service:](#Headless Service:)

综合举例

[创建测试 Pod (dns-test):](#创建测试 Pod (dns-test):)

[创建无头服务 (nginx):](#创建无头服务 (nginx):)

[创建 StatefulSet (nginx-statefulset):](#创建 StatefulSet (nginx-statefulset):)

应用配置:

查看资源:

[DNS 解析测试:](#DNS 解析测试:)

[在 StatefulSet Pod 内部进行通信测试:](#在 StatefulSet Pod 内部进行通信测试:)

[五、 DaemonSet(工作负载)控制器](#五、 DaemonSet(工作负载)控制器)

关键特性:

典型用例:

应用场景:

官方案例(监控):

示例

[创建 DaemonSet 配置文件 (ds.yaml):](#创建 DaemonSet 配置文件 (ds.yaml):)

[应用 DaemonSet 配置:](#应用 DaemonSet 配置:)

[查看 Pod 列表:](#查看 Pod 列表:)

[六、 Job(特殊的工作负载)控制器](#六、 Job(特殊的工作负载)控制器)

[普通 Job(Job):](#普通 Job(Job):)

定时任务(CronJob):

应用场景:

官方文档链接:

示例

[拉取 Perl 镜像:](#拉取 Perl 镜像:)

[应用 Job 配置:](#应用 Job 配置:)

[查看 Pod 状态:](#查看 Pod 状态:)

[查看 Job 结果:](#查看 Job 结果:)

[删除 Job 资源:](#删除 Job 资源:)

[设置 Job 的重试次数 (job-limit.yaml):](#设置 Job 的重试次数 (job-limit.yaml):)

[应用 Job 配置并查看状态:](#应用 Job 配置并查看状态:)

[查看 Job 描述:](#查看 Job 描述:)

[七、 CronJob(管理周期性任务的工作负载)控制器](#七、 CronJob(管理周期性任务的工作负载)控制器)

[CronJob 的关键特性:](#CronJob 的关键特性:)

应用场景:

官方文档链接:

示例

[创建 CronJob 配置文件 (cronjob.yaml):](#创建 CronJob 配置文件 (cronjob.yaml):)

[创建 CronJob:](#创建 CronJob:)

[查看 CronJob 状态:](#查看 CronJob 状态:)

[查看执行的 Pod:](#查看执行的 Pod:)

[查看 Pod 日志:](#查看 Pod 日志:)

解决日志查看权限问题:


一、pod控制器概念

在 Kubernetes 中,Pod 控制器是一种管理 Pod 的中间层。使用 Pod 控制器,只需告诉它想要多少个什么样的 Pod,它会创建出满足条件的 Pod 并确保每个 Pod 资源处于用户期望的目标状态。如果 Pod 在运行中出现故障,控制器会根据指定策略重新编排或重建 Pod。常见的 Pod 控制器包括 ReplicaSet、Deployment、StatefulSet 等,每种都适用于不同的场景和需求。

Pod控制器,又称之为工作负载(workload),是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。

pod和控制器的关系

Pod和控制器在Kubernetes中的关系是相互依赖的。Pod是Kubernetes中的基本工作单元,而控制器则是用来管理Pod生命周期和行为的高级抽象。下面是它们之间的关系:

  • 管理关系

  • 控制器通过定义期望的状态(如Pod的数量、配置等)来管理Pod。控制器会监视Pod的实际状态,并在发现任何偏差时采取措施来恢复到期望状态。

  • 生命周期管理

  • 当Pod因为某些原因(如节点故障、Pod崩溃等)无法正常运行时,控制器会根据其策略(如重启、替换等)来处理这些Pod,确保应用的高可用性。

  • 自动化操作

  • 控制器可以自动执行滚动更新、回滚、扩缩容等操作,这些操作通常涉及到Pod的创建、删除和更新。

  • 标签和选择器

  • Pod通过标签(Labels)与控制器关联。控制器使用标签选择器(Label Selector)来识别它所管理的Pod。这样,控制器就可以对一组具有相同标签的Pod执行操作。

  • 服务发现

  • 控制器(如Deployment或StatefulSet)可以与服务(Service)关联,服务负责为Pod提供稳定的网络标识和负载均衡。这样,其他Pod或外部客户端可以通过服务来访问这些Pod,而不需要知道具体的Pod信息。

  • 持久化存储

  • 对于需要持久化数据的Pod,控制器(如StatefulSet)会管理与这些Pod关联的持久化存储卷(PersistentVolumes和PersistentVolumeClaims),确保Pod在重启或迁移后能够访问到其数据。

  • 任务执行

  • 对于一次性任务(Job)或周期性任务(CronJob),控制器负责调度这些任务的执行,并在任务完成后进行清理。

  • 声明式配置

  • 用户通过定义控制器的配置(如Deployment的YAML文件),控制器会根据这些声明式配置来管理Pod。这种方式使得用户可以专注于期望的结果,而不是具体的操作步骤。

总结来说,Pod是Kubernetes中执行应用的实体,而控制器则是负责确保这些Pod按照用户定义的期望状态运行的管理者。控制器通过自动化和声明式配置,简化了Pod的管理,提高了集群的运维效率。

作用

  • 确保期望状态:Pod控制器负责确保Pod的运行状态与用户定义的期望状态相匹配。如果Pod因为某些原因(如节点故障、Pod崩溃等)与期望状态不一致,控制器会采取措施来恢复Pod,使其回到期望状态。

  • 自动重启:当Pod失败或被删除时,Pod控制器会根据其配置自动重启Pod,以保证Pod的数量和状态符合用户的设定。

  • 滚动更新:对于Deployment和StatefulSet等控制器,它们支持滚动更新(Rolling Update)策略,这意味着在更新Pod时,旧的Pod会逐渐被新的Pod替换,而不会一次性全部替换,从而减少服务中断时间。

  • 回滚:如果更新后的Pod出现问题,Pod控制器允许用户回滚到之前的版本,以恢复服务。

  • 扩缩容:Pod控制器可以根据负载或其他策略自动调整Pod的副本数量,实现水平伸缩(Horizontal Scaling)。

  • 有序管理:对于有状态的Pod(如StatefulSet管理的Pod),控制器确保Pod的创建、更新和删除是有序进行的,以维护Pod的顺序和状态。

  • 服务发现:通过与服务(Service)的配合,Pod控制器帮助实现服务发现,使得Pod可以通过DNS名称被其他Pod或服务发现和访问。

  • 持久化存储管理:对于需要持久化存储的Pod,Pod控制器可以与PersistentVolumes和PersistentVolumeClaims配合,确保Pod的存储需求得到满足,并且在Pod重新调度后仍然能够访问到相同的持久化数据。

  • 任务调度:Job和CronJob控制器用于执行一次性任务或周期性任务,Pod控制器在这里负责调度和管理这些任务的执行。

总的来说,Pod控制器是Kubernetes中实现应用部署、运维和管理的关键组件,它通过自动化和声明式配置,简化了集群资源的管理,提高了应用的可靠性和可维护性。

pod控制器的类型组成及特点

Pod控制器的类型

  • ReplicaSet:ReplicaSet(RS)确保指定数量的Pod副本始终运行。它通过标签选择器来识别和管理Pod,并且可以根据需要自动创建或删除Pod。ReplicaSet通常不直接使用,而是通过Deployment来间接管理。

  • 用户期望的Pod副本数量:这是ReplicaSet的核心目标,它定义了用户希望在集群中运行的Pod实例的数量。ReplicaSet会监控当前运行的Pod数量,并根据这个目标数量进行调整。如果Pod数量少于期望值,ReplicaSet会创建新的Pod;如果多于期望值,它会删除多余的Pod。

  • 标签选择器(Label Selector):标签选择器是一个过滤条件,它定义了哪些Pod应该由ReplicaSet管理。在Kubernetes中,每个Pod都可以被赋予一系列的标签(key-value对),而ReplicaSet通过标签选择器来识别这些Pod。只有匹配标签选择器的Pod才会被ReplicaSet视为其管理的对象。

  • Pod资源模板:当需要创建新的Pod时,ReplicaSet会使用这个模板来生成Pod的定义。这个模板包含了Pod的规格,如容器镜像、环境变量、存储卷等。ReplicaSet会根据这个模板创建新的Pod实例,以确保Pod的配置与用户期望的一致。

  • ReplicaSet通常不直接由用户创建和管理,而是通过Deployment来间接管理。Deployment是一个更高级别的抽象,它允许用户声明式地定义应用的期望状态,包括副本数量、更新策略等。Deployment会自动创建和管理ReplicaSet,以确保应用的稳定运行。这种方式简化了用户的管理操作,使得用户无需直接处理ReplicaSet的细节。

  • Deployment:Deployment是Kubernetes中用于声明式更新的高级API对象。它管理ReplicaSet,允许用户声明期望的Pod副本数量和更新策略,如滚动更新。Deployment支持回滚到之前的版本,并且提供了声明式配置,使得应用的部署和管理更加简单和直观。

  • 声明式更新策略:允许用户定义如何更新Pod,例如滚动更新(Rolling Update)。

  • 回滚机制:支持用户回滚到之前的部署版本。

  • ReplicaSet管理:Deployment对象管理一个或多个ReplicaSet对象,确保Pod的副本数量符合期望状态。

  • 声明式配置:用户通过Deployment的声明来定义应用的期望状态,Kubernetes会自动调整实际状态以匹配期望状态。

  • DaemonSet:DaemonSet确保Pod副本在集群中的所有(或某些)节点上运行。这通常用于运行系统级服务,如日志收集或监控代理。DaemonSet确保这些服务在每个节点上都有一个实例,即使在节点重启后也能自动恢复。

  • Pod模板:定义DaemonSet中Pod的规格和配置。

  • 选择节点的策略:DaemonSet确保在集群中的每个节点上都运行一个Pod的副本,除非节点被明确排除。

  • 控制逻辑:DaemonSet控制器负责在新节点加入集群时创建Pod,并在节点不再需要DaemonSet时删除Pod。

  • StatefulSet:StatefulSet用于管理有状态的分布式应用。与Deployment不同,StatefulSet提供了稳定的持久化存储、唯一的网络标识符(如DNS名)以及有序的部署和扩展。

  • Pod模板:定义StatefulSet中Pod的规格和配置。

  • 稳定的持久化存储:为每个Pod提供稳定的持久化存储,通常通过PersistentVolumes实现。

  • 有序部署和扩展:StatefulSet支持有序地部署和扩展Pod,这对于有状态的应用非常重要。

  • 唯一网络标识符:每个Pod都有一个稳定的DNS名称,这对于服务发现和负载均衡很有用。

  • Job:Job负责运行一次性任务。当Pod成功终止时,Job完成。Job适用于批处理任务,如数据处理或备份。

  • Pod模板:定义Job执行任务所需的Pod规格和配置。

  • 完成条件:定义何时Job被认为是完成的,例如所有Pod成功终止。

  • 重试策略:可以设置失败时的重试次数和重试间隔。

  • CronJob:CronJob用于管理周期性运行的任务。它基于时间表(Cron格式)来调度Job的执行。CronJob可以创建Job对象来执行周期性任务,非常适合定时任务。

  • 定时执行的Job:CronJob定义了一个定时任务,它会按照Cron格式的时间表周期性地创建Job。

  • Cron格式的调度:用户可以定义Cron表达式来指定Job的执行时间。

  • Job管理:CronJob控制器负责根据调度创建Job,并在Job完成后进行清理。

Pod与控制器的关系

  • Pod通过label-selector与控制器关联,控制器负责应用的运维,如伸缩和升级。

二、 k8s中的服务发现

在 Kubernetes (K8S) 中,服务发现是一个关键特性,它允许集群内的服务和应用相互发现和通信。这对于构建动态、可扩展的微服务架构至关重要。

  • 服务发现的需求

  • 动态性:Pod 可能会因为各种原因(如调度、节点故障等)在集群的不同节点之间移动。

  • 频繁更新和发布:现代应用开发强调快速迭代和持续部署,这要求服务能够在不停机的情况下进行更新和扩展。

  • 自动伸缩:在负载增加时,如促销活动期间,应用需要能够自动扩展以处理更多的请求。

  • Kubernetes DNS 服务

  • Kubernetes 使用 DNS 作为服务发现的主要机制。当创建一个 Service 时,Kubernetes 会自动为它创建一个 DNS 记录,使得集群内的其他服务可以通过这个 DNS 名称来发现和访问它。

  • Service 的 DNS 名称通常遵循 服务名.命名空间.svc.cluster.local 的格式,例如 my-service.default.svc.cluster.local

  • DNS 插件的演变

  • skyDNS:在 Kubernetes 1.3 版本之前,skyDNS 是集群内部 DNS 服务的实现。

  • kubeDNS:从 Kubernetes 1.3 到 1.11 版本,kubeDNS 成为了官方推荐的 DNS 插件。它提供了更好的性能和稳定性。

  • CoreDNS:从 Kubernetes 1.11 版本开始,CoreDNS 成为了默认的 DNS 插件。CoreDNS 是一个更现代、更灵活的 DNS 服务器,它支持更多的功能和插件。

  • CoreDNS 的特点

  • CoreDNS 是一个可扩展的 DNS 服务器,它允许通过插件来添加新的功能。

  • 它提供了对 DNS 记录的更细粒度控制,例如可以为不同的 Service 类型(如 ClusterIP、NodePort、LoadBalancer)配置不同的 DNS 策略。

  • CoreDNS 还支持 DNSSEC,这是一个安全特性,可以为 DNS 查询提供加密和验证。

通过这些 DNS 插件,Kubernetes 集群能够实现服务的自动发现,这对于构建和管理大规模的分布式应用非常重要。开发者和运维人员可以依赖于这种内置的服务发现机制,而无需担心服务的网络位置变化。

安装CoreDNS(仅二进制部署环境需要安装CoreDNS)

使用 sed 命令来修改 CoreDNS 配置文件的示例。这个过程通常用于将 CoreDNS 的基础模板文件 coredns.yaml.base 转换为一个特定的配置文件,以便在 Kubernetes 集群中部署 CoreDNS。

方法一 下载并配置

  • 下载 CoreDNS 配置模板

    下载链接:https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base

  • 这个链接指向 Kubernetes 项目中的 CoreDNS 配置模板文件 coredns.yaml.base。这个文件是 CoreDNS 的默认配置模板,包含了 CoreDNS 的基本设置。

  • 创建一个 sed 脚本文件

    vim transforms2sed.sed
    s/DNS__SERVER/10.0.0.2/g
    s/DNS__DOMAIN/cluster.local/g
    s/DNS__MEMORY__LIMIT/170Mi/g
    s/MACHINE_GENERATED_WARNING/Warning: This is a file generated from the base underscore template file: coredns.yaml.base/g

  • 创建了一个名为 transforms2sed.sed 的文件,这个文件包含了一系列的 sed 替换命令。这些命令用于修改 coredns.yaml.base 文件中的特定占位符。

  • 使用 sed 命令进行替换

    sed -f transforms2sed.sed coredns.yaml.base > coredns.yaml

  • _DNS__SERVER__ 替换为 CoreDNS 的服务地址(例如 10.0.0.2)。

  • _DNS__DOMAIN__ 替换为集群的域名(例如 cluster.local)。

  • _DNS__MEMORY__LIMIT__ 替换为 CoreDNS Pod 的内存限制(例如 170Mi)。

  • __MACHINE_GENERATED_WARNING__ 替换为一个警告信息,表明这个文件是由基础模板文件生成的。

  • 使用 sed 命令来读取 coredns.yaml.base 文件,并根据 transforms2sed.sed 文件中的指令进行替换。这里的替换包括:

  • 生成最终的 CoreDNS 配置文件 : 通过上述 sed 命令,将生成一个新的 coredns.yaml 文件,这个文件包含了根据集群环境定制的 CoreDNS 配置。

方法二 上传配置文件

上传 CoreDNS 配置文件并创建 Nginx 服务

  • 创建 Nginx 服务

    kubectl create -f coredns.yaml

    kubectl get pods -n kube-system

    vim nginx-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-service
    labels:
    app: nginx
    spec:
    type: NodePort
    ports:
    - port: 80
    targetPort: 80
    selector:
    app: nginx

  • 创建一个名为 nginx-service.yaml 的文件,定义了一个类型为 NodePort 的 Service,用于暴露 Nginx 应用。

  • 部署 Nginx 服务

    kubectl create -f nginx-service.yaml

  • 使用 kubectl create -f nginx-service.yaml 命令部署 Nginx 服务。

  • 检查服务

    kubectl get svc

  • 使用 kubectl get svc 命令查看服务列表,确认 Nginx 服务的 ClusterIP 和 NodePort。

  • 创建测试 Pod

    vim pod6.yaml
    apiVersion: v1
    kind: Pod
    metadata:
    name: dns-test
    spec:
    containers:
    - name: busybox
    image: busybox:1.28.4
    args:
    - /bin/sh
    - -c
    - sleep 36000
    restartPolicy: Never

  • 创建一个名为 .yaml 的文件,定义了一个包含 busybox 容器的 Pod,该容器将用于测试服务发现。

  • 部署测试 Pod

    kubectl create -f pod6.yaml

  • 使用 kubectl create -f pod.yaml 命令部署测试 Pod。

  • 测试服务发现

    //解析kubernetes和nginx-service名称
    kubectl exec -it dns-test sh

    //查看statefulset的定义
    kubectl explain statefulset

    kubectl explain statefulset.spec
    KIND: StatefulSet
    VERSION: apps/v1

    RESOURCE: spec <Object>

    DESCRIPTION:
    Spec defines the desired identities of pods in this set.

       A StatefulSetSpec is the specification of a StatefulSet.
    

    FIELDS:
    podManagementPolicy <string> #Pod管理策略
    replicas <integer> #副本数量
    revisionHistoryLimit <integer> #历史版本限制
    selector <Object> -required- #选择器,必选项
    serviceName <string> -required- #服务名称,必选项
    template <Object> -required- #模板,必选项
    updateStrategy <Object> #更新策略
    volumeClaimTemplates <[]Object> #存储卷申请模板,必选项

  • dns-test Pod 中,可以使用 nslookupdig 命令来测试对 Nginx 服务的 DNS 解析。例如,可以在 busybox 容器中执行 nslookup nginx-service 来查看 Nginx 服务的 IP 地址。


三、 Deployment(更新资源)控制器

vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx    
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4
        ports:
        - containerPort: 80

kubectl create -f nginx-deployment.yaml

kubectl get pods,deploy,rs

一个Deployment资源的定义文件,用于在Kubernetes集群中部署一个名为nginx-deployment的Nginx web服务。这个Deployment配置了3个Nginx Pod副本,并且使用了标签app: nginx来标识和管理这些Pod。下面是这个Deployment的详细解释和如何使用kubectl命令来创建和管理它。

Deployment配置文件解释

  • apiVersion: apps/v1:指定了Kubernetes API的版本。

  • kind: Deployment:表明这是一个Deployment资源。

  • metadata:包含了Deployment的名称和标签。

  • spec:定义了Deployment的规格。

  • replicas:设置期望的Pod副本数量为3。

  • selector:使用matchLabels来选择具有相同标签的Pod。

  • template:定义了Pod模板,包括Pod的元数据和规格。

    • metadata:Pod的标签与Deployment的标签匹配。

    • spec:定义了Pod的容器规格,包括容器名称、镜像和端口。

使用kubectl命令创建Deployment

保存文件后,使用以下命令创建Deployment:

kubectl create -f nginx-deployment.yaml

创建Deployment后,可以使用以下命令查看相关的Pod、Deployment和ReplicaSet:

kubectl get pods,deploy,rs

这个命令会列出由该Deployment管理的所有Pod,Deployment本身的信息,以及与之关联的ReplicaSet。

应用场景

Deployment非常适合部署和管理无状态的应用,如web服务器、缓存服务器等。它的滚动更新和回滚功能使得应用的持续部署和维护变得简单。

声明式更新

Deployment支持声明式更新,这意味着可以在Deployment的YAML文件中指定新的镜像版本,然后应用这个更新。Kubernetes会自动创建新的ReplicaSet和Pod,逐步替换旧的Pod,直到所有Pod都更新到新的版本。

示例中的Deployment

在示例中,Deployment使用了Nginx的Docker镜像nginx:1.15.4。如果想要更新这个镜像到新版本,只需修改YAML文件中的image字段,然后重新应用配置即可。Kubernetes会自动处理更新过程。

编辑和查看Kubernetes Deployment的配置和历史版本

kubectl edit deployment/nginx-deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2021-04-19T08:13:50Z"
  generation: 1
  labels:
    app: nginx                    #Deployment资源的标签
  name: nginx-deployment
  namespace: default
  resourceVersion: "167208"
  selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx-deployment
  uid: d9d3fef9-20d2-4196-95fb-0e21e65af24a
spec:
  progressDeadlineSeconds: 600
  replicas: 3                    #期望的pod数量,默认是1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%                #升级过程中会先启动的新Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
      maxUnavailable: 25%        #升级过程中在新的Pod启动好后销毁的旧Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
    type: RollingUpdate            #滚动升级
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx                #Pod副本关联的标签
    spec:
      containers:
      - image: nginx:1.15.4                #镜像名称
        imagePullPolicy: IfNotPresent    #镜像拉取策略
        name: nginx
        ports:
        - containerPort: 80                #容器暴露的监听端口
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always                #容器重启策略
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
......
  • 编辑Deployment配置 : 使用kubectl edit命令可以直接在默认编辑器中修改Deployment的配置。在例子中,查看了名为nginx-deployment的Deployment的配置。这个配置文件包含了Deployment的各种设置,例如:

  • replicas:期望的Pod副本数量。

  • selector:用于选择Pod的标签选择器。

  • strategy:定义了更新策略,这里使用的是RollingUpdate,它指定了在升级过程中新Pod的最大数量(maxSurge)和旧Pod的最大不可用数量(maxUnavailable)。

  • template:定义了Pod模板,包括容器的镜像、端口和其他规格。

    kubectl rollout history deployment/nginx-deployment
    deployment.apps/nginx-deployment
    REVISION CHANGE-CAUSE
    1 <none>

  • 查看历史版本 : 使用kubectl rollout history命令可以查看Deployment的历史版本和变更原因。在您的例子中,Deployment的当前版本是1,没有提供变更原因。这意味着Deployment自创建以来没有经历过任何更新。


四、 StatefulSet(管理有状态应用)控制器

StatefulSet 是 Kubernetes 中用于管理有状态应用的控制器。它为每个 Pod 提供了一个持久化的身份,这对于需要持久化存储或稳定网络标识的应用非常有用。

  • 稳定的持久化存储:StatefulSet 通过 Persistent Volume Claims (PVCs) 为每个 Pod 提供稳定的存储。即使 Pod 被重新调度到其他节点,它仍然能够访问到相同的持久化数据。

  • 稳定的网络标识:StatefulSet 通过 Headless Service 为每个 Pod 提供稳定的网络标识。这意味着即使 Pod 被重新调度,其 PodName 和 HostName 也不会改变。

  • 有序部署和扩展:StatefulSet 确保 Pod 是有序创建的,即从 0 到 N-1 的顺序。在下一个 Pod 运行之前,所有之前的 Pod 必须都是 Running 和 Ready 状态。

  • 有序收缩和删除:StatefulSet 也确保 Pod 是有序删除的,即从 N-1 到 0 的顺序。

  • Pod 选择器和模板:StatefulSet 使用 Pod 选择器来识别它管理的 Pod,并且有一个 Pod 模板来定义 Pod 的规格。

  • 更新策略:StatefulSet 支持滚动更新,允许用户配置和禁用 Pod 的自动化滚动更新。

  • 最小准备时间 :StatefulSet 允许设置 minReadySeconds,指定新创建的 Pod 在被认为是可用之前应该运行和就绪的最小秒数。

  • Pod 索引标签 :StatefulSet 为每个 Pod 创建时,会添加一个 pod-index 标签,其值为 Pod 的序号索引。

  • 部署和扩展保证:StatefulSet 在部署和扩展时,确保所有前驱 Pod 都是 Running 和 Ready 状态,然后才会启动下一个 Pod。在删除 Pod 时,也确保所有后继 Pod 都已完全关闭。

  • Pod 管理策略 :StatefulSet 允许通过 podManagementPolicy 字段放松其顺序保证,同时保留其唯一性和身份保证。

  • 持久卷声明模板 :StatefulSet 使用 volumeClaimTemplates 来定义每个 Pod 应该请求的存储资源。

常见应用场景:数据库

https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

示例定义了一个 Headless Service 和一个 StatefulSet,用于部署一个名为 nginx 的应用。这个 StatefulSet 配置了 3 个副本,每个 Pod 都有一个名为 www 的 PVC,用于存储,并且使用了 nginx-slim 镜像。这个 StatefulSet 还设置了一个 Headless Service 来提供稳定的网络标识。


StatefulSet 的三个关键组成部分及其作用

StatefulSet 的设计是为了满足有状态应用的需求,这些应用通常需要持久化存储和稳定的网络标识。

  • Headless Service

  • 目的:Headless Service 用于为 StatefulSet 中的每个 Pod 提供一个稳定的 DNS 名称。这样,即使 Pod 被重新调度到其他节点,它的 DNS 名称也不会改变,从而保证了网络标识的稳定性。

  • 实现 :Headless Service 不分配 Cluster IP,而是直接将 DNS 请求解析到对应的 Pod IP。这样,每个 Pod 都有一个基于 StatefulSet 名称和 Pod 序号的 DNS 子域,例如 web-0.nginx.default.svc.cluster.local

  • VolumeClaimTemplates

  • 目的:VolumeClaimTemplates 用于为每个 Pod 提供独立的持久化存储。这样,每个 Pod 都有自己的存储空间,即使在 Pod 重新调度后,也能保持数据的连续性和一致性。

  • 实现:在 StatefulSet 的定义中,可以包含一个或多个 VolumeClaimTemplates。当 StatefulSet 创建 Pod 时,会为每个 Pod 创建相应的 PersistentVolumeClaim (PVC)。这些 PVC 会请求与 StatefulSet 关联的 PersistentVolume (PV),从而为每个 Pod 提供专用的存储卷。

  • StatefulSet 控制器

  • 目的:StatefulSet 控制器负责管理 Pod 的生命周期,确保 Pod 的数量符合用户的期望,并且按照顺序进行部署、扩展和收缩。

  • 实现:StatefulSet 控制器会监控 Pod 的状态,确保每个 Pod 都按照定义的顺序运行。在进行滚动更新时,它会按照顺序逐个更新 Pod,确保在更新下一个 Pod 之前,所有先前的 Pod 都已经就绪。同样,在删除 Pod 时,也会按照相反的顺序进行,以确保服务的平滑过渡。

  • 这三个组件共同工作,使得 StatefulSet 能够为有状态应用提供所需的稳定性和可靠性。Headless Service 解决了网络标识的稳定性问题,VolumeClaimTemplates 解决了持久化存储的需求,而 StatefulSet 控制器则确保了 Pod 的有序管理和更新。这种设计使得 StatefulSet 成为部署和管理有状态应用的理想选择,如数据库、消息队列等。

清单定义StatefulSet

一个完整的 StatefulSet 控制器由一个 Headless Service、一个 StatefulSet 和一个 volumeClaimTemplate 组成

vim stateful-demo.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  labels:
    app: myapp-svc
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  serviceName: myapp-svc
  replicas: 3
  selector:
    matchLabels:
      app: myapp-pod
  template:
    metadata:
      labels:
        app: myapp-pod
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: myappdata
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: myappdata
      annotations:          #动态PV创建时,使用annotations在PVC里声明一个StorageClass对象的标识进行关联
        volume.beta.kubernetes.io/storage-class: nfs-client-storageclass
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 2Gi

stateful-demo.yaml 文件中,定义了一个完整的 StatefulSet 控制器,它包括一个 Headless Service、一个 StatefulSet 和一个 VolumeClaimTemplate。

以下是对这个清单的详细解析:

  • Headless Service (myapp-svc)

  • apiVersion: 使用的 Kubernetes API 版本。

  • kind: 定义的资源类型为 Service。

  • metadata: 资源的元数据,包括名称和标签。

  • spec: Service 的规格。

    • ports: 定义了服务监听的端口(这里是 80 端口)。

    • clusterIP: 设置为 None,表示这是一个 Headless Service,没有 ClusterIP。

    • selector: 用于选择 Pod 的标签选择器,这里选择标签为 app: myapp-pod 的 Pod。

  • StatefulSet (myapp)

  • apiVersion: 使用的 Kubernetes API 版本。

  • kind: 定义的资源类型为 StatefulSet。

  • metadata: 资源的元数据,包括名称。

  • spec: StatefulSet 的规格。

    • serviceName: 引用的 Headless Service 的名称。

    • replicas: 期望的 Pod 副本数量,这里是 3。

    • selector: 用于选择 Pod 的标签选择器,与 Headless Service 中的标签选择器相匹配。

    • template: Pod 模板,定义了 Pod 的规格。

    • metadata: Pod 的元数据,包括标签。

    • spec: Pod 的规格。

      • containers: 定义了 Pod 中的容器。

      • name: 容器的名称。

      • image: 容器使用的镜像。

      • ports: 容器暴露的端口。

      • volumeMounts: 容器挂载的卷。

      • terminationGracePeriodSeconds: Pod 终止前的优雅期限。

  • VolumeClaimTemplate (myappdata)

  • metadata: 卷声明的元数据,包括名称和注释。

    • annotations: 用于指定 StorageClass,这里指定了 nfs-client-storageclass
  • spec: 卷声明的规格。

    • accessModes: 卷的访问模式,这里是 ReadWriteOnce

    • resources: 卷的资源请求,这里是 2Gi 的存储空间。

这个清单定义了一个 StatefulSet,它将创建 3 个 Pod,每个 Pod 都有一个名为 myappdata 的 PersistentVolumeClaim(PVC),用于存储数据。每个 Pod 都会通过 Headless Service myapp-svc 获得一个稳定的 DNS 名称。这样,即使 Pod 在集群中重新调度,它们也能保持相同的网络标识符和存储卷。这种配置非常适合需要持久化存储和稳定网络标识的有状态应用。

创建、管理和删除 StatefulSet

如何在 Kubernetes 集群中创建、管理和删除 StatefulSet,以及与之相关的服务、持久化卷(PV)、持久化卷声明(PVC)和 Pod

创建 StatefulSet

kubectl apply -f stateful-demo.yaml 

使用 kubectl apply -f stateful-demo.yaml 命令创建 StatefulSet。这将根据提供的 YAML 文件中的配置创建相应的资源。

查看无头服务

kubectl get svc  #查看创建的无头服务myapp-svc

使用 kubectl get svc 命令查看集群中的服务。可以看到 myapp-svc 服务的状态,它是一个无头服务,没有 ClusterIP。

查看 StatefulSet

kubectl get sts    #查看statefulset

使用 kubectl get sts 命令查看 StatefulSet。可以看到名为 myapp 的 StatefulSet 的期望副本数、当前副本数和年龄。

查看 PVC 绑定

kubectl get pvc    #查看pvc绑定

使用 kubectl get pvc 命令查看 PVC 的状态。您可以看到每个 PVC 都已绑定到一个 PV,并且它们的访问模式和存储容量。

查看 PV 绑定

kubectl get pv    #查看pv绑定

使用 kubectl get pv 命令查看 PV 的状态。可以看到每个 PV 的容量、访问模式、回收策略和状态。有些 PV 已经被 PVC 绑定,有些则处于可用状态。

查看 Pod 信息

kubectl get pods   #查看Pod信息

使用 kubectl get pods 命令查看 Pod 的状态。可以看到 StatefulSet 创建的 Pod 都已经运行。

删除 StatefulSet

kubectl delete -f stateful-demo.yaml    

使用 kubectl delete -f stateful-demo.yaml 命令删除 StatefulSet。这将删除 StatefulSet 及其管理的所有 Pod。删除操作是有序的,从最后一个 Pod 开始删除。

观察 Pod 删除过程

//当删除的时候是从myapp-2开始进行删除的,关闭是逆向关闭
kubectl get pods -w

使用 kubectl get pods -w 命令观察 Pod 的删除过程。可以看到 Pod 按照 StatefulSet 定义的顺序被删除。

重新创建 StatefulSet

//此时PVC依旧存在的,再重新创建pod时,依旧会重新去绑定原来的pvc
kubectl apply -f stateful-demo.yaml

在删除 StatefulSet 后,可以重新应用相同的 YAML 文件来重新创建 StatefulSet。由于 PVC 仍然存在,新创建的 Pod 将重新绑定到原来的 PVC。

再次查看 PVC 绑定

kubectl get pvc

使用 kubectl get pvc 命令确认 PVC 的状态。可以看到 PVC 仍然绑定到之前创建的 PV。

这些步骤展示了 StatefulSet 的生命周期管理,包括创建、查看、删除和重新创建。在实际应用中,这种管理方式允许您灵活地部署和管理有状态应用,同时保持数据的持久化和一致性。

复制再试一次分享


创建PV

创建共享目录:stor01节点

//stor01节点
mkdir -p /data/volumes/v{1,2,3,4,5}

使用 mkdir 命令在 /data/volumes/ 目录下创建五个新的目录(v1 到 v5)。这些目录将用作 NFS 共享的存储卷。

配置 NFS 共享

vim /etc/exports
/data/volumes/v1 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.41.0/24(rw,no_root_squash)

编辑 /etc/exports 文件,添加上述创建的目录作为共享资源。每个目录都配置了 IP 地址范围 192.168.41.0/24,表示只有该子网内的客户端可以访问这些共享。rw 表示允许读写权限,no_root_squash 允许 root 用户以 root 权限访问共享。

重启 NFS 服务

systemctl restart rpcbind
systemctl restart nfs

使用 systemctl 命令重启 rpcbindnfs 服务,以应用新的共享配置。

重新导出共享

exportfs -arv

使用 exportfs -arv 命令重新导出所有共享,确保新的共享配置生效。

查看共享列表

showmount -e

使用 showmount -e 命令查看当前服务器上所有导出的共享。这将显示共享的路径、客户端可以访问的权限以及客户端的 IP 地址范围。

这些步骤确保了 NFS 服务器正确配置,并且准备好了共享目录。在 Kubernetes 集群中,您可以创建 PersistentVolumes (PV) 和 PersistentVolumeClaims (PVC) 来使用这些 NFS 共享。这样,Kubernetes 中的 Pod 就可以挂载这些共享卷,实现跨 Pod 的数据共享和持久化存储。

定义pv

创建

pv-demo.yaml 文件包含了五个 PersistentVolume (PV) 的定义,这些 PV 将使用 NFS 服务器 stor01 上的共享目录。每个 PV 都有一个指定的容量和访问模式。

vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: stor01
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
  • PV pv001

  • name: PV 的名称。

  • labels: 用于标识 PV 的标签。

  • spec: PV 的规格。

    • nfs: NFS 服务器的配置,包括共享路径和服务器地址。

    • accessModes: PV 的访问模式,这里设置了 ReadWriteManyReadWriteOnce,表示 PV 可以被多个节点以读写方式共享,也可以被单个节点以读写方式独占。

    • capacity: PV 的存储容量,这里设置为 1Gi(1Gibibyte)。

  • PV pv002pv005

  • 这些 PV 的配置与 pv001 类似,但每个 PV 的容量不同,这里设置为 2Gi。pv002 只设置了 ReadWriteOnce 访问模式,意味着它只能被单个节点以读写方式独占。

应用 PV 定义

kubectl apply -f pv-demo.yaml

使用 kubectl apply -f pv-demo.yaml 命令将这些 PV 定义应用到 Kubernetes 集群中。

获取 PV 列表

kubectl get pv

使用 kubectl get pv 命令查看集群中的 PV 列表,确认这些 PV 是否已成功创建。

这些 PV 定义使得 Kubernetes 集群能够使用 NFS 共享作为持久化存储。在 StatefulSet 或其他需要持久化存储的工作负载中,可以通过 PersistentVolumeClaim (PVC) 来请求这些 PV。这样,即使 Pod 在集群中重新调度,它们也能保持对这些共享存储的访问,这对于有状态的应用(如数据库)来说非常重要。


滚动更新

**在 Kubernetes 中对 StatefulSet 进行滚动更新,以及如何在 Pod 内部解析其他 Pod 的名称。**StatefulSet 控制器将在 StatefulSet 中删除并重新创建每个 Pod。它将以与 Pod 终止相同的顺序进行(从最大的序数到最小的序数),每次更新一个 Pod。在更新其前身之前,它将等待正在更新的 Pod 状态变成正在运行并就绪。如下操作的滚动更新是按照2-0的顺序更新。

修改 StatefulSet 配置

vim stateful-demo.yaml          #修改image版本为v2
.....
image: ikubernetes/myapp:v2
....

编辑 stateful-demo.yaml 文件,将 Pod 模板中的容器镜像版本更新为 v2。这将触发 StatefulSet 的滚动更新。

应用更新

kubectl apply -f stateful-demo.yaml

使用 kubectl apply -f stateful-demo.yaml 命令应用更新。这将导致 StatefulSet 控制器开始滚动更新过程,逐个更新 Pod。

观察滚动更新过程

kubectl get pods -w   #查看滚动更新的过程

使用 kubectl get pods -w 命令观察滚动更新的过程。可以看到每个 Pod 依次进入终止状态,然后新的 Pod 被创建并启动。这个过程是从序号最大的 Pod 开始,逆序进行的。

在 Pod 内部解析其他 Pod 的名称

//在创建的每一个Pod中,每一个pod自己的名称都是可以被解析的
kubectl exec -it myapp-0 /bin/sh

使用 kubectl exec -it myapp-0 /bin/sh 命令进入 myapp-0 Pod 的 shell。然后,可以使用 hostname 命令查看当前 Pod 的完整名称,或者使用 nslookup 命令解析其他 Pod 的名称。

解析 Pod 名称到 IP 地址

//从上面的解析,我们可以看到在容器当中可以通过对Pod的名称进行解析到ip。其解析的域名格式如下:
(pod_name).(service_name).(namespace_name).svc.cluster.local

在 Pod 内部,可以通过 Pod 的名称解析到其对应的 IP 地址。解析的域名格式遵循 (pod_name).(service_name).(namespace_name).svc.cluster.local。例如,myapp-1.myapp-svc.default.svc.cluster.local

请注意, nslookup 命令在某些情况下可能无法解析 Pod 的名称,这可能是因为 DNS 解析缓存或者网络问题。在实际环境中,可能需要检查 CoreDNS 的配置或者网络设置,以确保 DNS 解析正常工作。

滚动更新是 StatefulSet 的一个重要特性,它允许在不中断服务的情况下更新应用。通过这种方式,可以逐步部署新版本的应用,同时确保集群的稳定性和可用性。


扩容和伸缩操作

如何在 Kubernetes 中对 StatefulSet 进行扩容和缩容操作

扩容 StatefulSet

kubectl scale sts myapp --replicas=4  #扩容副本增加到4个

使用 kubectl scale sts myapp --replicas=4 命令将名为 myapp 的 StatefulSet 的副本数扩展到 4 个。这将创建一个新的 Pod,使其总副本数达到 4。

动态查看扩容过程

kubectl get pods -w  #动态查看扩容

使用 kubectl get pods -w 命令观察扩容过程。可以看到新的 Pod 被创建,并且状态从 Pending 变为 Running

查看 PersistentVolumes (PV)

kubectl get pv  #查看pv绑定

使用 kubectl get pv 命令查看当前集群中所有的 PV。在扩容过程中,新的 Pod 将尝试绑定到现有的 PV,或者如果有必要,可能会创建新的 PV。

缩容 StatefulSet

kubectl patch sts myapp -p '{"spec":{"replicas":2}}'  #打补丁方式缩容

使用 kubectl patch sts myapp -p '{"spec":{"replicas":2}}' 命令通过打补丁的方式将 StatefulSet 的副本数缩容到 2。这将导致 StatefulSet 控制器逐步终止并删除额外的 Pod。

动态查看缩容过程

kubectl get pods -w  #动态查看缩容

再次使用 kubectl get pods -w 命令观察缩容过程。可以看到 Pod 的数量减少,直到只剩下 2 个 Pod。

在 StatefulSet 中进行扩容和缩容时,Kubernetes 会确保操作是有序的,以避免数据丢失或服务中断。对于有状态应用,通常需要确保在进行这些操作时,应用的状态能够正确地迁移和同步。


无状态和有状态应用以及常规 Service 和 Headless Service 的区别总结

无状态应用(Stateless Applications):

  • Pod 同质性:Deployment 管理的 Pod 被认为是完全相同的,可以互换。

  • 无顺序要求:Pod 的创建、更新和删除没有特定的顺序要求。

  • 节点无关性:Pod 可以在任何节点上运行,不需要特定的节点。

  • 伸缩性:可以根据负载自动或手动扩容和缩容。

有状态应用(Stateful Applications):

  • 实例差异性:每个实例(Pod)都有自己的唯一标识和状态,例如数据库实例。

  • 不对等关系:实例之间可能存在主从、领导者选举等不对等的关系。

  • 外部存储依赖:应用可能依赖于外部存储,如数据库或文件系统。

  • 顺序性:在部署、更新和删除时,需要考虑实例的顺序和唯一性。

常规 Service(ClusterIP Service):

  • 访问策略:为一组 Pod 提供访问策略,通过 ClusterIP 在集群内部提供负载均衡和服务发现。

  • ClusterIP:分配一个 ClusterIP,集群内的其他组件可以通过这个 IP 访问 Service。

  • 负载均衡:如果配置了负载均衡,Service 可以分发流量到后端的多个 Pod。

Headless Service:

  • 无 ClusterIP:Headless Service 不分配 ClusterIP,而是直接通过 DNS 解析到后端 Pod 的 IP 地址。

  • DNS 解析:通过 DNS 查询,可以直接获取到后端 Pod 的 IP 地址列表。

  • 服务发现:适合于需要直接与后端 Pod 通信的场景,如数据库集群的发现。

在 Kubernetes 中,Deployment 和 StatefulSet 是管理无状态和有状态应用的两种主要资源。而 Service(包括 ClusterIP Service 和 Headless Service)则提供了不同的服务发现和负载均衡机制,以适应不同的应用场景。

综合举例

如何在 Kubernetes 集群中创建一个测试 Pod、一个无头服务(Headless Service)和一个 StatefulSet,以及如何在这些资源之间进行通信和测试。

创建测试 Pod (dns-test)

vim pod6.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: dns-test
spec:
  containers:
  - name: busybox
    image: busybox:1.28.4
    args:
    - /bin/sh
    - -c
    - sleep 36000
  restartPolicy: Never

创建一个名为 pod6.yaml 的文件,定义了一个使用 busybox 镜像的 Pod。这个 Pod 将执行 sleep 36000 命令,保持运行状态,用于后续的 DNS 解析测试。

创建无头服务 (nginx)

vim sts.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1beta1  
kind: StatefulSet  
metadata:
  name: nginx-statefulset  
  namespace: default
spec:
  serviceName: nginx  
  replicas: 3  
  selector:
    matchLabels:  
       app: nginx
  template:  
    metadata:
      labels:
        app: nginx  
    spec:
      containers:
      - name: nginx
        image: nginx:latest  
        ports:
        - containerPort: 80  

创建一个名为 sts.yaml 的文件,定义了一个无头服务 nginx,它将为 nginx-statefulset 的 Pod 提供 DNS 解析。服务的 clusterIP 设置为 None,以便创建一个 Headless Service。

创建 StatefulSet (nginx-statefulset)

sts.yaml 文件中,定义了一个 StatefulSet,它将创建 3 个 nginx Pod。每个 Pod 都有一个唯一的名称,如 nginx-statefulset-0nginx-statefulset-1nginx-statefulset-2

应用配置

kubectl apply -f sts.yaml

kubectl apply -f pod6.yaml

使用 kubectl apply -f sts.yaml 命令应用上述配置,创建服务和 StatefulSet。

查看资源

kubectl get pods,svc

使用 kubectl get pods,svc 命令查看集群中的 Pod 和服务。

DNS 解析测试

kubectl exec -it dns-test sh
/ # nslookup nginx-statefulset-0.nginx.default.svc.cluster.local
/ # nslookup nginx-statefulset-1.nginx.default.svc.cluster.local
/ # nslookup nginx-statefulset-2.nginx.default.svc.cluster.local

使用 kubectl exec -it dns-test sh 命令进入 dns-test Pod 的 shell,然后使用 nslookup 命令解析 nginx-statefulset 的每个 Pod 的 DNS 名称。这将显示每个 Pod 的 IP 地址。

在 StatefulSet Pod 内部进行通信测试

kubectl exec -it nginx-statefulset-0 bash
/# curl nginx-statefulset-0.nginx
/# curl nginx-statefulset-1.nginx
/# curl nginx-statefulset-2.nginx

使用 kubectl exec -it nginx-statefulset-0 bash 命令进入 nginx-statefulset-0 Pod 的 shell,然后使用 curl 命令测试与其他 nginx-statefulset Pod 的通信。

这些步骤展示了如何在 Kubernetes 中设置和测试有状态服务的 DNS 解析和内部通信。这对于确保服务发现和负载均衡正常工作非常重要,尤其是在有状态应用的场景中。通过这些测试,可以验证 StatefulSet 的 Pod 是否能够正确地解析彼此的 DNS 名称,并且能够相互通信。


五、 DaemonSet(工作负载)控制器

DaemonSet 是 Kubernetes 中的一种工作负载控制器,它确保在集群中的所有(或指定的)节点上运行一个 Pod 的副本。这使得 DaemonSet 成为运行集群级服务的理想选择,如日志收集、监控代理、存储守护进程等。

关键特性:

  • 节点覆盖:DaemonSet 确保在集群中的每个节点上都有一个 Pod 副本运行,或者根据需要在特定节点上运行。

  • 自动管理:当新节点加入集群时,DaemonSet 会自动在这些节点上创建 Pod。当节点被移除时,相应的 Pod 也会被清理。

  • 删除行为:删除 DaemonSet 会删除它创建的所有 Pod,这有助于维护集群的整洁。

典型用例:

  • 集群存储守护进程 :在每个节点上运行如 GlusterFS 的 glusterd 或 Ceph 的守护进程,以提供分布式存储服务。

  • 日志收集:部署如 Fluentd、Logstash 等日志收集代理,以便在每个节点上收集日志并将其发送到中央日志存储。

  • 监控代理 :在每个节点上运行监控代理,如 Prometheus 的 Node Exporter、Collectd、Datadog 代理、New Relic 代理或 Ganglia 的 gmond,以收集节点的监控数据。

应用场景:

  • Agent:DaemonSet 常用于部署代理或守护进程,这些代理或守护进程作为集群的"代理",执行特定的任务,如数据收集、服务代理等。

官方案例(监控):

//官方案例(监控)
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/

Kubernetes 官方文档提供了使用 DaemonSet 进行集群监控的案例。例如,可以部署 Prometheus Node Exporter 作为 DaemonSet,这样每个节点都会运行一个 Node Exporter Pod,用于暴露节点的监控指标。然后,可以使用 Prometheus 服务器来抓取这些指标,进行进一步的分析和可视化。

DaemonSet 是 Kubernetes 生态系统中的重要组成部分,它为在集群范围内部署和管理分布式服务提供了一种简单而有效的方式。

示例

如何创建一个 DaemonSet 并在 Kubernetes 集群中的每个节点上部署一个 Nginx Pod。

创建 DaemonSet 配置文件 (ds.yaml)

vim ds.yaml 
apiVersion: apps/v1
kind: DaemonSet 
metadata:
  name: nginx-daemonSet
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4
        ports:
        - containerPort: 80
  • apiVersion: 指定 Kubernetes API 的版本。

  • kind: 指定资源类型为 DaemonSet。

  • metadata: 包含 DaemonSet 的名称和标签。

  • spec: 包含 DaemonSet 的规格。

    • selector: 用于选择 Pod 的标签选择器。

    • template: 定义 Pod 模板,包括 Pod 的元数据和规格。

    • metadata: Pod 的标签。

    • spec: Pod 的规格,包括容器定义。

      • containers: 定义容器的名称、镜像和端口。

应用 DaemonSet 配置

kubectl apply -f ds.yaml

使用 kubectl apply -f ds.yaml 命令将 DaemonSet 配置应用到集群中。这将创建一个名为 nginx-daemonSet 的 DaemonSet,并在每个节点上部署一个 Nginx Pod。

查看 Pod 列表

//DaemonSet会在每个node节点都创建一个Pod
kubectl get pods

使用 kubectl get pods 命令查看集群中的 Pod。可以看到由 DaemonSet 创建的 Pod,它们的名称通常包含 DaemonSet 的名称和随机生成的哈希值。

在示例中,nginx-deployment 是之前创建的 Deployment 的名称,而不是 DaemonSet。DaemonSet 创建的 Pod 名称通常会包含 daemonset 关键字,例如 nginx-daemonset-...。如果希望查看由 DaemonSet 创建的 Pod,需要使用更具体的过滤器,例如 kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | grep nginx-daemonset

**请注意,**DaemonSet 通常用于在每个节点上运行特定的守护进程或服务,而一般不是用于部署像 Nginx 这样的 web 服务。如果你的目标是在集群中部署 web 服务,通常使用 Deployment 或 StatefulSet 会更合适。DaemonSet 更适合于那些需要在每个节点上运行的服务,如日志收集器、监控代理等。


六、 Job(特殊的工作负载)控制器

在 Kubernetes 中,Job 是一种用于执行一次性任务的工作负载,它保证任务至少运行一次,直到成功完成。Job 有两种类型:普通 Job 和定时任务 CronJob。

普通 Job(Job):

  • 一次性任务:Job 用于执行那些只需要运行一次直到成功完成的任务。

  • 保证执行:如果 Job 中的 Pod 失败(例如,因为节点故障),Kubernetes 会自动重新启动一个新的 Pod,直到任务成功完成。

  • 任务完成:一旦 Job 中的所有 Pod 成功终止,Job 就被认为是完成的。

定时任务(CronJob):

  • 周期性执行:CronJob 用于定期执行任务,它基于 Cron 表达式来定义任务的调度。

  • 重复执行:CronJob 会创建 Job 对象来执行任务,并且可以根据设定的时间表重复执行。

  • 历史记录:CronJob 保留了 Job 的历史记录,包括成功和失败的任务。

应用场景:

  • 数据库迁移:执行数据库迁移脚本,直到迁移成功。

  • 批处理脚本:运行批处理作业,如数据备份、日志清理等。

  • 安全扫描:使用 kube-bench 等工具对集群进行安全扫描。

  • 离线数据处理:处理不需要持续运行的大量数据,如数据分析、报告生成等。

  • 视频解码:执行视频转码等耗时的一次性任务。

官方文档链接:

https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/    

Job 是 Kubernetes 中处理短期、一次性任务的重要资源,它为开发者和运维人员提供了一种简单的方式来自动化和保证任务的执行。CronJob 则为周期性任务提供了自动化的解决方案,使得集群能够根据预定的时间表执行任务。

示例

如何在 Kubernetes 中创建和处理 Job 资源

创建 Job 配置文件 (job.yaml)

vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4
  • 定义了一个名为 pi 的 Job,它将运行一个 Perl 容器来计算圆周率(π)。

  • .spec.template.spec 定义了 Pod 的规格,包括容器的名称、镜像和执行的命令。

  • restartPolicy: Never 表示 Pod 失败后不会重启。

  • backoffLimit: 4 表示 Job 在失败后最多重试 4 次。

拉取 Perl 镜像

//在所有node节点下载perl镜像,因为镜像比较大,所以建议提前下载好
docker pull perl

使用 docker pull perl 命令提前拉取 Perl 镜像,以避免在 Job 执行时下载镜像导致延迟。

应用 Job 配置

kubectl apply -f job.yaml 

使用 kubectl apply -f job.yaml 命令创建 Job。这将在集群中启动一个 Pod 来执行计算圆周率的任务。

查看 Pod 状态

kubectl get pods

使用 kubectl get pods 命令查看 Pod 的状态。您可以看到 Pod pi-bqtf7 已经成功完成。

查看 Job 结果

//结果输出到控制台
kubectl logs pi-bqtf7

使用 kubectl logs pi-bqtf7 命令查看 Pod 的日志输出,这里会显示计算出的圆周率值。

删除 Job 资源

//清除job资源
kubectl delete -f job.yaml 

使用 kubectl delete -f job.yaml 命令删除 Job 和相关的 Pod 资源。

设置 Job 的重试次数 (job-limit.yaml)

//backoffLimit
vim job-limit.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: busybox
spec:
  template:
    spec:
      containers:
        - name: busybox
          image: busybox
          imagePullPolicy: IfNotPresent
          command: ["/bin/sh", "-c", "sleep 10;date;exit 1"]
      restartPolicy: Never
  backoffLimit: 2
  • 创建一个新的 Job 配置文件,名为 busybox,它将运行一个 BusyBox 容器,执行一个失败的命令(exit 1)。

  • backoffLimit: 2 表示 Job 在失败后最多重试 2 次。

应用 Job 配置并查看状态

kubectl apply -f job-limit.yaml
kubectl get job,pods

使用 kubectl apply -f job-limit.yaml 命令创建 Job。然后使用 kubectl get job,pods 命令查看 Job 和 Pod 的状态。您可以看到 Job 没有成功完成,并且 Pod 状态为 Error

查看 Job 描述

kubectl describe job busybox

使用 kubectl describe job busybox 命令查看 Job 的详细信息,包括失败的原因。这里会显示 BackoffLimitExceeded 警告,表示 Job 达到了指定的重试次数限制。

通过这些步骤,可以了解如何在 Kubernetes 中创建和管理一次性任务。Job 是执行这类任务的理想选择,尤其是当任务需要在集群中运行到完成为止时。CronJob 则用于定期执行这类任务。


七、 CronJob(管理周期性任务的工作负载)控制器

ronJob 是 Kubernetes 中用于管理周期性任务的工作负载,它类似于 Linux 系统中的 crontab。CronJob 可以创建一个或多个 Job 对象来执行定时任务,这些任务按照预定的时间表(Cron 表达式)重复执行。

CronJob 的关键特性:

  • 定时执行:CronJob 使用 Cron 表达式来定义任务的执行时间表。

  • Job 创建:在预定的时间,CronJob 控制器会创建一个 Job 对象来执行任务。

  • 历史记录:CronJob 保留了 Job 的历史记录,包括成功和失败的任务,这对于审计和调试非常有用。

  • 并发控制:CronJob 允许配置并发策略,以控制同时运行的任务数量。

应用场景:

  • 通知系统:定期发送系统状态通知、日志报告或其他类型的定期通知。

  • 数据备份:执行数据库备份、文件备份等周期性数据保护任务。

  • 定期清理:清理日志文件、临时文件或其他不再需要的数据。

  • 监控和报告:定期执行监控任务并生成报告。

官方文档链接:

https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/

CronJob 是 Kubernetes 中处理周期性任务的强大工具,它使得自动化任务的创建和管理变得简单。通过定义 Cron 表达式,您可以轻松地安排任务在特定的时间执行,从而实现自动化运维。

示例

如何在 Kubernetes 中创建一个 CronJob,该 CronJob 每分钟执行一次打印 "Hello" 的任务。

创建 CronJob 配置文件 (cronjob.yaml)

//每分钟打印hello
vim cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
  • apiVersion: 指定 Kubernetes API 的版本。

  • kind: 指定资源类型为 CronJob。

  • metadata: 包含 CronJob 的名称。

  • spec: 包含 CronJob 的规格。

  • schedule: 使用 Cron 表达式定义任务的执行时间表。在这个例子中,"*/1 * * * *" 表示每分钟执行一次。

  • jobTemplate: 定义了 Job 模板,它包含了执行任务的 Pod 规格。

    • containers: 定义了容器的名称、镜像和其他参数。

    • args: 执行的命令,这里使用 /bin/sh 打印当前日期和 "Hello" 消息。

  • restartPolicy: 设置为 OnFailure,表示只在容器失败时重启。

创建 CronJob

kubectl create -f cronjob.yaml 

使用 kubectl create -f cronjob.yaml 命令创建 CronJob。这将在集群中设置一个周期性任务。

查看 CronJob 状态

kubectl get cronjob

使用 kubectl get cronjob 命令查看 CronJob 的状态,包括调度时间、活动状态和最近一次执行的时间。

查看执行的 Pod

kubectl get pods

使用 kubectl get pods 命令查看由 CronJob 创建的 Pod。这些 Pod 通常会在任务完成后标记为 Completed

查看 Pod 日志

kubectl logs hello-1621535124-mffj6

使用 kubectl logs 命令查看特定 Pod 的日志输出。在这个例子中,我们查看了 hello-1621525164-mffj6 Pod 的日志,可以看到打印的日期和 "Hello" 消息。

解决日志查看权限问题

kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous

如果在查看日志时遇到权限问题,可以通过创建一个 clusterrolebinding 来授予 system:anonymous 用户 cluster-admin 权限。这通常不推荐,因为它会降低集群的安全性。在生产环境中,应该使用更细粒度的权限控制。

通过这些步骤,可以在 Kubernetes 中设置周期性任务,例如定期备份、日志清理或发送通知。CronJob 提供了一种简单的方式来自动化这些重复性任务。

相关推荐
Kika写代码几秒前
【基于轻量型架构的WEB开发】课程 13.2.4 拦截器 Java EE企业级应用开发教程 Spring+SpringMVC+MyBatis
spring·架构·java-ee
运维佬1 分钟前
nginx配置负载均衡详解
运维·nginx·负载均衡
华为云开发者联盟18 分钟前
解读Karmada多云容器编排技术,加速分布式云原生应用升级
kubernetes·集群·karmada·多云容器
Shepherd06191 小时前
【Jenkins实战】Windows安装服务启动失败
运维·jenkins
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
Biomamba生信基地2 小时前
Linux也有百度云喔~
linux·运维·服务器·百度云
new_abc2 小时前
Ubuntu 22.04 ftp搭建
linux·运维·ubuntu
鹿鸣天涯3 小时前
‌华为交换机在Spine-Leaf架构中的使用场景
运维·服务器·网络
CodingBrother3 小时前
软考之面向服务架构SOA-通信方法
架构
小白也有IT梦3 小时前
域名绑定服务器小白教程
运维·nginx