- 云原生
- 运维
- 安全
【免费下载链接】cloud-custodian
Rules engine for cloud security, cost optimization, and governance, DSL in yaml for policies to query, filter, and take actions on resources
本指南围绕 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逐段拆解这条策略:
| 字段 | 取值 | 含义 |
|---|---|---|
name | start-all-stopped-dev-instances | 策略名称,运行后会在输出目录下生成同名子目录,存放日志与资源 JSON 文件 |
resource | oci.instance | 声明操作 OCI 计算实例资源,由 OCI Provider 的Instance资源类注册(见下文源码解析) |
filters[0] | value过滤器 | 匹配lifecycle_state等于STOPPED的实例,op: eq显式声明相等比较 |
filters[1] | value过滤器 | 使用点号路径freeform_tags.custodian_dev读取实例自由格式标签字典中的键custodian_dev,要求其值等于字符串'true' |
actions | start | 对过滤后命中实例执行启动动作,对应 OCI SDK 的instance_action(..., action="START")调用 |
需要特别注意的是两点:
- 标签键的嵌套访问:OCI 实例资源中的
freeform_tags是一个键值字典,Cloud Custodian 的value过滤器(继承自 c7n 核心的ValueFilter)支持用点号路径深入字典取值,因此freeform_tags.custodian_dev实际读取的是{"custodian_dev": "true"}中的值。 - 值的类型: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_ociOCI 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 客户端配置:
- 若环境变量
OCI_FINGERPRINT、OCI_KEY_FILE、OCI_REGION、OCI_TENANCY、OCI_USER全部存在,则直接使用环境变量构造配置(各变量名定义见 tools/c7n_oci/c7n_oci/constants.py); - 否则若指定了
--profile,则从 OCI 配置文件读取对应 profile; - 否则读取默认配置(
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_error | boolean(默认 true) | 动作执行失败时是否抛出异常;设为 false 时会把失败资源记入failed_resources并从处理列表中移除 |
block_until_completion | boolean | 是否开启批处理模式等待动作完成 |
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
相关推荐
Cloud Custodian OCI 实战:查询并批量移除计算实例标签(oci.instance remove-tag)
Cloud Custodian OCI 实战:查询并批量移除计算实例标签(oci.instance remove tag) 本文基于 Cloud Custodi
云原生运维安全Cloud Custodian OCI 实战:用 reboot 动作重启 Compute 实例
Cloud Custodian OCI 实战:用 reboot 动作重启 Compute 实例 本文基于 Cloud Custodian(c7n)OCI 插件的
云原生运维安全Cloud Custodian 实战:用 ec2-invalid-ami 策略自动停止使用未批准 AMI 的 EC2 实例
Cloud Custodian 实战:用 ec2 invalid ami 策略自动停止使用未批准 AMI 的 EC2 实例 本文基于 Cloud Custodi
云原生运维安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考