☰
使用 Cloud Custodian OCI Provider 批量启动带特定标签的已停止实例
2026/10/12 11:30:38 网站建设 项目流程
  • 云原生
  • 运维
  • 安全

【免费下载链接】cloud-custodian

Rules engine for cloud security, cost optimization, and governance, DSL in yaml for policies to query, filter, and take actions on resources

项目地址:https://gitcode.com/gh_mirrors/cl/cloud-custodian
点击查看免费下载

本指南围绕 OCI(Oracle Cloud Infrastructure)计算实例的“批量启动”场景展开:通过一条 Cloud Custodian 策略,筛选出所有处于STOPPED状态、且带有custodian_dev自由格式标签的实例,并统一执行启动动作。读完本文,你将掌握oci.instance资源的查询与过滤写法、start动作的用法,以及从安装认证到运行验证、再到源码原理的完整链路。

场景背景:为什么需要“按标签批量启动”

在 OCI 云环境中,开发环境的实例常被批量停机以节省成本,或在夜间被统一关闭。当开发周期开始时,运维人员又需要将这些实例重新拉起。逐个手动启动效率低且容易遗漏,而 Cloud Custodian 提供了一种声明式的 YAML 策略 DSL(领域专用语言),可以"查询 → 过滤 → 执行动作"一气呵成。

本文对应的官方示例文档位于 docs/source/oci/examples/instance_start_dev_instances_compute.rst,其核心思路是:利用 OCI 实例的自由格式标签(freeform tags)作为"该实例属于开发环境"的标记,再结合实例生命周期状态(lifecycle state)过滤,最后批量执行启动。

核心策略:启动所有带 custodian_dev 标签的已停止实例

示例文档给出了如下完整策略:

policies: - name: start-all-stopped-dev-instances description: | Start all the stopped dev instances resource: oci.instance filters: - type: value key: lifecycle_state value: 'STOPPED' op: eq - type: value key: freeform_tags.custodian_dev value: 'true' actions: - start

逐段拆解这条策略:

字段取值含义
namestart-all-stopped-dev-instances策略名称,运行后会在输出目录下生成同名子目录,存放日志与资源 JSON 文件
resourceoci.instance声明操作 OCI 计算实例资源,由 OCI Provider 的Instance资源类注册(见下文源码解析)
filters[0]value过滤器匹配lifecycle_state等于STOPPED的实例,op: eq显式声明相等比较
filters[1]value过滤器使用点号路径freeform_tags.custodian_dev读取实例自由格式标签字典中的键custodian_dev,要求其值等于字符串'true'
actionsstart对过滤后命中实例执行启动动作,对应 OCI SDK 的instance_action(..., action="START")调用

需要特别注意的是两点:

  1. 标签键的嵌套访问:OCI 实例资源中的freeform_tags是一个键值字典,Cloud Custodian 的value过滤器(继承自 c7n 核心的ValueFilter)支持用点号路径深入字典取值,因此freeform_tags.custodian_dev实际读取的是{"custodian_dev": "true"}中的值。
  2. 值的类型:YAML 中'true'带引号表示字符串。在 OCI 控制台或 CLI 打标签时,若标签值写入的是布尔或字符串,务必与策略中的字面量保持一致,否则过滤器不会命中。

前置准备:安装与认证

本策略运行在 Cloud Custodian 的 OCI Provider(Beta)之上,完整安装与认证说明见 docs/source/oci/gettingstarted.rst。

安装 c7n 与 c7n-oci

OCI 插件是可选的独立包,需先安装基础 Cloud Custodian(要求运行在受支持的 Python 版本上),再安装 OCI Provider:

pip install c7n pip install c7n-oci

若希望从当前仓库源码安装最新版,可进入仓库后执行:

pip install -e ./cloud-custodian pip install -e ./cloud-custodian/tools/c7n_oci

OCI Provider 包的工程配置见 tools/c7n_oci/pyproject.toml:包名为c7n_oci(当前版本 0.1.27),要求 Python>=3.9.2,依赖c7n与oci>=2.106,<3.0,并额外固定pyopenssl>=24。

