如何在 Raspberry Pi 上使用 Kubernetes 创建 Cron 任务

找到一种更好的方法来高效可靠地运行您的计划任务。
401 位读者喜欢这篇文章。
hands programming

WOCinTech Chat。由 Opensource.com 修改。CC BY-SA 4.0

我在家中搭建 Raspberry Pi 上的 Kubernetes 集群 的原因之一是,我想通过不在云中运行高可用、冗余的基础设施来节省成本。Kubernetes 通过设计提供高可用性。这种能力提供的可能性非常棒。需要一个 Web 服务器持续运行?构建一个容器并将其放入 Kubernetes 集群中。需要一项始终可用的服务?打包它并将其运送到 Kubernetes 集群。

遗留系统

我在办公室里有四台旧的 Raspberry Pi 设备在做各种事情。它们可以很好地完成单个任务,但我已经过度扩展了一台第一代 Raspberry Pi。我想弃用较旧的 Raspberry Pi,因为它们不再有效。为此,我需要迁移工作负载(例如云迁移)。我在这些 Raspberry Pi 设备上运行最多的东西之一是 cron 任务。我几乎为我所做的一切都设置了 cron 任务:监控、更新 Web 应用程序、检测域名配置中的更改等等。

k8s 任务和 cron 任务

Kubernetes 具有任务的概念。引用官方任务文档,“任务创建一个或多个 Pod,并确保指定数量的 Pod 成功终止。” 如果您有一个需要运行直到完成的 Pod,无论发生什么情况,Kubernetes 任务都适合您。将任务视为批处理处理器。

Kubernetes cron 任务 是一个相对较新的事物。但我很高兴这已成为现代 Kubernetes 集群中的标准功能。这意味着我可以一次性告诉集群,我希望在特定时间运行任务。由于 cron 任务构建在现有任务功能之上,我知道任务将运行到完成。该任务将在我的 Kubernetes 集群中的六个节点之一上运行。即使 Pod 在任务执行过程中被销毁,它也会在另一个节点上启动并在那里运行。高可用性的 cron 任务一直是我多次尝试解决的难题。这个问题现在已经解决了,我所要做的就是实现它。

Kubernetes cron 任务 的实现与 Kubernetes 的许多其他事物一样:YAML。有一些项目可以帮助您处理 YAML(例如 ksonnet),但这将在另一篇文章中讨论。现在,让我们一起创建一个 Dockerfile 和一个 Kubernetes 配置文件。

用例

我将我的新闻通讯 DevOps'ish 从 Medium 转移到了 Netlify,并使用 Hugo 作为静态站点生成器。这使得网站非常快速且易于管理。但迁移中丢失的一项功能是计划发布帖子的能力。Netlify 提供了一个构建钩子,它会在被调用时触发构建。我可以撰写新闻通讯并将其设置为未来的日期。默认情况下,除非在指定日期之后完成构建,否则 Hugo 不会发布文章。通过 cron 任务使用 curl 调用构建钩子 URL 是一种在 Netlify 上使用 Hugo 实现计划发布帖子的方法。

Dockerfile

Dockerfile 非常简单。从 alpine:latest 拉取,安装 curl,并运行 curl 命令。但我不希望构建钩子 URL 在 Dockerfile 中公开。建议通过 Kubernetes secret 将 URL 作为变量加载。这样做是为了确保工件没有敏感数据,并且可以公开共享。这是 Dockerfile


FROM alpine:latest

LABEL maintainer="Chris Short <chris@chrisshort.net>"

RUN set -x \
        && apk update \
        && apk upgrade \
        && apk add --no-cache curl

ENTRYPOINT [ "/bin/sh", "-c" ]

CMD [ "/usr/bin/curl -vvv -X POST -d '' ${URL}" ]

​

Docker 构建

由于我的 Kubernetes 集群在 Raspberry Pi 上运行,我确保将此 Dockerfile 拉取到 Raspberry Pi 开发机器并在此处构建它

docker build -t devopsish-netlify-cron .

名称可以随意命名。我可能会在准备好时将此名称重命名为 netlify-curl 或其他更合适的名称。

Docker 注册表

