使用fastapi和pulumi搭建基于Azure云的IAC Restful API服务 — 对外发布

图片

图片

前言

在IAC(即Infrastructure As Code,基础设施即代码)领域,Terraform 是一个老牌工具,使用HCL(HashiCorp Configuration Language)语言来编写配置文件。它支持几乎所有主流的云提供商,如AWS、Azure、GCP等,通过如下几个关键步骤管理基础设施:编写配置文件、初始化环境、生成执行计划、应用计划以及查看状态。

Pulumi 则是一个较新的IAC工具,支持使用多种常见的编程语言(如TypeScript、Python、Go、C#)来编写基础设施代码,而不仅限于声明式语法。这带来了许多灵活性和优势:

  1. 使用常用编程语言:Pulumi允许使用者使用熟悉的编程语言编写基础设施配置,这样可以使用语言本身的功能,如条件语句、循环、函数和模块化,提高代码的可读性和重用性。

  2. 更好的集成:Pulumi在与现有开发工具链(如CI/CD管道、测试框架等)集成方面表现出色,因此可以使用流行的编程生态系统中的库和工具。这对DevOps团队来说非常有吸引力。

  3. 灵活的状态管理:虽然Terraform也有状态文件用于记录资源的现实状态,Pulumi进一步简化了状态管理,允许使用不同的存储后端,包括云存储和Pulumi自己的服务。

  4. 更高的可扩展性:Pulumi支持JavaScript、TypeScript、Python、Go和C#等多种语言,这让它能够适应更广泛的需求和团队技术栈,可以更灵活地处理复杂的基础设施场景。

本文使用Python语言, 以pulumi作为后端IAC工具,服务端采用FastAPI框架提供Restful能力,来实现基于Azure云的IAC Restful API服务

架构设计

图片

架构说明:

  • 开发人员调用http接口来进行IAC操作

  • FastAPI服务端分为2个部分,一个gateway负责对外提供restful api服务,一个backend端负责解析前端数据,调用pulumi模块生成IAC代码

  • 任务信息会存入mysql数据库,起到任务追溯的作用以及作为资源cmdb的数据源

  • IAC操作完成后,会将此次操作变更同步进入资源CMDB

Pulumi模块说明

与经典的命令行模式执行pulumi来进行资源创建/变更不同,在本架构中使用Pulumi Automation来实现IAC能力。Pulumi Automation提供了一种编程接口,使得基础设施管理过程可以完全自动化和自定义。

Pulumi模块支持哪些资源

该模块涉及:

Azure资源模块

Resource GroupAks Cluster(ManagedCluster)Aks Nodepool(AgentPool)Availability SetContainer RegistryData FactoryDatabricks Access ConnectorDatabricks WorkspaceKey VaultLoad BalancerMysql Flexible ServerMysql Single ServerNetwork InterfaceNetwork Security GroupPrivate ZoneRecovery Service VaultRedisRole AssignmentRoute TableStorage AccountSubnetUser Assigned IdentityVirtual Machine

目前我们的pulumi模块现已支持以上azure资源

感兴趣的可以联系我们,提供相关代码模块

主要特点

  1. 集成灵活性:利用Pulumi Automation,可以更轻松地将基础设施管理操作嵌入到现有的应用程序或平台中。这对于需要与其他系统进行复杂交互的场景尤为适用,例如动态响应用户请求或事件驱动的基础设施变更。

  2. 复用性和模块化:通过将Pulumi的命令行操作封装在代码中,Pulumi Automation允许我们创建更具复用性和模块化的基础设施管理代码库。这对于大型团队和复杂项目尤其有价值,因为代码更易于维护和共享。

  3. 状态和并行处理:使用Pulumi Automation,可以更细致地管理资源状态和并行操作。我们可以根据具体情况编写代码来处理不同的资源状态,以及根据依赖关系有序地创建或销毁资源,这可以显著提升执行效率和可靠性。

  4. 错误处理和重试机制:通过编写自定义的错误处理和重试逻辑,Pulumi Automation可以更健壮地应对基础设施操作中的各种可能错误。我们可以在代码中捕获异常并进行适当的重试或回滚动作,而不必依赖于外部脚本或手动操作。

依赖模块

需求python 3.7+, 执行pip install -r requirements.txt来安装依赖模块

requirements.txt

pulumi>=3.0.0,<4.0.0pulumi-azure-native>=1.0.0,<2.0.0fastapi[all]jsonify>=0.5,<0.6pydantic>=1.9.1,<1.9.2pymysqlpyparsingpulumi_azure

实验步骤

前置条件

Python 

需求python 3.7+, 执行pip install -r requirements.txt来安装依赖模块 

Service Principal

服务主体必须对该订阅具有完全访问权限

pulumi环境变量

必须配置PULUMI_CONFIG_PASSPHRASE供pulumi连接到您的stack,若您使用非本地文件作为backend,则还需配置相应的backend所需字段

mysql数据库(可选)

用以记录资源创建任务信息

资源CMDB(可选)

根据自身需要,可配置一个资源CMDB,存放云资源实时参数配置与状态,以供实际使用

流程说明

图片

  • FastAPI gateway将异步调用backend方法,传递前端参数给到后端方法

  • FastAPI后端将参数入库,并调用pulumi模块,生成IAC代码

  • Pulumi模块内部使用Azure API,进行IAC操作

以下步骤为可选步骤

  • 资源信息同步至cmdb

  • FastAPI接口提供资源信息查询

步骤一、创建fastapi应用服务端

使用以下代码创建fastapi app(即对外restful api服务)

app.py

@auto_deploy_api.post("/create_resource")
async def create_res(VERABLES_DICT: Item, backgroundTasks: BackgroundTasks):
    VERABLES = VERABLES_DICT.VERABLES
    try:
        # 启动异步任务,因为创建资源耗时较长,http请求不应也无法一直保持
        backgroundTasks.add_task(create_resource, VERABLES, id)
        return {"message": "Task running at backend", "id": id}
    except auto.StackAlreadyExistsError:
        return HTTPException(status_code=409,detail="application already exists")
    except Exception as e:
        return Response(status_code=500, content=repr(e))

步骤二、集成fastapi与pulumi模块

将pulumi模块与fastapi服务集成在同一目录下,文件架构如下:

图片

app.py:fastapi 应用入口文件,定义restful接口

auto_deploy_inline.py:调用pulumi模块,执行IAC操作

pulumi_resources/IAC_resource:存放pulumi模块

create_resource 

def create_resource(VERABLES, task_id):
    project_name = VERABLES["GLOBAL_VARS"]["PROJECT_NAME"]
    app_name = VERABLES["GLOBAL_VARS"]["APPLICATION_NAME"]
    env = VERABLES["GLOBAL_VARS"]["ENV"]
    stack_name = "%s-%s-%s-stack" % (project_name, app_name, env)
    try:
        # 此方法处理前端传入的参数,调用pulumi模块,进行资源创建,此处仅以网络资源为例
        def resource_init():
            if "RESOURCE_GROUP" not in VERABLES.keys():
                raise Exception("Resource group is mandatory")
            rg = ResourceGroup(VERABLES["RESOURCE_GROUP"]["NAME"], location)
            if "NETWORK" in VERABLES.keys():
                if "ROUTE_TABLE" in VERABLES["NETWORK"].keys():
                    for rt_ele in VERABLES["NETWORK"]["ROUTE_TABLE"]:
                        RouteTable(rt_ele["name"], location, None, **rt_ele)
                if "NETWORK_SECURITY_GROUP" in VERABLES["NETWORK"].keys():
                    for nsg_ele in VERABLES["NETWORK"]["NETWORK_SECURITY_GROUP"]:
                        NetworkSecurityGroup(nsg_ele["name"], location, None, **nsg_ele)
             
 
        resource_stack = auto.create_or_select_stack(stack_name=stack_name,
                                                     project_name=app_name,
                                                     program=resource_init)
 
 
        update_resource_creation_task_record(data_dict)
        print("Start preview...")
        resource_up_res = resource_stack.preview(on_output=print)
        print("Preview OK...")
        time.sleep(1)
        print("Start up...")
        resource_up_res = resource_stack.up(on_output=print)
        print("Up OK...")
        data_dict["status"] = "successed"
        update_resource_creation_task_record(data_dict)
        return (resource_up_res.stdout)
    except Exception as e:
        data_dict["status"] = "failed"
        data_dict["output"] = repr(e)
        update_resource_creation_task_record(data_dict)

步骤三、启动fastapi应用

cd $YOURPATH/resource_deploy/auto_deploy_fastapi
uvicorn app:auto_deploy_api --host 0.0.0.0 --port 8000

步骤四、Postman调用接口创建资源

接下来,我们就可以通过http请求的方式,调用pulumi的IAC能力,操作Azure云的资源了

图片

示例payload

payload

{
    'VERABLES': {
        'GLOBAL_VARS': {
            'PROJECT_NAME': 'auto',
            'APPLICATION_NAME': 'auto',
            'ENV': 'dev',
            'LOCATION': 'chinanorth3',
            'SUBSCRIPTION_ID': '***********'
        },
        'RESOURCE_GROUP': {
            'NAME': 'test-pulumi-rg',
            'TAGS': {
                'ApplicationID': 'ITPlatform',
                'ApplicationName': 'ITPlatform'
            }
        },
        'NETWORK': {
            'ROUTE_TABLE': [{
                'name': 'test-rt01',
                'resource_group_name': 'test-network-rg01',
                'routes': [{
                    'name': 'rule1',
                    'address_prefix': '0.0.0.0/0',
                    'next_hop_type': 'VirtualAppliance',
                    'next_hop_ip_address': '10.20.128.140'
                }]
            }],
            'NETWORK_SECURITY_GROUP': [{
                'name': 'test-nsg01',
                'resource_group_name': 'test-network-rg01',
                'rules': [{
                    'access': 'Allow',
                    'destination_address_prefix': '*',
                    'destination_port_range': '*',
                    'direction': 'Inbound',
                    'name': 'rule1',
                    'priority': 1001,
                    'protocol': '*',
                    'source_address_prefixes': ['10.20.2.0/24'],
                    'source_port_range': '*'
                }]
            }]
        }
}

附言

用类似的方法,可以创建删除资源的接口与查看任务状态的接口,示例如下:

app.py

@auto_deploy_api.delete("/delete_resource")
async def delete_res(VERABLES_DICT: Item, backgroundTasks: BackgroundTasks):
    VERABLES = VERABLES_DICT.VERABLES
    try:
        # 启动异步任务,因为删除资源耗时较长,http请求不应也无法一直保持
        backgroundTasks.add_task(delete_resource, VERABLES)
        return {"message": "Will delete"}
    except auto.StackNotFoundError:
        return HTTPException(status_code=404,detail="application not found")
    except Exception as e:
        return Response(status_code=500, content=repr(e))
 
@auto_deploy_api.post("/stack_status")
async def delete_res(VERABLES_DICT: Item):
    VERABLES = VERABLES_DICT.VERABLES
    try:
        data = get_stack_status(VERABLES["ID"])
        return data
    except auto.StackNotFoundError:
        return HTTPException(status_code=404,detail="id not found")
    except Exception as e:
        return Response(status_code=500, content=repr(e))

auto_deploy_inline.py

def delete_resource(VERABLES):
    stack_name = VERABLES["GLOBAL_VARS"]["STACK_NAME"]
    project_name = VERABLES["GLOBAL_VARS"]["PROJECT_NAME"]
    client_id, client_secret, client_tenant = get_azure_sp()
    def resource_init():
        pass
 
    resource_stack = auto.create_or_select_stack(stack_name=stack_name,
                                                 project_name=app_name,
                                                 program=resource_init)
    resource_stack.refresh(on_output=print)
    resource_destroy_res = resource_stack.destroy(on_output=print)
  
    return (resource_destroy_res.stdout)
 
 
def get_stack_status(id):
    data = get_task_record(id)
    if len(data) == 0:
        raise auto.StackNotFoundError
    data_dict = {"id": id, "stack_name": data[0][1], "status": data[0][3],
                 "payload": data[0][2], "output": data[0][4]}
 
    return data_dict

调用方式:

图片

图片

另外,若配置了资源CMDB,可在FastAPI Gateway上配置资源信息查询接口,示例如下:

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/728481.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

戴尔外星人原厂系统美版改国行正确识别本机SN,支持F12 Support Assist OS Recevory恢复重置识别SN服务编码

1.重新部署可以永久正确识别My Alienware和Support Assist服务编码 原厂系统远程恢复安装&#xff1a;https://pan.baidu.com/s/166gtt2okmMmuPUL1Fo3Gpg?pwdm64f 提取码:m64f 2.安装有两个软件和官网主页会识别原机的SN码&#xff0c;就是本机服务编码&#xff08;my Alie…

Day15—热点搜索词统计

一、要求 根据用户上网的搜索记录对每天的热点搜索词进行统计&#xff0c;以了解用户所关心的热点话题。 要求完成&#xff1a;统计每天搜索数量前3名的搜索词&#xff08;同一天中同一用户多次搜索同一个搜索词视为1次&#xff09;。 二、数据 三、配置scala环境 1.下载sca…

vue 中实现用户上传文件夹的功能

vue 中实现上传文件夹的功能 使用 input 元素的 webkitdirectory 属性使用 vue-simple-uploader 组件 vue 中文件上传一般都是用 element 中的 upload 组件&#xff0c;upload 组件可以实现单个文件或者多个文件的上传&#xff0c;但是无法通过选择文件夹上传其中文件。 要实现…

账号和权限的管理

文章目录 管理用户账号和组账号用户账号的分类超级用户普通用户程序用户 UID&#xff08;用户id)和(组账号)GIDUID用户识别号GID组标识号 用户账号文件添加用户账号设置/更改用户口令 管理用户账号和组账号 用户账号的分类 超级用户 root 用户是 Linux 操作系统中默认的超级…

计算机毕业设计hadoop+spark+hive游戏推荐系统 游戏数据分析可视化大屏 steam游戏爬虫 游戏大数据 大数据毕业设计 机器学习 知识图谱

游戏推荐系统开题报告 一、引言 随着信息技术和网络技术的飞速发展&#xff0c;电子游戏已成为人们日常生活中不可或缺的一部分。然而&#xff0c;面对海量的游戏资源&#xff0c;用户往往难以找到适合自己的游戏。因此&#xff0c;构建一个高效、准确的游戏推荐系统显得尤为…

Go-知识并发控制mutex

Go-知识并发控制mutex 1. 介绍2. 数据结构2.1 Mutex 结构体2.2 Mutex 方法 3. 加锁解锁过程3.1 简单加锁3.2 加锁被阻塞3.3 简单解锁3.4 解锁并唤醒协程 4. 自旋过程4.1 什么是自旋4.2 自旋条件4.3 自旋的优势4.4 自旋的问题 5. Mutex 模式5.1 Normal 模式5.2 Starving 模式(饥…

React实现H5手势密码

监测应用进入前后台 在JavaScript中&#xff0c;监听H5页面是否在前台或后台运行&#xff0c;主要依赖于Page Visibility API。这个API在大多数现代浏览器中都是支持的&#xff0c;包括苹果的Safari和谷歌的Chrome&#xff08;也就基本覆盖了Android和iOS平台&#xff09;。下…

RabbitMQ 学习笔记

RabbitMQ学习笔记 一些概念 Broker &#xff1a;RabbitMQ服务。 virtual host&#xff1a; 其实就是分组。 Connection&#xff1a;连接&#xff0c;生产者消费者与Broker之间的TCP连接。 Channel&#xff1a;网络信道&#xff0c;轻量级的Connection&#xff0c;使用Chann…

【C++】一个极简但完整的C++程序

一、一个极简但完整的C程序 我们编写程序是为了解决问题和任务的。 1、任务&#xff1a; 某个书店将每本售出的图书的书名和出版社&#xff0c;输入到一个文件中&#xff0c;这些信息以书售出的时间顺序输入&#xff0c;每两周店主会手工计算每本书的销售量、以及每个出版社的…

任务调度框架革新:TASKCTL在Docker环境中的高级应用

Docker&#xff1a;轻量级容器化技术的魅力 Docker 作为一款开源的轻量级容器化技术&#xff0c;近年来在 IT 界掀起了一股热潮。它通过封装应用及其运行环境&#xff0c;使得开发者可以快速构建、部署和运行应用。Docker 的优势在于其轻量级、可移植性和可扩展性&#xff0c;它…

http和https的区别在哪

HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;超文本传输安全协议&#xff09;之间存在几个关键区别主要涉及安全性、端口、成本、加密方式、搜索引擎优化&#xff08;SEO&#xff09;、身份验证等方面 1、安全性&#xff1a;HTTP&#xff08;超文本传输协议…

Python | Leetcode Python题解之第171题Excel列表序号

题目&#xff1a; 题解&#xff1a; class Solution:def titleToNumber(self, columnTitle: str) -> int:number, multiple 0, 1for i in range(len(columnTitle) - 1, -1, -1):k ord(columnTitle[i]) - ord("A") 1number k * multiplemultiple * 26return n…

CASS界址点顺序重排

1、绘制一个宗地&#xff0c;如下&#xff1a; 2、注记界址点号&#xff0c;如下 3、【地籍】--【调整宗地内界址点顺序】&#xff0c;如下&#xff1a; 重排完成后&#xff0c;点击工具栏的【重】按钮&#xff0c;即可刷新标注。

Docker 拉取镜像失败处理 配置使用代理拉取

解决方案 1、在 /etc/systemd/system/docker.service.d/http-proxy.conf 配置文件中添加代理信息 2、重启docker服务 具体操作如下&#xff1a; 创建 dockerd 相关的 systemd 目录&#xff0c;这个目录下的配置将覆盖 dockerd 的默认配置 代码语言&#xff1a;javascript 复…

Golang | Leetcode Golang题解之第171题Excel列表序号

题目&#xff1a; 题解&#xff1a; func titleToNumber(columnTitle string) (number int) {for i, multiple : len(columnTitle)-1, 1; i > 0; i-- {k : columnTitle[i] - A 1number int(k) * multiplemultiple * 26}return }

Linux——ansible关于“文件操作”的模块

修改文件并将其复制到主机 一、确保受管主机上存在文件 使用 file 模块处理受管主机上的文件。其工作方式与 touch 命令类似&#xff0c;如果不存在则创建一个空文件&#xff0c;如果存在&#xff0c;则更新其修改时间。在本例中&#xff0c;除了处理文件之外&#xff0c;Ansi…

2024广东省职业技能大赛云计算赛项实战——Redis主从架构

Redis主从架构 前言 Redis是一个开源的内存数据结构存储系统&#xff0c;一般用于作为数据库、缓存和消息代理使用&#xff0c;而主从架构是许多分布式系统中常见的设计模式&#xff0c;用来提高系统的性能、可靠性和扩展性。 虚拟机使用的是自行创建的CentOS7&#xff0c;如…

自定义平台后台登录地址前缀的教程

修改平台后台地址默认的 admin 前缀 修改后端 config/admin.php 配置文件,为自定义的后缀 修改 平台后台前端源码中 src/settings.js 文件,修改为和上面一样的配置 修改后重新打包前端代码,并且覆盖到后端的 public 目录下 重启 swoole 服务即可

关于如何得到Mindspore lite所需要的.ms模型

关于如何得到Mindspore lite所需要的.ms模型 一、.ckpt模型文件转.mindir模型二、.mindir模型转.ms模型三、其它3.1 代码3.2 数据 四、参考文档 一、.ckpt模型文件转.mindir模型 由于要得到ms模型&#xff0c;mindspore的所有模型里面&#xff0c;是必须要用mindir模型才可以进…

计算机毕业设计Python深度学习房价预测 房价可视化 链家爬虫 房源爬虫 房源可视化 卷积神经网络 大数据毕业设计 机器学习 人工智能 AI

基于python一/二手房数据爬虫分析预测系统可视化 商品房数据Flask框架&#xff08;附源码&#xff09; 项目介绍python语言、Flask框架、MySQL数据库、Echarts可视化 sklearn机器学习 多元线性回归预测模型、requests爬虫框架 链家一手房 一手房数据商品房数据、分析可视化预测…