跳转到主要内容

一个工具,用于封装OpenShift命令行工具,以实现OpenShift模板的可重复自动化部署。

项目描述

ocdeployer

Build Status

一个工具,用于封装OpenShift命令行工具,以实现OpenShift模板的可重复自动化部署。允许您更有效地根据模板重新创建环境。

  • 反复将相同的模板部署到不同的OpenShift项目中
  • 通过“阶段”定义它们应该部署的顺序
  • 可选地等待资源“准备好”后再继续到下一阶段
    • 使DeploymentConfig资源达到期望的副本数量
    • 使Build资源成功
    • 使StatefulSet资源达到期望的副本数量
  • 定义哪些外部“镜像”应该作为ImageStreams导入到项目中
  • 定义您的服务依赖哪些机密,并从本地目录或OpenShift中的另一个项目导入它们
  • 将组件模板拆分为“服务集”,并部署所有集或特定集
  • 定义依赖关系(例如:服务集“A”需要服务集“B”)
  • 创建环境文件,其中定义了应在模板处理时设置的参数,以便您可以将相同的模板部署到不同的环境中
  • 在部署时指定多个环境文件并合并它们
  • 使用OpenShift模板以及jinja2模板
  • 如果需要更精细的控制,可以在Python中创建自定义的预部署/部署/后部署脚本
  • 快速调整模板中定义的资源请求/限制。
  • 在部署期间监视命名空间中的事件。

需要 OpenShift 命令行工具(oc 命令)

在部署之前,您应该登录到您的项目

$ oc login https://api.myopenshift --token=*************

入门

详情

以下是一个示例 ocdeployer 项目结构:

├── env
│   ├── prod-env.yml
│   └── qa-env.yml
├── secrets
│   ├── mysql-secrets.yml
│   └── postgres-secrets.yml
└── templates
    ├── _cfg.yml
    ├── set1
    │   ├── _cfg.yml
    │   ├── env
    │   │   └── qa-env.yml
    │   ├── nginx.yml
    │   └── postgres.yml
    └── set2
        ├── _cfg.yml
        ├── custom
        │   └── deploy.py
        ├── mysql.yml
        └── ruby-app.yml

以下解释了结构的各个部分:

  • secrets 目录 -- 这是可选的。包含包含 SecretListSecret 资源的开源 YAML 文件。需要导入密钥的应用程序可以使用此目录中的密钥。

  • env 目录 -- 您可以在项目的根级别创建 env 文件,以及在每个服务集(如下所述)中。您可以在部署时在 CLI 上指定多个环境,并且这些值将合并。

  • templates 目录 -- OpenShift YAML/JSON 模板以及一个特殊的配置文件(名为 _cfg.yml)。模板通常分为此目录中的文件夹,称为服务集。基本 _cfg.yml 定义了所有服务集的部署顺序,以及所有服务都依赖的任何“全局”密钥/图像。

  • set1set2 是服务集文件夹 -- 每个服务集文件夹包含以下内容:

    • 一个 _cfg.yml,该文件配置特定服务集的部署。
    • 一个名为 custom 的目录,其中包含自定义部署脚本。这是可选的。Python 脚本可以放置在这里,它们可以在特定服务集的预部署/部署/后部署阶段运行。
    • 一个名为 env 的目录,其中包含环境文件或文件。这是可选的。定义应传递给模板的参数。在此 env 文件中定义的值将与根级别定义的值合并,服务集文件中匹配的键具有优先权。

请参阅 示例 以更好地了解所有这些配置如何结合在一起,以及 ocdeployer 在运行部署时的更多详细信息。

安装和用法

安装

您可以使用以下命令从 pypi 安装此包:

$ pip install ocdeployer

或者,如果您是从源安装,请将其安装到虚拟环境中

$ python3 -m venv .venv
$ . .venv/bin/activate
(venv) $ pip install -r requirements.txt

用法

