在 OKD 中创建 Kubernetes Cron 作业

开始使用 OKD,这是一个以前称为 OpenShift Origin 的 Kubernetes 发行版。
167 位读者喜欢这篇文章。
Kubernetes

Jason Baker。CC BY-SA 4.0。

开始使用 Kubernetes 和 OKD(一个以前称为 OpenShift Origin 的 Kubernetes 发行版)可能会让人望而生畏。 有许多概念和组件需要学习和理解。 本教程将引导您创建一个示例 Kubernetes cron 作业,该作业使用服务帐户和一个 Python 脚本来列出当前项目/命名空间中的所有 pod。 作业本身相对来说没什么用,但本教程介绍了 Kubernetes 和 OKD 基础设施的许多部分。 此外,Python 脚本是使用 OKD REST API 进行集群相关任务的一个很好的示例。

本教程涵盖了 Kubernetes/OKD 基础设施的几个部分,包括

  • 服务帐户和令牌
  • 基于角色的访问控制 (RBAC)
  • 镜像流
  • BuildConfig
  • Source-to-image (S2I)
  • 作业和 cron 作业(主要是后者)
  • Kubernetes 的 Downward API

本教程的 Python 脚本和示例 OKD YAML 文件可以在 GitHub 上找到; 要使用它们,只需将 value: https://okd.host:port 行替换为 cronJob.yml 中您的 OKD 实例的主机名。

先决条件

所需软件

  • 安装了默认 S2I 镜像流的 OKD 或 MiniShift 集群
  • 集成的镜像注册表

可选软件(用于玩转 Python 脚本)

要安装模块,请运行

pip3 install --user openshift kubernetes 

身份验证

Python 脚本将使用服务帐户 API 令牌来向 OKD 进行身份验证。 该脚本期望有一个指向 OKD 主机的环境变量,它将连接到该主机

