zl程序教程

您现在的位置是:首页 >  其他

当前栏目

aws cdk 使用 cdktf 将 cdk 和 terraform 结合创建和部署资源

2023-04-18 16:49:10 时间

之前的很多文章已经介绍过如何使用cdk,并通过javascript项目推送ecr仓库,创建eks‘和ecs集群等。但是cdktf并不支持javascript,typescript又实在不想接触,于是选择python项目来比较两者。

cdk 项目结构和部署(python)

cdk是aws提供的iac工具,通过渲染cloudformation模板进行资源的创建和部署,不赘述了。

创建python的cdk项目

cdk init --language python

初始化项目时会自动创建python的venv,直接安装依赖

source .venv/bin/activate
pip install -r requirements.txt

最终的项目结构如下

$ tree aws-cdk-python
aws-cdk-python
├── app.py
├── aws_cdk_python
│   ├── aws_cdk_python_stack.py
│   └── __init__.py
├── cdk.json
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── source.bat
└── tests
    ├── __init__.py
    └── unit
        ├── __init__.py
        └── test_aws_cdk_python_stack.py

创建ec2实例的简单堆栈

import aws_cdk as cdk
from aws_cdk import (
    Stack,
    aws_ec2 as ec2,
    aws_iam as iam,
)
from constructs import Construct

app = cdk.App()

class AwsCdkPythonStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        
        vpc = ec2.Vpc.from_lookup(self, "myvpc", vpc_id="vpc-086d798b56f59e2ae",)
        
        amzn_linux = ec2.MachineImage.latest_amazon_linux(
            generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
            edition=ec2.AmazonLinuxEdition.STANDARD,
            virtualization=ec2.AmazonLinuxVirt.HVM,
            storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
            )
        
        role = iam.Role(self, "InstanceSSM", assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"))
        role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSSMManagedInstanceCore"))
        instance = ec2.Instance(self, "Instance",
            instance_type=ec2.InstanceType("t3.small"),
            machine_image=amzn_linux,
            vpc = vpc,
            role = role,
            instance_name = "testcdk",
            vpc_subnets = ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PUBLIC
                )      
            )
        
AwsCdkPythonStack(app, "AwsCdkPythonStack",
    env=cdk.Environment(account=os.getenv('CDK_DEFAULT_ACCOUNT'), region=os.getenv('CDK_DEFAULT_REGION')),
    )

app.synth()

部署资源

cdk deploy

发现了有趣的一点,控制台的资源显示方式出现了树状视图?经过查询在2022年9月14日aws发布了cdk树状构建视图,为啥只有cdk支持,并且没有资源直链了,不是很理解怎么设计的。。。

AWS 云开发工具包 (CDK) 宣布推出 AWS CloudFormation 控制台中的 CDK 构件树视图

在这里插入图片描述

生成的cfn模板

Resources:
  InstanceSSMCBFA3CF0:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: ec2.amazonaws.com.cn
        Version: "2012-10-17"
      ManagedPolicyArns:
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/AmazonSSMManagedInstanceCore
    Metadata:
      aws:cdk:path: AwsCdkPythonStack/InstanceSSM/Resource
  InstanceInstanceSecurityGroupF0E2D5BE:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: AwsCdkPythonStack/Instance/InstanceSecurityGroup
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          Description: Allow all outbound traffic by default
          IpProtocol: "-1"
      Tags:
        - Key: Name
          Value: testcdk
      VpcId: vpc-086d798b56f59e2ae
    Metadata:
      aws:cdk:path: AwsCdkPythonStack/Instance/InstanceSecurityGroup/Resource
  InstanceInstanceProfileAB5AEF02:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - Ref: InstanceSSMCBFA3CF0
    Metadata:
      aws:cdk:path: AwsCdkPythonStack/Instance/InstanceProfile
  InstanceC1063A87:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: cn-north-1a
      IamInstanceProfile:
        Ref: InstanceInstanceProfileAB5AEF02
      ImageId:
        Ref: SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter
      InstanceType: t3.small
      SecurityGroupIds:
        - Fn::GetAtt:
            - InstanceInstanceSecurityGroupF0E2D5BE
            - GroupId
      SubnetId: subnet-0d5dfa09abe8480d1
      Tags:
        - Key: Name
          Value: testcdk
      UserData:
        Fn::Base64: "#!/bin/bash"
    DependsOn:
      - InstanceSSMCBFA3CF0

还有两个简单的示例项目

cdktf 项目结构和部署(python)

terraform使用起来虽然相比cloudformation较为简单,但是需要学习一种新的语法,即HashiCorp 配置语言(HCL)。aws 和 hashicopr合作发布了CDKTF,可以将terraform和cdk集成通过cdk来编写terraform配置

terraform platform