(venv) $ ocdeployer -h
Usage: ocdeployer [OPTIONS] COMMAND [ARGS]...

  Deploys components to a given cluster. NOTE: You need the openshift cli
  tool ('oc') installed and to login to your openshift cluster before
  running the tool.

Options:
  -h, --help  Show this message and exit.

Commands:
  deploy       Deploy to project
  list-routes  List routes currently in the project
  list-sets    List service sets available in template dir
  process      Process templates but do not deploy
  wipe         Delete everything from project

部署命令

使用 deploy 命令将模板推送到 OpenShift。

使用 ocdeployer deploy -h 获取有关参数和选项的更多详细信息。

进程命令

使用 process 查看模板数据而无需实际部署。 processdeploy 非常类似,但它不会将任何配置推送到 OpenShift,而会简单地使用 jinja2 和 OpenShift 模板解析模板(即运行 oc process),替换提供的变量/项目名称等,然后将结果配置打印到 stdout 或保存到目录中。

擦除命令

使用 wipe 删除项目中的对象。它实际上运行以下命令,删除所有对象或具有特定标签的对象:

oc delete all [--all or --selector mylabel=myvalue]
oc delete configmap [--all or --selector mylabel=myvalue]
oc delete secret [--all or --selector mylabel=myvalue]
oc delete pvc [--all or --selector mylabel=myvalue]

列出路由命令

使用 list-routes 打印项目中活动路由的 URL。

列出集合命令

使用 list-sets 打印模板目录中可用于部署的服务集名称。


模板配置

解释模板配置的最佳方式是描述配置服务集的过程。

创建服务集的指南

  1. templates 目录中为您的服务集创建一个新目录,例如 "myservice"。

  2. 请在此目录中添加您的服务 OpenShift YAML 文件。这些文件应该是包含运行服务所需所有资源(除机密信息和外部镜像的镜像流,我们稍后会讨论这一点)的 OpenShift 模板文件。这通常包括 buildConfigdeploymentConfigserviceroute 等内容。

  3. 在您的目录中创建一个 '_cfg.yml' 文件。下面解释了该配置文件的内容。

    # (optional) requires
    #
    # Here you can list other service sets that need to be deployed before this one can.
    # Deployment will fail when processing this file if we see the required service set has
    # not yet been deployed in this run of ocdeployer.
    requires:
    - "myotherservice"
    
    # (optional) secrets
    #
    # Lists which secrets apps in this service set rely on; they will be validated or imported at run time.
    # A secret is only imported once per deploy run, so if other service sets rely on the same
    # secret it won't be imported again.
    secrets:
    - "mysecret"
    # You can also specify which service accounts a secret should be linked to
    - name: "othersecret"
      link: ["builder"]
    
    # (optional) custom_deploy_logic
    #
    # Indicates that there is a pre_deploy/post_deploy/deploy method defined for this
    # service set in the 'custom' folder that should be used
    custom_deploy_logic: true
    
    # (optional) post_deploy_timeout
    #
    # Indicates how long custom post_deploy logic should take before timeout (in seconds).
    # A null value can be handled differently depending on the post deploy logic,
    # but it is recommended that it means there is "no waiting" that will occur
    post_deploy_timeout: 300
    
    # (optional) images
    # Lists the image streams these services require to be imported into the destination namespace.
    #
    # key = the name or name:tag for the image stream. If no tag is specified, 'latest' is used.
    # value = the full image docker uri
    #
    # 'oc import-image <key> --from="<value>"' is run at deploy time.
    #
    # If it already exists, it will be re-imported (and therefore the image will be updated)
    images:
    - cp-kafka: "confluentinc/cp-kafka"
    - cp-zookeeper: "confluentinc/cp-zookeeper"
    - nginx-stable-openshift: "docker.io/mhuth/nginx-stable-openshift"
    - python-36-centos7: "centos/python-36-centos7"
    - postgresql-95-rhel7: "registry.access.redhat.com/rhscl/postgresql-95-rhel7"
    
    # (required) deploy_order
    #
    # Lists the order in which components in this service set should be deployed.
    deploy_order:
      # A stage deploys a group of components in sequentially and then waits for them to reach 'active'
      # in parallel. By default, at the end of each stage, we wait for:
      #   * DeploymentConfig's to be "active"
      #   * StatefulSet's to be "active"
      #   * BuildConfig's to succeed
      #
      # Setting 'wait' to false under the stage disables this behavior.
      #
      # Stages are processed after being sorted by name.
      stage0:
        wait: false
        components:
        - "zookeeper"
      stage1:
        # You can specify a wait timeout. By default, 300sec is used
        timeout: 600
        # 'components' lists the template files that should be deployed in this stage.
        # Their config is applied in openshift in the same order they are listed.
        components:
        - "kafka"
        - "inventory-db"
      stage2:
        components:
        - "insights-inventory"
        - "upload-service"
    
  4. 如果将 custom_deploy_logic 设置为 True,请阅读下面的“自定义部署逻辑”。

  5. 如果您想为此服务的模板定义环境变量,请阅读下面的“环境文件”。

  6. 将您的服务文件夹名称添加到 templates 目录中的基本 _cfg.yml 中。请记住,deploy_order 指定了每个服务集部署的顺序。因此,如果您的服务集依赖于其他服务的先部署,请适当排序!

  7. 运行 ocdeployer list-sets,您应该会看到您的新组件作为可部署的服务集列出。

