如何识别 aws cdk 应用程序何时在部署状态下运行?
Posted
技术标签:
【中文标题】如何识别 aws cdk 应用程序何时在部署状态下运行?【英文标题】:How can I identify when the aws cdk app is running in the deployment state? 【发布时间】:2021-10-13 21:14:39 【问题描述】:我有以下问题:
我创建了一个堆栈,在创建资源后(特别是带有 Amazon MQ 的 rabbitmq 代理)我想配置一些不能用 cdk 完成的东西,而必须通过 REST api 调用来完成。
问题是我只想在代理启动并运行并且rabbitmq_url被解析后仅在部署状态下进行其余的api调用。
我有类似以下的东西,但没有按预期工作:
# Doc Ref: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amazonmq-broker.html
rabbitmq_broker = amazonmq. \
CfnBroker(self, "RabbitMQBroker",
broker_name=f"os.getenv('ENVIRONMENT_NAME')-rabbitmq",
engine_type="RABBITMQ",
engine_version="3.8.17",
deployment_mode="SINGLE_INSTANCE",
host_instance_type="mq.t3.micro",
subnet_ids=[[public_subnet.subnet_id for public_subnet in vpc.public_subnets][0]],
logs=amazonmq.CfnBroker.LogListProperty(general=True),
# This means we can access rabbitmq from internet without going into the VPC
publicly_accessible=True,
users=[amazonmq.CfnBroker.UserProperty(username=os.getenv('RABBITMQ_USER'),
password=os.getenv('RABBITMQ_PASSWORD'))],
auto_minor_version_upgrade=True)
rabbitmq_url = f"rabbitmq_broker.ref.mq.os.getenv('CDK_DEFAULT_REGION').amazonaws.com"
...
# Only executed when the token is resolved in the deploy stage
if not core.Token.is_unresolved(rabbitmq_broker.ref):
# Create virtual host 'kmhbackend' via RabbitMQ Management HTTP API
response = requests.post(f"https://rabbitmq_url:15671/api/vhosts/kmhbackend",
auth=(os.getenv('RABBITMQ_USER'), os.getenv('RABBITMQ_PASSWORD')),
headers='content-type': 'application/json')
if response.status_code != requests.codes.get('created'):
Log.error("Warning: The virtual host has not been created")
print("Warning: The virtual host has not been created")
如何识别 cdk 应用何时在部署状态下运行?
我不想只使用上下文变量来识别它。
提前致谢
【问题讨论】:
你可以一直等待你的堆栈完成它的整个部署,然后执行 API 调用? @DebdutGoswami,你是什么意思等待整个部署完成,先执行 cdk deploy 然后执行一些其他脚本来配置剩下的东西?这样会有点松散 Iac 的感觉,因为我需要在每次部署后手动执行或创建一个 lambda 来监听事件,但这样做会有点痛苦 你是绝对正确的,但我只是提出了一种解决方法,因为我无法在 cdk 文档中找到任何类似的东西。也许我只是在寻找错误的关键字。您可以改为在他们的 github 存储库中提出功能请求。 【参考方案1】:所以深入阅读文档后,解决方案是在新的嵌套堆栈中创建自定义资源,并在2个堆栈之间添加依赖关系,这样自定义资源将等待初始资源完全部署。
所以解决办法是这样的:
class MessageBrokerConfigStack(core.NestedStack):
"""
This stack will take of configure rabbitmq once it's created by API calls
* the RabbitMQ Management HTTP API at 'rabbitmq-web-console:15671' ,
docs of API can be found in rabbitmq_url/api/index.html
Warning: In the docs the port used for the RabbitMQ Management HTTP API is 15672,
but with AWS the port to be used is 15671
"""
def __init__(self, scope: core.Construct, id: str,
vpc: ec2.Vpc, rabbit_broker_url: str,
rabbitmq_user: str, rabbitmq_password: str,
**kwargs) -> None:
super().__init__(scope, id, **kwargs)
...
onEvent = lambda_. \
Function(self, "CR_RabbitMQ_configurator_handler",
function_name="cr_cdk_rabbitmq_configurator_handler",
description="Function that will handle all the configuration for rabbitmq broker created by cdk",
runtime=lambda_.Runtime.PYTHON_3_7,
layers=[layer],
handler="config_rabbitmq.lambda_handler",
code=lambda_.Code.from_asset('aws_lambda/lambdas')
)
config_rabbitmq_provider = cr.Provider(self, 'CR_RabbitMQ_configurator_provider',
vpc=vpc,
vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
on_event_handler=onEvent)
# Will create a custom resource in cloudformation, this custom resource is compose by a lambda that
# will contain a function and this function will handle the different events
# ref https://docs.aws.amazon.com/cdk/latest/guide/apps.html#lifecycle
# ref https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_custom
config_rabbitmq = core.CustomResource(self, 'CR_RabbitMQ_configurator',
service_token=config_rabbitmq_provider.service_token,
properties=
"rabbitmq_url": rabbit_broker_url,
"rabbit_user": rabbitmq_user,
"rabbit_password": rabbitmq_password
)
然后 lambda 代码将侦听事件并执行所需的操作。
import requests
def lambda_handler(event, context):
"""
This method is the native input for AWS Lambda
"""
print("lambda rabbitmq received")
print(event)
print(context)
props = event['ResourceProperties']
rabbitmq_url = props['rabbitmq_url']
rabbit_user = props['rabbit_user']
rabbit_password = props['rabbit_password']
print(rabbitmq_url)
print(rabbit_user)
print(rabbit_password)
if event["RequestType"] == "Create":
# ref https://docs.aws.amazon.com/cdk/latest/guide/apps.html#lifecycle
# ref https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_custom
# Only executed when the token is resolved in the deploy stage
# Create virtual host 'kmhbackend' via RabbitMQ Management HTTP API
response = requests.put(f"https://rabbitmq_url:15671/api/vhosts/new_virtual_host",
auth=(rabbit_user, rabbit_password),
headers='content-type': 'application/json')
print("response from rabbitmq:")
print(response)
if response.status_code != requests.codes.get('created'):
print("Warning: The virtual host has not been created")
然后在父栈上我们只需要做
resource = Resource(....)
configResource = ConfigResouce(...)
configResource.add_dependency(resource)
【讨论】:
以上是关于如何识别 aws cdk 应用程序何时在部署状态下运行?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 aws-cdk 从 AWS Secrets Manager 导入 EKS 密钥?
如何在部署前从@aws-cdk/aws-appsync 检索 schema.graphql 文件