cdk for terraform包括两个包

  • cdktf-cli” - A CLI that allows users to run commands to initialize, import, and synthesize CDK for Terraform applications.
  • cdktf” - A library for defining Terraform resources using programming constructs.

先决条件

安装cdktf工具

npm install -g cdktf-cli

创建项目(python),需要提前安装pipenv

cdktf init
cdktf init --template=python --local

pipenv会创建python虚拟环境。在项目目录下生成2个文件PipfilePipfile.lock代替原来的 requirement.txt,通过shell可以查看虚拟环境创建的路径

$ pipenv --venv  
/home/ec2-user/.local/share/virtualenvs/aws-cdktf-XFznh62X

pipenv常用命令

pipenv --where                 列出本地工程路径
pipenv --venv                  列出虚拟环境路径
pipenv --py                    列出虚拟环境的Python可执行文件
pipenv install                 创建虚拟环境
pipenv isntall [moduel]        安装包
pipenv install [moduel] --dev  安装包到开发环境
pipenv uninstall[module]       卸载包
pipenv uninstall --all         卸载所有包
pipenv graph                   查看包依赖
pipenv lock                    生成lockfile
pipenv run python [pyfile]     运行py文件
pipenv --rm                    删除虚拟环境

按需添加providers

pipenv install cdktf-cdktf-provider-aws
pipenv install cdktf-cdktf-provider-google
pipenv install cdktf-cdktf-provider-azurerm
pipenv install cdktf-cdktf-provider-docker
pipenv install cdktf-cdktf-provider-github
pipenv install cdktf-cdktf-provider-null

项目结构

$ tree aws-cdktf
aws-cdktf
├── cdktf.json
├── help
├── main.py
├── main-test.py
├── Pipfile
└── Pipfile.lock

按照官方的文档创建简单的示例项目,和原生的cdk项目一摸一样的用法,几乎没有迁移学习成本。

此外,由于使用pipenv导致vscode中没有代码提示,只需要将python解释器切换到pipenv的解释器即可。

https://developer.hashicorp.com/terraform/cdktf

#!/usr/bin/env python
from constructs import Construct
from cdktf import App, TerraformStack, TerraformOutput
from cdktf_cdktf_provider_aws.provider import AwsProvider
from cdktf_cdktf_provider_aws.instance import Instance


class MyStack(TerraformStack):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, id)
        
        AwsProvider(self, "aws",
            region = "cn-north-1",
            profile= "admin"
        )

        instance = Instance(self, "Hello",
            ami = "ami-0a20a235e8c07b393",
            instance_type = "t3.small"
        )
        
        TerraformOutput(self, "public_ip",
                        value=instance.public_ip,
                        )

app = App()
MyStack(app, "aws-cdktf")

app.synth()

发布部署,注意不能在pipenv的虚拟环境中执行

cdktf synth
cdktf deploy

生成的terraform模板

{
  "//": {
    "metadata": {
      "backend": "local",
      "stackName": "aws-cdktf",
      "version": "0.14.3"
    },
    "outputs": {
      "aws-cdktf": {
        "public_ip": "public_ip"
      }
    }
  },
  "output": {
    "public_ip": {
      "value": "${aws_instance.Hello.public_ip}"
    }
  },
  "provider": {
    "aws": [
      {
        "region": "cn-north-1"
      }
    ]
  },
  "resource": {
    "aws_instance": {
      "Hello": {
        "//": {
          "metadata": {
            "path": "aws-cdktf/Hello",
            "uniqueId": "Hello"
          }
        },
        "ami": "ami-0a20a235e8c07b393",
        "instance_type": "t3.small"
      }
    }
  },
  "terraform": {
    "backend": {
      "local": {
        "path": "xxx/aws-cdktf/terraform.aws-cdktf.tfstate"
      }
    },
    "required_providers": {
      "aws": {
        "source": "aws",
        "version": "4.48.0"
      }
    }
  }
}

貌似没有找到完整的cdktf api参考,那我创建资源的具体参数要靠猜的?之后找到在补上

cdktf最终还是通过terraform的api部署资源,查看terraform的provider和module。因此仍然可能由于网络原因下载失败的问题,要么手动离线安装,要么配个代理下载

$ tree -a 
cdktf.out
├── manifest.json
└── stacks
    └── aws-cdktf
        ├── cdk.tf.json
        ├── plan
        ├── .terraform
        │   ├── providers
        │   │   └── registry.terraform.io
        │   │       └── hashicorp
        │   │           └── aws
        │   │               └── 4.48.0
        │   │                   └── linux_amd64 -> /home/ec2-user/.terraform.d/plugin-cache/registry.terraform.io/hashicorp/aws/4.48.0/linux_amd64
        │   └── terraform.tfstate
        └── .terraform.lock.hcl