自定义部署逻辑

默认情况下,不运行 pre_deploy/post_deploy,部署逻辑由 ocdeployer.deploy.deploy_components 方法处理。因此,除非您正在进行复杂操作并需要额外的“Python 脚本”来处理您的(预/后)部署逻辑,否则您不需要担心自定义逻辑(并且通常不需要重新编写主要部署逻辑)。

但假设您想在部署组件之前或之后执行一些任务。自定义脚本对此很有用。

您可以在服务集的 _cfg.yml 中设置 custom_deploy_logictrue。然后您有两个选项来定义自定义部署脚本:

  • 您可以在项目的根 custom 目录中定义单个 deploy.py。此脚本将适用于所有服务集,只要它们将 custom_deploy_logic 设置为 true
  • 您可以在服务集的 custom 目录中创建一个名为 deploy.py 的脚本。此脚本将仅适用于该服务集。

如果项目中既包含根自定义目录中的 deploy.py,也包含服务集自定义目录中的 deploy.py,则服务集部署脚本具有优先级。


注意

ocdeployer<4.0 的先前版本中,custom 目录位于项目的根文件夹中,并需要将部署文件插入其中,以匹配服务集的名称,例如 deploy_myservice.py。为了向后兼容,定义服务集部署脚本的方法仍然被支持。


在此脚本中,您可以定义 3 个方法:

def pre_deploy(project_name, template_dir, variables_per_component):
  • project_name:字符串,要部署到的项目名称
  • template_dir:字符串,正在部署的服务集模板的完整路径
  • variables_per_component:字典,键是服务集中每个组件的名称,值是从 env.yml 文件中解析出的变量的另一个字典。
def deploy(project_name, template_dir, components, variables_per_component, wait, timeout, resources_scale_factor, label):
  • project_name:字符串,要部署到的项目名称
  • template_dir:字符串,正在部署的服务集模板的完整路径
  • components:字符串列表,正在部署的服务集的组件名称
  • variables_per_component:字典,键是服务集中每个组件的名称,值是从 env.yml 文件中解析出的变量的另一个字典。
  • wait:布尔值,用于确定部署逻辑是否应等待类似 DeploymentConfig 和 BuildConfig 的“完成”(变为“活动”或构建成功)
  • timeout:整数,超时前等待的时间
  • resources_scale_factor:浮点数,运行 ocdeployer 时传递给 --scale-resources 的值
  • label:字符串,在部署时附加到 Open Shift 中每个对象的标签