配置认证凭据

Cloud Custodian 在运行时需要能够访问你的 OCI 资源,推荐通过 OCI CLI 初始化认证配置:

oci setup config

配置完成后,Cloud Custodian 会隐式读取该配置。从源码看,tools/c7n_oci/c7n_oci/session.py 中的SessionFactory会按以下优先级构建 OCI 客户端配置:

  1. 若环境变量OCI_FINGERPRINT、OCI_KEY_FILE、OCI_REGION、OCI_TENANCY、OCI_USER全部存在,则直接使用环境变量构造配置(各变量名定义见 tools/c7n_oci/c7n_oci/constants.py);
  2. 否则若指定了--profile,则从 OCI 配置文件读取对应 profile;
  3. 否则读取默认配置(DEFAULTprofile)。

实例主体认证(Instance Principal)

当 Cloud Custodian 直接运行在 OCI 实例上时,可以使用实例主体认证,只需设置:

export OCI_CLI_AUTH=instance_principal

此时Session.client()会使用InstancePrincipalsSecurityTokenSigner签名器,并从签名器获取tenancy_id与region。

运行策略与验证输出

将策略保存为 YAML 文件(例如custodian.yml),然后执行:

custodian run --output-dir=. custodian.yml

成功执行时,命令行会输出类似下面的日志(示例来自 docs/source/oci/gettingstarted.rst 中的运行记录):

2023-05-25 18:15:53,132: custodian.oci.session:INFO Successfully authenticated user ... 2023-05-25 18:15:59,178: custodian.oci.query:INFO List of compartment IDs fetched using the ResourceSearchClient: {'ocid1.test.oc1..<unique_ID>EXAMPLE-compartmentId-1-Value', 'ocid1.test.oc1..<unique_ID>EXAMPLE-compartmentId-3-Value'} 2023-05-25 18:16:01,118: custodian.policy:INFO policy:filter-for-compute-name resource:oci.instance region: count:1 time:7.98 2023-05-25 18:16:05,474: custodian.oci.resources.compute:INFO Received status 200 for PUT:update_instance ...

针对start动作,源码 tools/c7n_oci/c7n_oci/resources/compute.py 会记录类似Received status 200 for POST:START的日志,标识 OCI 计算服务的启动请求已受理。运行结束后,--output-dir下会生成以策略名命名的目录,内含日志与描述命中资源的 JSON 文件。

控制查询范围:OCI_COMPARTMENTS

默认情况下,策略会针对租户(tenancy)内所有包含该类资源的 compartment 执行查询。你可以通过OCI_COMPARTMENTS环境变量指定一个或多个 compartment,多个 OCID 用逗号分隔:

export OCI_COMPARTMENTS=ocid1.test.oc1..<unique_ID>EXAMPLE-compartmentId-2-Value,ocid1.test.oc1..<unique_ID>EXAMPLE-compartmentId-3-Value

这一行为在源码中有直接体现:QueryResourceManager.source_type属性(tools/c7n_oci/c7n_oci/query.py)会判断——若设置了OCI_COMPARTMENTS则使用describe-native源(逐 compartment 调用list_instances),否则使用describe-search源(先通过ResourceSearchClient发现资源所在的 compartment,再逐 compartment 拉取完整资源)。两种源都会以(tenancy, region, resource, compartment_id, query)为缓存键做结果缓存。

从源码理解 start 动作的底层实现

资源注册:oci.instance

compute.py 中,Instance类通过@resources.register("instance")注册为oci.instance,其resource_type声明了:

  • service = "oci.core"、client = "ComputeClient":使用 OCI Python SDK 的 Compute 客户端;
  • enum_spec = ("list_instances", "items[]", None):枚举资源时调用list_instances;
  • id = "id"、name = "display_name":资源的唯一标识与展示名;
  • search_resource_type = "instance":用于describe-search源的结构化搜索。

InstanceStart 动作

