Jenkins 和 CMDB 优雅的互动

简述

CMDB在按业务、集群、模块、IP 纳管了基础设施资源后,如何为上层应用提供数据支撑,我想到的场景如下:

  • 监控平台资产按业务/集群/模块/IP 进行管理,告警内容可以帮助我们快速定位故障;
  • 堡垒机资产按业务/集群/模块/IP 进行管理,资产授权可以按不同粒度进行权限分配;
  • 防火墙权限策略按模块区分,避免重复的权限分配及配置混乱;
  • 为CI/CD构建按模块名提供动态化IP参数,有效避免IP的静态分配;

从以上几个场景可以看出,CMDB给我们提供了解决问题的基本思路。

本章我们就从为CI/CD构建提供动态化参数的实际案例来介绍下。

需求

在CI/CD中构建一项job需要目标主机的IP,我们可以通过以下几种方式获得:

  • 构建参数中手动指定
  • ssh publisher 或其他ssh 插件中提前定义
  • 在配置job过程中直接指定

以上几种方式都需要提前知道目标主机的IP,对执行构建人员来说很不友好。那么我们能不能参照DNS的套路,通过特定的名称查询CMDB来获取IP呢? 因此,jenkins从CMDB中根据模块名,动态获取模块对应IP的解决方案就有了。

通常情况下,较大的企业都会基于CMDB配套企业服务总线(ESB),来给各个平台提供服务。显然,我们的小企业是不具备这种能力的。因此我们需要借助CMDB API,自行将其封装成标准格式,然后通过Jenkins 调用API 来提供动态化参数,实现参数化构建。

整理流程如下:
在这里插入图片描述

API封装

通常情况下CMDB 自带的API 返回的结果数据比较多,上层的应用调用需要进行层层过滤筛选才能获得最终的结果。

例如蓝鲸CMDB 根据模块查询IP 接口,获取的结果数据为:

# 请求cmdb api 
curl http://paas.bk.net/api/c/compapi/v2/cc/search_host/ -d
{
    "bk_app_code": "bk-test",
    "bk_app_secret": "62bc9c22-334d-4fcd-9523-991662163b67",
    "bk_username": "admin",
    "condition": [
        {
            "bk_obj_id": "biz",
            "fields": [],
            "condition": [
                {
                    "field": "bk_biz_name",
                    "operator": "$in",
                    "value": ["生产环境"]
                }
            ]
        },
        {
            "bk_obj_id":"module",
            "fields":[""],
            "condition":[
                {
                    "field": "bk_module_name",
                    "operator": "$in",
                    "value": ["test"]
                }
            ]
        }
    ],
    "page": {
        "start": 0,
        "limit": 1,
        "sort": "bk_host_id"
    },
    "pattern": ""
}


# 返回数据
{
    "message": "success",
    "code": 0,
    "data": {
        "count": 2,
        "info": [
            {
                "host": {
                    "bk_cpu": null,
                    "bk_isp_name": null,
                    "host_host_manageip": "",
                    "bk_os_name": "",
                    "bk_province_name": null,
                    "bk_host_id": 1861,
                    "import_from": "3",
                    "bk_os_version": "",
                    "bk_disk": null,
                    "operator": null,
                    "create_time": "2019-12-08T14:24:04.924+08:00",
                    "bk_mem": null,
                    "bk_host_name": "",
                    "bk_host_innerip": "10.168.202.58",
                    "bk_host_type": "2",
                    "bk_comment": "",
                    "bk_host_jiwei": "",
                    "bk_host_band": "",
                    "bk_os_bit": "",
                    "bk_outer_mac": "",
                    "bk_host_jigui": "",
                    "bk_asset_id": "",
                    "bk_service_term": null,
                    "bk_cloud_id": [
                        {
                            "bk_obj_name": "",
                            "id": "0",
                            "bk_obj_id": "plat",
                            "bk_obj_icon": "",
                            "bk_inst_id": 0,
                            "bk_inst_name": "default area"
                        }
                    ],
                    "bk_sla": null,
                    "bk_cpu_mhz": null,
                    "bk_service_limit": null,
                    "bk_host_outerip": "",
                    "bk_state_name": null,
                    "bk_os_type": null,
                    "bk_host_stat": "1",
                    "bk_mac": "",
                    "bk_bak_operator": null,
                    "bk_supplier_account": "0",
                    "bk_host_model": "",
                    "bk_sn": "",
                    "bk_cpu_module": ""
                },
                "set": [],
                "biz": [
                    {
                        "bk_biz_id": 3,
                        "language": "1",
                        "life_cycle": "2",
                        "bk_biz_developer": "",
                        "bk_biz_maintainer": "admin",
                        "bk_biz_tester": "",
                        "time_zone": "Asia/Shanghai",
                        "default": 0,
                        "create_time": "2020-12-09T11:12:04.449+08:00",
                        "bk_biz_productor": "",
                        "bk_supplier_account": "0",
                        "operator": "admin",
                        "bk_biz_name": "生产环境",
                        "last_time": "2021-11-29T09:17:09.837+08:00",
                        "bk_supplier_id": 0
                    }
                ],
                "module": [
                    {
                        "default": 0,
                        "TopModuleName": "生产环境",
                        "bk_module_id": 1358
                    }
                ]
            }
        ]
    },
    "result": true,
    "request_id": "02ed84f480e0412980923cb1959973ba"
}

其中从请求的json数据可以得出查询条件:

  • 业务名: 生产环境
  • 模块名: test

返回的结果包含了很多信息,但是我们只想要test模块所部署的IP:10.168.202.58,其他信息可以忽略。如果直接使用原生API ,我们要花费很大的精力在解析json数据上。因此我们需要单独封装一个API,功能需求不变,即根据业务、模块查询IP


# 请求封装后的api 
curl http://10.168.209.88:8080/cmdb/getHost/?module=test&env=pro

{"status": 200, "module": "test", "env": "pro", "hosts": ["10.168.202.58"]}

通过简单的参数查询,即可得到我们想要的结果,后面只需愉快的接入了。

Jenkins接入

Jenkins我们以管理应用的job为例,功能为启动、停止、重启指定应用。

在参数化构建过程中,我们只需输入应用名,就可以获得该应用名所对应的部署IP,后面的一系列操作就可以基于此IP按需实现。

1.参数化构建

在这里插入图片描述
其中:

  • APP_NAME: 对应CMDB中的模块名
  • ACTION: 启动、停止、重启操作
  • HOST: 模块名对应的IP,调用api后结果以单选框的形式展现。

2.Active Choices Reactive Parameter

在这里插入图片描述

由于Jenkins 是基于grovvy开发,因此我们需要在Groovy Script处调用封装的API ,实现根据模块名动态获取IP的功能,得到的结果以Single Select即单选框的形式展现。

另外,Referenced parameters 是将实际输入的APP_NAME参数指,传递到Groovy Script中,实现按需调用。

3.构建结果

在这里插入图片描述

总结

通过CMDB给Jenkins提供动态参数,使CMDB成为数据孤岛的可能性进一步降低,同时也给Jenkins带来了另一种最佳实践。这种方式类似于DNS,我们不需要知道IP地址,只需知道应用名就可以快速获取IP进行操作了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值