def post_deploy(processed_templates, project_name, template_dir, variables_per_component):
  • processed_templates:字典,包含已部署每个组件的处理后的模板信息 -- 键:模板名称,值:ocdeployer.templates.Template 的实例
  • project_name:字符串,要部署到的项目名称
  • template_dir:字符串,正在部署的服务集模板的完整路径
  • variables_per_component:字典,键是服务集中每个组件的名称,值是从 env.yml 文件中解析出的变量的另一个字典。

ocdeployer.common 中的大部分代码在您编写自定义部署逻辑时可能对您有用(例如,用于运行 oc 命令的 oc 方法)。

自定义部署示例 1

假设部署组件后,您想要触发对已推送的任何构建配置进行构建(实际上,只要在您的服务集 _cfg.yml 中该阶段的 wait 不是 false,默认情况下每次阶段之后都会发生此操作 —— 但为了本例,请配合一下)。

您可以定义一个类似于以下所示的部署后方法

from ocdeployer.utils import oc, wait_for_ready_threaded

log = logging.getLogger(__name__)

def post_deploy(**kwargs):
    build_config_names = []
    for _, template in kwargs.get("processed_templates", {}).items():
        # Get the name of all build configs that were deployed
        # Remember, we are looking at the processed template info
        # We're looking at the template AFTER variable substitution occurred.
        build_config_names.extend(template.get_processed_names_for_restype("bc"))

    objs_to_wait_for = []
    for bc_name in build_config_names:
        oc("start-build", bc_name, exit_on_err=False)
        objs_to_wait_for.append(("bc", bc_name))
    else  
        log.warning("No build configs were deployed, nothing to do")

    # Wait for all builds to reach 'completed' state:
    if objs_to_wait_for:
        wait_for_ready_threaded(objs_to_wait_for)

自定义部署示例 2

假设当您的项目中的任何 ConfigMap 资源更新时,您想要触发部署的新一轮发布。您可以通过在部署前后跟踪 ConfigMap 的状态来实现这一点。

from ocdeployer.utils import oc, get_json, wait_for_ready

log = logging.getLogger(__name__)
old_config_map_data = {}

def pre_deploy(**kwargs):
    old_config_map_data = get_json("configmap", "MyConfigMap")['data']


def post_deploy(**kwargs):
    new_config_map_data = get_json("configmap", "MyConfigMap")['data']
    if new_config_map_data != old_config_map_data:
        oc("rollout", "dc/MyDeployment")
        wait_for_ready("dc", "MyDeployment")

图像

您可以使用 _cfg.yml 中的 images 部分来指示 ocdeployer 导入图像并为它们配置 ImageStream。

ocdeployer 在部署时将为每个必需的图像执行以下操作。

oc import-image <istag> --from="<from>" --scheduled=true --confirm

如果图像已经存在,它将被重新导入(因此图像将被更新)。

如果 ImageStreamTag 已经存在,但 "from" URI 已更新,ocdeployer 将运行以下命令来重新配置 ImageStream 上的标签

oc tag --scheduled=true --source=docker <from> <istag>

如果相同的 ImageStreamTag 被定义多次(无论是在同一 _cfg.yml 中还是在各种 _cfg.yml 文件中),它不会被重复导入。因此,如果打算将它们部署到同一命名空间,ImageStreamTag 需要在服务集中具有唯一名称。

_cfg.yml 中,images 部分可以定义两种方式

短格式

将所需的 ImageStreamTag 列为键,将图像的 "from" URI 列为值。

如果没有指定标签,则假设 "latest" 是所需的标签。

images:
- "cp-kafka:sometag": "confluentinc/cp-kafka"

长格式ocdeployer>=v4.3.0

  • istag -- 所需的 ImageStreamTag
  • from -- 图像的外部 "from" URI
  • envs -- 列出此图像应导入的环境。只有当 ocdeployer 与 --env 匹配所提供的环境运行时,才会导入图像。如果没有提供环境,则假定它应该在所有环境中加载。
images:
- istag: "cp-kafka:sometag"
  from: "confluentinc/cp-kafka"
  envs: ["qa", "prod"]

秘密