HOST:要连接到的 OKD 主机(例如,https://okd.host:port

OKD 还将需要为将运行 cron 作业 pod 的服务帐户自动创建令牌(请参阅下面的“设置如何使用环境变量和令牌”below)。

流程

设置此同步是一个很好的学习经验——因为您需要设置许多 Kubernetes 和 OKD 任务,所以您可以很好地了解它的各种功能。

一般流程是

  1. 创建一个新项目
  2. 创建一个包含 Python 脚本的 Git 存储库
  3. 创建一个服务帐户
  4. 授予服务帐户 RBAC 权限
  5. 设置如何使用环境变量和令牌
  6. 创建一个镜像流以接受 BuildConfig 创建的镜像
  7. 创建一个 BuildConfig 以将 Python 脚本转换为镜像/镜像流
  8. 构建镜像
  9. 创建 cron 作业

1. 创建一个新项目

在 OKD 中为此练习创建一个新项目

oc new-project py-cron

根据集群的设置方式,您可能需要请求集群管理员为您创建一个新项目。

2. 创建一个包含 Python 脚本的 Git 存储库

克隆或 fork 此存储库

https://github.com/clcollins/openshift-cronjob-example.git

您也可以在下面的代码示例中直接引用它。 这将作为存储库,从中拉取 Python 脚本并构建到最终运行的镜像中。

3. 创建一个服务帐户

服务帐户是一个非用户帐户,可以与 OKD 中的资源、权限等关联。 对于本练习,您必须创建一个服务帐户来运行包含 Python 脚本的 pod,通过令牌身份验证向 OKD API 进行身份验证,并进行 REST API 调用以列出所有 pod。

由于 Python 脚本将查询 OKD REST API 以获取命名空间中 pod 的列表,因此服务帐户将需要列出 pod命名空间的权限。 从技术上讲,项目中自动创建的默认服务帐户之一——system:serviceaccount:default:deployer——已经拥有这些权限。 但是,本练习将创建一个新的服务帐户来解释服务帐户创建和 RBAC 权限。

通过输入以下内容创建一个新的服务帐户

oc create serviceaccount py-cron

这将创建一个名为 py-cron 的服务帐户。(从技术上讲,它是 system:serviceaccounts:py-cron:py-cron,或“py-cron”命名空间中的“py-cron”服务帐户)。 该帐户自动接收两个 secret:一个 OKD API 令牌和 OKD 容器注册表的凭据。 API 令牌将在 Python 脚本中用于向 OKD 标识服务帐户以进行 REST API 调用。

与服务帐户关联的令牌可以使用以下命令查看

oc describe serviceaccount py-cron

4. 授予服务帐户 RBAC 权限

OKD 和 Kubernetes 使用 RBAC(基于角色的访问控制)来精细控制谁可以在复杂的集群中做什么。 在 RBAC 中

  1. 权限基于动词资源(例如,创建组、删除 pod 等)
  2. 权限集被分组到角色ClusterRole 中,后者顾名思义是集群范围的。
  3. 角色和 ClusterRole 通过创建 RoleBinding 或 ClusterRoleBinding 与服务帐户(或者,如果您想完全错误地操作,则与个人用户)关联(或绑定到)。
  4. 组、服务帐户和用户可以绑定到多个角色。

对于本练习,在项目中创建一个角色,授予该角色列出 pod 和项目的权限,并将 py-cron 服务帐户绑定到该角色

oc create role pod-lister --verb=list --resource=pods,namespaces
oc policy add-role-to-user pod-lister --role-namespace=py-cron system:serviceaccounts:py-cron:py-cron

请注意,必须添加 --role-namespace=py-cron 以防止 OKD 查找 ClusterRole。

验证服务帐户是否已绑定到角色

oc get rolebinding | awk 'NR==1 || /^pod-lister/'
NAME         ROLE                 USERS     GROUPS   SERVICE ACCOUNTS   SUBJECTS
pod-lister   py-cron/pod-lister                      py-cron

5. 设置如何使用环境变量和令牌

与服务帐户关联的令牌和各种环境变量在 Python 脚本中被引用为 py-cron API 令牌

py-cron 服务帐户自动创建的 API 令牌由 OKD 挂载到服务帐户正在运行的任何 pod 中。 此令牌被挂载到 pod 中每个容器的特定路径

/var/run/secrets/kubernetes.io/serviceaccount/token

Python 脚本读取此文件并使用它向 OKD API 进行身份验证以管理组。

  • HOST 环境变量:HOST 环境变量在 cron 作业定义中指定,并包含格式为 https://okd.host:port 的 OKD API 主机名。

  • NAMESPACE 环境变量:NAMESPACE 环境变量在 cron 作业定义中引用,并使用 Kubernetes Downward API 动态填充变量,其中包含 cron 作业 pod 正在运行的项目的名称。

6. 创建一个镜像流

镜像流是镜像的集合,在本例中,由 BuildConfig 构建创建,并且是镜像和 Kubernetes 对象之间的抽象层,允许它们引用镜像流而不是直接引用镜像。

在可以将新构建的镜像推送到镜像流之前,该流必须已经存在。 创建新的空流的最简单方法是使用 oc 命令行命令

oc create imagestream py-cron

7. 创建 BuildConfig

BuildConfig 是整个构建过程的定义——获取输入参数和代码并将它们转换为镜像的行为。

本练习的 BuildConfig 将使用 source-to-image (S2I) 构建策略,使用 Red Hat 提供的 Python S2I 镜像,并将 Python 脚本添加到其中,其中 requirements.txt 被解析并安装这些模块。 这将生成一个最终的基于 Python 的镜像,其中包含脚本和运行它所需的 Python 模块。

BuildConfig 的重要部分是:.spec.output.spec.source.spec.strategy

.spec.output

BuildConfig 的输出部分描述了如何处理构建的输出。 在这种情况下,BuildConfig 将生成的镜像输出为镜像流标签 (例如,py-cron:1.0),该标签可以在 deploymentConfig 中用于引用镜像。

这些可能是自解释的。

spec:
  output:
    to:
      kind: ImageStreamTag
      name: py-cron:1.0

.spec.source

BuildConfig 的源部分描述了构建的内容来自哪里。 在这种情况下,它引用了 Git 存储库,其中保存了 Python 脚本及其支持文件。

其中大多数也是自解释的。

spec:
  source:
    type: Git
    git:
      ref: master
      uri: https://github.com/clcollins/openshift-cronjob-example.git

.spec.strategy

BuildConfig 的策略部分描述了要使用的构建策略,在本例中为源(即 S2I)策略。 .spec.strategy.sourceStrategy.from 部分定义了公共 Python 3.6 镜像流,该镜像流存在于默认 OpenShift 命名空间中,供任何人使用。 此镜像流包含 S2I 构建器镜像,这些镜像将 Python 代码作为输入,安装 requirements.txt 文件中列出的任何依赖项,然后输出一个包含代码和已安装需求的成品镜像。

strategy:
  type: Source
  sourceStrategy:
    from:
      kind: ImageStreamTag
      name: python:3.6
      namespace: openshift

此示例的完整 BuildConfig 看起来像下面的 YAML。 替换您的 Git 存储库并使用 oc 命令创建 BuildConfig

oc create -f <path.to.buildconfig.yaml>

YAML

---
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  labels:
    app: py-cron
  name: py-cron
spec:
  output:
    to:
      kind: ImageStreamTag
      name: py-cron:1.0
  runPolicy: Serial
  source:
    type: Git
    git:
      ref: master
      uri: https://github.com/clcollins/openshift-cronjob-example.git
  strategy:
    type: Source
    sourceStrategy:
      from:
        kind: ImageStreamTag
        name: python:3.6
        namespace: openshift

8. 构建镜像

在大多数情况下,向 BuildConfig 添加 webhook 触发器以允许在每次将代码提交并推送到存储库时自动重建镜像会更有效率。 但是,对于本练习,每当需要更新镜像时,将手动启动镜像构建。

可以通过运行以下命令触发新的构建

oc start-build BuildConfig/py-cron

运行此命令会输出构建的名称; 例如

build.build.openshift.io/py-cron-1 started

可以通过观看日志来跟踪构建的进度

oc logs -f build.build.openshift.io/py-cron-1

构建完成后,镜像将被推送到 BuildConfig 的 .spec.output 部分中列出的镜像流。

9. 创建 cron 作业

Kubernetes cron 作业 对象定义了 cron 计划和行为,以及为运行实际同步而创建的 Kubernetes 作业

cron 作业定义的重要部分是:.spec.concurrencyPolicy.spec.schedule.spec.JobTemplate.spec.template.spec.containers

.spec.concurrencyPolicy

cron 作业规范的 concurrencyPolicy 字段是一个可选字段,用于指定如何处理此 cron 作业创建的作业的并发执行。 在本练习中,如果 cron 作业创建新作业,它将替换可能仍在运行的现有作业。

注意: 其他选项是允许并发(同时运行多个作业)或禁止并发(新作业将被跳过,直到正在运行的作业完成)。

.spec.schedule

cron 作业规范的 schedule 字段(毫不奇怪)是一个 Vixie cron 格式的计划。 在指定的时间,Kubernetes 将创建一个作业,如下面的 JobTemplate 规范中所定义。

spec:
  schedule: "*/5 * * * *"

.spec.JobTemplate.spec.template.spec.containers

cron 作业规范包含一个 JobTemplate 规范和一个模板规范,后者又包含一个容器规范。 所有这些都遵循其类型的标准规范,即 .spec.containers 部分只是您可能在任何其他 pod 定义中找到的普通容器定义。

此示例的容器定义是一个直接的容器定义,它使用了上面讨论的环境变量。

唯一重要的部分是: 

.spec.JobTemplate.spec.template.spec.containers.ServiceAccountName

此部分将先前创建的服务帐户 py-cron 设置为运行容器的帐户。 这将覆盖默认的 deployer 服务帐户。

py-cron 的完整 OKD cron 作业看起来像下面的 YAML。 替换 OKD 集群 API 的 URL,并使用以下 oc 命令创建 cron 作业: 

oc create -f <path.to.cronjob.yaml>

YAML

---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  labels:
    app: py-cron
  name: py-cron
spec:
  concurrencyPolicy: Replace
  failedJobsHistoryLimit: 1
  JobTemplate:
    metadata:
      annotations:
        alpha.image.policy.openshift.io/resolve-names: '*'
    spec:
      template:
        spec:
          containers:
          - env:
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: HOST
              value: https://okd.host:port
            image: py-cron/py-cron:1.0
            imagePullPolicy: Always
            name: py-cron
          ServiceAccountName: py-cron
          restartPolicy: Never
  schedule: "*/5 * * * *"
  startingDeadlineSeconds: 600
  successfulJobsHistoryLimit: 3
  suspend: false

四处查看

创建 cron 作业后,可以使用 oc get cronjob 命令查看其组件。 这显示了 cron 作业的简要描述、其计划和上次运行时间,以及它是处于活动状态还是暂停状态

oc get cronjob py-cron
NAME      SCHEDULE    SUSPEND   ACTIVE    LAST SCHEDULE   AGE
py-cron   */5 * * * *   False     0         1m              7d

如前所述,cron 作业创建 Kubernetes 作业以在计划时间过去时执行工作。 oc get jobs 命令列出了 cron 作业已创建的作业、所需的作业数(在本例中,每次运行仅一个作业)以及作业是否成功

oc get jobs
NAME                 DESIRED   SUCCESSFUL   AGE
py-cron-1544489700   1         1            10m
py-cron-1544489760   1         1            5m
py-cron-1544489820   1         1            30s

作业是 pod,可以使用 oc get pods 命令查看。 在此示例中,您可以看到作业 pod(以创建它们的作业命名,例如作业“py-cron-1544489760”创建了 pod“py-cron-1544489760-xl4vt”)。 还有构建 pod,或构建容器镜像的 pod,如上面的 BuildConfig 中所述。

oc get pods
NAME                       READY     STATUS      RESTARTS   AGE
py-cron-1-build            0/1       Completed   0          7d
py-cron-1544489760-xl4vt   0/1       Completed   0          10m
py-cron-1544489820-zgfg8   0/1       Completed   0          5m
py-cron-1544489880-xvmsn   0/1       Completed   0          44s
py-cron-2-build            0/1       Completed   0          7d
py-cron-3-build            0/1       Completed   0          7d

最后,由于此示例只是一个连接到 OKD REST API 以获取有关项目中 pod 信息的 Python 脚本,因此可以使用 oc get logs 验证脚本是否正常工作,方法是从 pod 获取日志以查看写入标准输出的脚本的输出

oc logs py-cron-1544489880-xvmsn
---> Running application from Python script (app.py) ...
ResourceInstance[PodList]:
  apiVersion: v1
  items:
  - metadata:
      annotations: {openshift.io/build.name: py-cron-1, openshift.io/scc: privileged}
      creationTimestamp: '2018-12-03T18:48:39Z'
      labels: {openshift.io/build.name: py-cron-1}
      name: py-cron-1-build
      namespace: py-cron
      ownerReferences:
      - {apiVersion: build.openshift.io/v1, controller: true, kind: Build, name: py-cron-1,
        uid: 0c9cf9a8-f72c-11e8-b217-005056a1038c}

<snip>

总结

本教程介绍了如何在 OKD(一个以前称为 OpenShift Origin 的 Kubernetes 发行版)中创建 Kubernetes cron 作业。 BuildConfig 描述了如何构建包含调用 OKD REST API 的 Python 脚本的容器镜像,并创建了一个镜像流来描述由构建构建的镜像的不同版本。 创建了一个服务帐户来运行容器,并创建了一个角色以允许服务帐户从 OKD REST API 获取 pod 信息。 RoleBinding 将角色与服务帐户关联起来。 最后,创建了一个 cron 作业以按指定的计划运行作业(包含 Python 脚本的容器)。

接下来阅读什么
Chris Collins
Chris Collins 是 Red Hat 的 SRE 和 OpenSource.com 通讯员,热衷于自动化、容器编排及其周围的生态系统,并喜欢在家中重现企业级技术以获得乐趣。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.