start动作注册于 compute.py:

@Instance.action_registry.register("start") class InstanceStart(OCIBaseAction): schema = type_schema("start", rinherit=OCIBaseAction.schema) def perform_action(self, resource): client = self.manager.get_client() response = client.instance_action( instance_id=resource["id"], action="START", ) log.info(f"Received status {response.status} for POST:START {response.request_id}") return response

即:对每个命中资源调用 OCI SDK 的instance_action,传入instance_id(即资源的id字段)与动作START。同一文件还注册了同族的stop(SOFTSTOP/ 强制STOP)与reboot(SOFTRESET/ 强制RESET)动作,可参见 instance_poweron_compute.rst 中"启动单个已停止实例"的对照示例。

OCIBaseAction 的通用行为

所有 OCI 动作继承自 tools/c7n_oci/c7n_oci/actions/base.py 的OCIBaseAction,其 schema 额外支持两个通用选项:

参数类型说明
fail_on_errorboolean(默认 true)动作执行失败时是否抛出异常;设为 false 时会把失败资源记入failed_resources并从处理列表中移除
block_until_completionboolean是否开启批处理模式等待动作完成

process()会逐个资源调用子类实现的perform_action(resource),并汇总succeeded_resources与failed_resources结果。

测试验证:仓库如何保证该功能可靠

仓库在 tools/c7n_oci/tests/test_instance.py 中提供了test_instance_start测试用例:

@terraform("compute", scope="class") def test_instance_start(self, test, compute): ocid = self._get_instance_details(compute) session_factory = test.oci_session_factory() policy = test.load_policy( { "name": "instance-start", "resource": "oci.instance", "filters": [ {"type": "value", "key": "id", "value": ocid}, ], "actions": [{"type": "start"}], }, session_factory=session_factory, ) policy.run() resource = self._fetch_instance_validation_data(policy.resource_manager, ocid) test.assertEqual(resource["id"], ocid) assert resource["lifecycle_state"] in ["STARTING", "RUNNING"]

该测试通过 Terraform 编排真实的计算实例,运行"按 id 过滤 + start 动作"的策略,随后校验实例生命周期状态进入STARTING或RUNNING,从而证明start动作确实触发了实例启动。对应的 VCR 录制数据位于tools/c7n_oci/tests/cassettes/TestInstance.test_instance_start.yml。这也意味着:本文示例策略中使用的lifecycle_state过滤器取值STOPPED,与 OCI 实例生命周期枚举中的状态值保持一致。

组合建议与注意事项

  • 与其他过滤条件组合:除了按标签与状态过滤,还可以组合display_name(见 gettingstarted.rst 示例一)、shape(示例二)等字段,或通过策略级query关键字在查询阶段先行收窄范围(例如query: [{'lifecycle_state': 'STOPPED'}])。
  • 先 dry-run 再执行:可以把actions先注释掉运行一次,从输出目录的 JSON 中确认命中实例集合,避免误启动生产实例;也可以将标签改为更严格的值(如custodian_dev: 'true'与部门标签联合使用)。
  • 关注 Beta 状态:OCI Provider 目前标注为 Beta,相关能力以 docs/source/oci/gettingstarted.rst 与仓库源码为准,生产环境使用前建议先在测试租户验证。
  • 多 compartment 的执行范围:不设置OCI_COMPARTMENTS时查询覆盖整个租户,可能命中大量资源,建议结合MaxResourceLimit或先以单个 compartment 验证。

通过本文的策略与源码解析,你已经可以从零搭建一条"按标签批量启动 OCI 开发实例"的自动化治理策略,并可在此基础上自由组合其他过滤条件与动作(stop、reboot、update、remove-tag等),实现完整的实例生命周期治理。

  • 云原生
  • 运维
  • 安全

【免费下载链接】cloud-custodian

Rules engine for cloud security, cost optimization, and governance, DSL in yaml for policies to query, filter, and take actions on resources

项目地址:https://gitcode.com/gh_mirrors/cl/cloud-custodian
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询