默认情况下,ocdeployer 将简单地验证在 _cfg.yml 中指定的秘密是否已存在于您的目标命名空间中。

您可以使用 --secrets-src-project 运行 ocdeployer,从 OpenShift 的另一个项目中导入所需秘密,或者使用 --secrets-local-dir 从存储在本地目录中的 OpenShift 配置文件加载所需秘密。

如果您将 --secrets-src-project 设置为目标命名空间相同,这实际上会导致 ocdeployer 简单地验证该秘密是否存在于该命名空间中。

您在 secrets-local-dir 中放置的任何 .yaml/.json 文件都将被解析,并从中提取秘密并进行导入。文件可以包含单个秘密(kind: Secret)或资源列表(kind: List

一个示例秘密 .yaml 文件

apiVersion: v1
data:
    ssh-privatekey: <your key here>
kind: Secret
metadata:
    creationTimestamp: null
    name: my_secret
type: kubernetes.io/ssh-auth

_cfg.yml 中,秘密可以指定为两种方式

短格式

仅列出名称

secrets:
- "name of secret"

长格式ocdeployer>=v4.3.0

列出名称以及

  • link -- 列出应使用 oc secrets link 链接到秘密的服务帐户
  • envs -- 列出应导入此秘密的环境。只有当 ocdeployer 与 --env 匹配所提供的环境运行时,才会导入秘密。如果没有提供环境,则假定它应该在所有环境中加载。
secrets:
- name: "name of secret"
  link: ["account1", "account2"]
  envs: ["qa", "prod"]

请注意,在部署时间不会删除现有秘密的任何链接 —— ocdeployer 将仅添加新链接。

如何从项目导出秘密以供以后与 --secrets-local-dir 一起使用?

您可以使用以下方法导出所有秘密

$ oc export secrets -o yaml > /tmp/secrets/secrets.yaml

或导出单个秘密对象

$ oc export secret mysecret -o yaml > /tmp/secrets/mysecret.yaml

在您的下一个项目部署中,使用密钥文件

(venv) $ oc login https://my.openshift --token=*************
(venv) $ ocdeployer deploy -a --secrets-local-dir /tmp/secrets/ myproject

环境文件

默认情况下,以下参数在部署时由ocdeployer传递给模板

  • 'NAMESPACE' 对应CLI上选择的工程名称。
  • 'SECRETS_PROJECT' 对应CLI上选择的secrets-src-project

您可以在两个地方定义“环境”文件,以包含更多自定义变量信息。

根环境文件

在您项目的根目录下,一个名为env的目录可以存放设置项目根级别变量的环境yaml文件。假设我们创建一个名为env/myenv.yaml的文件,其内容如下

global:
  # Values defined outside of the "parameters" section are intended to be evaluated during jinja2 processing
  some_var: false
  parameters:
    # Values defined as "parameters" are evaluated by 'oc process' as OpenShift template parameters
    VAR1: "applies to all components"
    VAR2: "also applies to all components"

set1:
  parameters:
    VAR2: "this overrides global VAR2 for only components in the 'set1' set"
    VAR3: "VAR3 applies to all components within the 'set1' service set"

set1/db:
  parameters:
    VAR2: "this overrides global VAR2, and 'set1' VAR2, for only the 'db' component"
    VAR4: "VAR4 only applies to 'db' component"
    # Using keyword {prompt} will cause ocdeployer to prompt for this variable's value at runtime.
    VAR5: "{prompt}"

这允许您在全局级别、在“服务集级别”或“服务集内的组件级别”定义变量。您还可以在“更细粒度级别”覆盖具有相同名称的变量。如果OpenShift模板在其“参数”部分未定义变量,则在处理时将跳过该变量。这允许您在全局级别定义变量,但不必在每个模板中都将每个变量作为参数定义。

服务集环境文件

您还可以为每个服务集在env目录内定义变量。假设我们在templates/set1/env/myenv.yaml创建一个文件,其内容如下

global:
  # Values defined here apply to all components of service set 'set1'
  parameters:
    VAR1: "overrides the VAR1 set globally at root level"

db:
  parameters:
    VAR5: "overrides the VAR5 set on db component at root level"

变量合并和变量覆盖的过程与根级别env文件相同。服务集env文件在处理时会与根env文件合并。但除此之外,服务集级别定义的值将优先于根级别定义的任何值。

选择环境

使用-e--env命令行选项在运行时选择环境,例如

(venv) $ ocdeployer deploy -s myset -e myenv myproject

注意

ocdeployer<v4.0中,没有在服务集内支持env文件,因此仅使用根环境文件,并使用-e/--env-file参数来指定特定的YAML文件路径。这仍然为了向后兼容而得到支持。


通过环境文件覆盖部署配置

环境文件中保留组件键名_cfg。在此键下列出的数据可以以与_cfg.yml文件相同的方式进行结构化,允许您为不同的环境添加或覆盖部署配置的值。

  • 在基本env文件中定义的_cfg部分将与基本_cfg中设置的值合并。
  • 在服务集的env文件中定义的_cfg部分将与该服务集的_cfg中的值合并。

例如,假设您只想在部署到“qa”环境时导入映像。

您的基本配置可能如下所示

deploy_order:
  stage0:
    components: ["set1", "set2", "set3"]

您为set1的服务集配置可能如下所示

images:
- image1: repo/image1:latest

deploy_order:
  stage0:
    components: ["component1", "component2"]

然后,您可以使用以下设置定义templates/set1/env/qa.yml

_cfg:
  images:
  - image1: repo/image1:other-tag
  - image2: repo/image2:latest

这将在部署时间选择--env qa时仅发生以下操作

  • image1 ImageStreamTag的源映像将被覆盖,映射到新的外部标签(other-tag而不是latest
  • 导入image2

使用多个环境文件

您可以在部署时间定义多个环境并将它们合并。示例

env1.yaml

global:
  my_value: true
  my_other_value: false

env2.yaml

global:
  my_value: false
  my_other_value: true

运行以下命令

(venv) $ ocdeployer deploy -s myset -e env1 -e env2 myproject

结果合并env1.yaml和env2.yaml。由于env1在列表中列出在前面,因此此文件中任何匹配的参数条目将覆盖env2中的条目。结果是看起来像这样的值文件

global:
  my_value: true
  my_other_value: true

常见用法

列出可部署的服务集列表

(venv) $ ocdeployer list-sets
Available service sets: ['platform', 'advisor', 'engine', 'vulnerability']

示例:使用“prod”环境部署platform/engine服务集,并从“mysecretsproject”导入密钥

(venv) $ ocdeployer deploy -s platform,engine -e prod --secrets-src-project mysecretsproject mynewproject

您可以使用--scale-resources标志缩放所有资源的cpu/内存请求/限制

(venv) $ ocdeployer deploy -s platform --scale-resources 0.5 mynewproject

此功能将根据所需的系数乘以模板中配置的资源请求/限制。如果您未配置请求/限制,则不会进行扩展。如果以0进行扩展,则将从所有项目中完全删除资源配置,导致您的默认Kubernetes限制范围生效。

您可以使用以下命令从您的项目中删除所有内容(基本上是所有内容,所以请小心)

(venv) $ ocdeployer wipe <openshift project name>

您还可以删除匹配特定标签的所有内容

(venv) $ ocdeployer wipe -l mylabel=myvalue <openshift project name>

已知问题/需要改进

  • 当前脚本在退出前会检查部署是否已移动到'active'状态,但是它们不会修复任何“悬挂”或“卡住”的构建/部署。
  • 目前没有“强制”配置的方法,即删除模板中未列出的内容。

项目详情


发布历史 发布通知 | RSS源

下载文件

下载适用于您平台的可执行文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

ocdeployer-5.7.11.tar.gz (60.8 kB 查看哈希值)

上传时间: 源代码

构建分布

ocdeployer-5.7.11-py3-none-any.whl (42.1 kB 查看哈希值)

上传时间: Python 3

由以下组织支持