下一步是将镜像添加到 Docker 注册表。我考虑过在 Kubernetes 集群本身中运行 Docker 注册表,但后来我意识到 Google Container Registry (GCR) 是一个可用的选项。由于我在 Google Cloud 中有很多东西,所以我决定使用 GCR 以获得简单性和可用性(还有整个“Kubernetes 内部状态”的事情)。

Heptio 有一个很棒的指南,标题为 Google Cloud Registry (GCR) 与外部 Kubernetes。如果您要将 GCR 与外部 Kubernetes 集群一起使用,我强烈建议您首先阅读此指南。一旦 GCR 配置完成,您的 Kubernetes 集群配置为使用 GCR,并且容器已构建,您需要为 GCR 标记它

docker tag devopsish-netlify-cron gcr.io/chrisshort-net/devopsish-netlify-cron

然后将新标记的容器镜像推送到 GCR

gcloud docker -- push gcr.io/chrisshort-net/devopsish-netlify-cron:latest

Kubernetes secret

如前所述,下一个部分将是 Kubernetes secret。有很多方法可以处理 k8s secret。Secret 可以通过命令行或应用配置文件一次性加载。我选择了配置文件方法,因为我会将它们保存在 1Password 中,然后删除它们。secret 文件看起来像这样

apiVersion: v1
kind: Secret
metadata:
  name: devopish-build-hook
type: Opaque
data:
  url: [REDACTED]

经过编辑的 URL 字符串将是 Netlify 构建钩子 URL。由于这是一个不透明的 secret,因此字符串需要进行 base64 编码

echo -n "<SECRET>" | base64

将 base64 字符串添加到文件后,应用它

kubectl apply -f secret.yml

Cron 任务配置

Kubernetes cron 任务 配置文件拼凑起来相对容易。“Schedule”是必填字段,如果您熟悉 cron,它看起来将与 cron 格式字符串完全相同。

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: devopsish-netlify-cronjob
spec:
  schedule: "1 2-14 * * 0-1,5-6"
  jobTemplate:
    spec:
      template:
        spec:
          imagePullSecrets:
            - name: gcr-secret
          containers:
          - name: devopsish-netlify-cronjob
            image: gcr.io/chrisshort-net/devopsish-netlify-cron:latest
            env:
              - name: URL
                valueFrom:
                  secretKeyRef:
                    name: devopish-build-hook
                    key: url
          restartPolicy: OnFailure

我遇到的一个陷阱是 Kubernetes 专门使用 UTC。在创建计划时,请务必考虑到这一点。

以下是 Kubernetes 配置文件指定的内容

  1. 创建一个名为 devopsish-netlify-cronjob 的 cron 任务
  2. 计划在周日、周一、周五和周六的 UTC 时间 0200 到 1400 之间每小时的第一分钟运行
  3. 使用提供的 gcr secret 从 gcr.io/chrisshort-net/devopsish-netlify-cron:latest 拉取镜像
  4. 基于名为 devopish-build-hook 的 secret 中的 URL 键设置环境
  5. 在 cron 任务计划上运行容器

应用配置文件,您就可以开始了

kubectl apply -f devopsish-netlify-cronjob.yml

结论

瞧!您已经构建了一个 Docker 容器,将镜像部署到 Google Container Registry,配置了 Kubernetes 集群以从 GCR 拉取镜像,创建了一个 secret 来存储构建钩子,并创建了 cron 任务。如果一切正常,以下命令应显示一个活动的 cron 任务

cshort@michiganjfrog ~> kubectl get cronjob
NAME                        SCHEDULE             SUSPEND   ACTIVE    LAST SCHEDULE   AGE
devopsish-netlify-cronjob   1 2-14 * * 0-1,5-6   False     0         8h              2d

现在去庆祝您的高可用性、几乎保证每次都运行的 Kubernetes cron 任务吧。恭喜!

本文最初发布在 Chris Short 的博客上。经许可转载。

Chris Short
开源外交官 | Kubernetes 贡献者 | 残疾退伍军人(肯定很痛苦)| 底特律 | AWS 的 Kubernetes | 他/他/他的 | 观点仅代表我个人

2 条评论

您是否看过 Rancher (Rancher.Com) 用于编排?他们承诺 2 分钟即可启动 Kubernetes,提供 Pi 原生二进制文件,连接到 Swarm、Mesos... 不胜枚举。我很想听听您对此的看法。

Creative Commons 许可本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© 2025 open-source.net.cn. All rights reserved.