超棒的 AWS CDK - 第一部分 - 使用 AWS CDK 进行常见和实用部署的系列文章

简介


本系列文章将介绍如何使用 AWS CDK(云开发工具包)在 AWS 上进行常见且实用的云资源部署。本系列文章旨在帮助那些已经熟悉 AWS 的用户使用 AWS 提供的这个强大的 IaC(基础设施即代码)库来部署云资源。

您可能已经想到,AWS CDK 仅针对 AWS 云基础设施的部署。因此,如果您担心云部署会受到 AWS 供应商锁定,那么本系列文章可能不适合您。还有其他工具可以进行多供应商云部署和配置(例如 Terraform、Pulumi 和 Serverless)。

但是,如果您觉得自己像许多 DevOps/解决方案架构师/开发人员一样经常使用 AWS,那么本系列文章将向您展示使用 AWS CDK 部署资源的实用示例。

背景
 

您可以使用控制台、命令行界面或其他 IaC 工具在 AWS 上手动创建资源。这正是 AWS 刚出现时人们所做的。但很快,人们就发现,这种配置云基础设施的模式容易出错且不可持续,尤其对于海量复杂的资源堆栈而言。这些挫败感促成了 Cloudformation 于 2011 年的诞生。

Cloudformation


AWS Cloudformation 是 AWS 提供的托管服务,用于配置云基础设施和服务。您可以使用 JSON 或 YAML 模板文件来执行此操作,该文件定义了您希望 AWS 创建、更新或销毁哪些资源。Cloudformation 会使用该文件并对您已部署的资源堆栈进行必要的更改。

Cloudformation 是 AWS 上自动部署资源的骨干服务。它确保已部署资源的一致性,并可以跟踪资源的漂移(在 Cloudformation 模板文件之外创建、更新或销毁资源时)。

问题在于,Cloudformation 模板文件的编写、读取、更新和管理极其困难。毕竟,它们只是基本的 YAML/JSON 文件。如果您只配置少量资源,这还好。但一旦资源超过 20 个,就完全无法依靠人力进行管理。

这就是 CDK 的用武之地。

云开发工具包


AWS CDK 是一个函数库,它可以生成 Cloudformation 模板,并使用它配置 AWS 中的资源。它允许您使用自己喜欢的语言编写代码来定义这些 Cloudformation 模板。

使用 CDK,您可以从代码编辑器访问智能感知,将资源分解为逻辑部分,进行类型检查、枚举等,这意味着配置资源时出错的可能性大大降低。您还可以为要部署的基础设施编写测试,以确保在 IaC 中所做的任何更改都不会破坏您已部署的资源堆栈,也不会在您错误地超出能力范围配置时造成数百万美元的损失。

过去一年使用 CDK 对我来说非常愉快,很难再回到其他用于 AWS 资源配置的解决方案,例如 Terraform、Serverless 和 SAM。

但事情并非总是一帆风顺


没有一个项目是完美的。 AWS CDK 虽然很棒,但它也是一个近期项目(于 2019 年 7 月启动),因此它尚未涵盖在 AWS 上部署的所有可能功能(即使是 Cloudformation 也尚未涵盖 AWS 上的所有可能功能)。有些功能需要通过控制台或命令行界面手动配置。由于 CDK 的开发正在努力跟上 AWS 发布新服务和更新的步伐,因此也存在一些小错误、快速变化的接口、弃用等问题。也许一年之内,本系列中的许多代码示例都会被弃用。但核心 API 和概念将保持不变。此外,对于大多数常见服务,CDK 都能满足您的需求。

如何安装 AWS CDK

先决条件
您将需要:

  • 一个具有编程访问权限的 AWS 账户
  • Node.js

设置

  • 确保您已设置 Node.js
  • 确保您的 AWS 凭证已正确配置。


以下是我的 AWS 配置访问文件示例,

AWS 凭证文件:

# Linux 和 MacOS:~/.aws/credentials
# Windows:%USERPROFILE%\.aws\credentials

[默认]
aws_access_key_id=xXXxxxxXXXXxxxxxxx
aws_secret_access_key=xxXXXXxxxXXxXxx

AWS 配置文件:

# Linux 和 MacOS:~/.aws/config
# Windows:%USERPROFILE%\.aws\config

[默认]
region=us-west-2
output=json


AWS CDK 在需要访问部署资源所需的 AWS 账户时,会查找这些文件。
部署资源时,使用的 IAM 凭证具有管理员权限会很有帮助,因为这会减少很多与权限相关的麻烦。
如果您对 AWS IAM 以及部署的权限需求有深入的了解,可以筛选掉一些权限和特权。
在任意文件夹中全局安装 AWS CDK(以便您可以使用您选择的语言引导启动新的 CDK 项目)。

npm install -g aws-cdk


检查是否已安装

cdk --version
ninjamac@ip-192-168-1-2 aws % npm install -g aws-cdk

added 1 package in 5s
npm notice
npm notice New major version of npm available! 10.9.2 -> 11.3.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.3.0
npm notice To update run: npm install -g npm@11.3.0
npm notice
ninjamac@ip-192-168-1-2 aws % cdk --version
2.1010.0 (build 6b421db)

引导新的 CDK 应用程序


使用您的终端,创建一个新的目录 simple-ec2 并进入该目录:

mkdir app && cd app
ninjamac@ip-192-168-1-2 simple-ec2 % cdk init --language=typescript
Applying project template app for typescript
# Welcome to your CDK TypeScript project

This is a blank project for CDK development with TypeScript.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

## Useful commands

* `npm run build`   compile typescript to js
* `npm run watch`   watch for changes and compile
* `npm run test`    perform the jest unit tests
* `npx cdk deploy`  deploy this stack to your default AWS account/region
* `npx cdk diff`    compare deployed stack with current state
* `npx cdk synth`   emits the synthesized CloudFormation template

Initializing a new git repository...
Executing npm install...
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
✅ All done!

这将使用 Typescript 为您初始化一个新的 CDK 项目。

运行 npm update 以确保您使用的是最新版本的 CDK。

如果 @aws-cdk/core 与其他 @aws-cdk 子包之间存在版本冲突,那么您会遇到一些奇怪的错误。@aws-cdk/core 和所有其他导入的 @aws-cdk/PACKAGE 都应该具有相同的版本。

CDK 应用程序的结构和设置

ninjamac@ip-192-168-1-2 app % tree -I 'node_modules' 
.
├── README.md
├── bin
│   └── app.ts
├── cdk.json
├── cdk.out
│   ├── AppStack.assets.json
│   ├── AppStack.template.json
│   ├── asset.7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200
│   │   ├── __entrypoint__.js
│   │   └── index.js
│   ├── cdk.out
│   ├── manifest.json
│   └── tree.json
├── jest.config.js
├── lib
│   └── app-stack.ts
├── package-lock.json
├── package.json
├── test
│   └── app.test.ts
└── tsconfig.json

6 directories, 16 files
  •  /bin/app.ts 是 CDK 使用的入口文件。您可以在此处定义堆栈。
  • 用于配置资源的 IaC 将位于 lib 文件夹中,并且在 synth 和 deploy 操作期间,./bin/app.ts 需要它。我稍后会解释这两个命令。
  • ./test/app.test.ts 包含用于测试 CDK 应用程序的模板代码

设置


在 ./bin/app.ts 中,定义了一个 new App() ,它代表一个单一堆栈。

我们可以在此文件中为我们的堆栈添加描述。

// ./bin/app.ts
#!/usr/bin/env node

import * as cdk from 'aws-cdk-lib';
import { AppStack } from '../lib/app-stack';

const app = new cdk.App();

new AppStack(app, 'AppStack');

lib/app-stack.ts

// ./lib/app-stack.ts

import * as cdk from '@aws-cdk/core';

export class appStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
  }
}

如您所见,cdk init 命令为我们快速构建了一个良好的模板,让我们能够快速编写 IaC。基类 cdk.Stack 使我们能够创建新的 Cloudformation 堆栈。

我们还需要创建一个 .env 文件来保存我们的 AWS 账号和我们将要使用的区域。在项目的根目录中创建一个名为 .env 的文件,并添加以下内容。将 xxXxXxxXXxXxx 替换为您的 AWS 账号,并使用您想要的区域。

AWS_ACCOUNT_NUMBER=654654314383
AWS_ACCOUNT_REGION=ap-southeast-2

 写基础结构代码

bin/app.ts

#!/usr/bin/env node

import * as cdk from 'aws-cdk-lib';
import { AppStack } from '../lib/app-stack';

const app = new cdk.App();

new AppStack(app, 'AppStack');

lib/app-stack.ts 

import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_iam as iam } from 'aws-cdk-lib';
import { aws_ec2 as ec2 } from 'aws-cdk-lib';
import { readFileSync } from 'fs';

require('dotenv').config()

const config = {
  env: {
    account: process.env.AWS_ACCOUNT_NUMBER,
    region: process.env.AWS_REGION
  }
}

// Defining the CDK stack class that extends the Stack class
export class AppStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, { ...props, env: config.env }); // Calling the constructor of the parent class (Stack)

    // Creating a new VPC (Virtual Private Cloud)
    const vpc = new ec2.Vpc(this, 'VPC');   

    // Importing an IAM Role from its Amazon Resource Name (ARN)
    const role = new iam.Role(
      this,
      'simple-instance-1-role', // this is a unique id that will represent this resource in a Cloudformation template
      { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') }
    )

    const instance = new ec2.Instance(
      this,
      "myEc2App",
      {
          instanceType: ec2.InstanceType.of(
              ec2.InstanceClass.T2,
              ec2.InstanceSize.MEDIUM
          ),
//***** We are using Windows AMI, we can login via RDP if SG has 3389 port enabled *****
          machineImage: ec2.MachineImage.latestWindows(
              ec2.WindowsVersion.WINDOWS_SERVER_2022_ENGLISH_FULL_BASE
          ),
          keyName: 'windows',  //utilizing existing one [created one via console]
          role: role,
          vpc: vpc
      }
  );
  }
}

部署


记住,我们在第二部分中在 ~/.aws/config 和 ~/.aws/credentials 中设置了 AWS 配置文件和凭证。

我将部署到我的默认配置文件,该配置文件链接到我的个人 AWS 账户,区域为 ap-southeast-2。

# bootstap CDK 
cdk bootstrap

#观察有没有变化
cdk diff

# 合成 AWS CloudFormation 模板,无需部署
cdk synth

# 部署
cdk deploy

#销毁

cdk destroy
ninjamac@ip-192-168-1-2 app % cdk bootstrap
[WARNING] aws-cdk-lib.aws_ec2.InstanceProps#keyName is deprecated.
  - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
  This API will be removed in the next major release.
 ⏳  Bootstrapping environment aws://654654314383/ap-southeast-2...
Trusted accounts for deployment: (none)
Trusted accounts for lookup: (none)
Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize.
CDKToolkit: creating CloudFormation changeset...
 ✅  Environment aws://654654314383/ap-southeast-2 bootstrapped.
ninjamac@ip-192-168-1-2 app % cdk diff                 
[WARNING] aws-cdk-lib.aws_ec2.InstanceProps#keyName is deprecated.
  - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
  This API will be removed in the next major release.
start: Building AppStack Template
success: Built AppStack Template
start: Publishing AppStack Template (654654314383-current_region)
success: Published AppStack Template (654654314383-current_region)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Could not create a change set, will base the diff on template differences (run again with -v to see the reason)

Stack AppStack
IAM Statement Changes
┌───┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬───────────────────────────────────┬────────────────────────────────────────────────────────────────┬───────────┐
│   │ Resource                                                                                                      │ Effect │ Action                            │ Principal                                                      │ Condition │
├───┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼───────────────────────────────────┼────────────────────────────────────────────────────────────────┼───────────┤
│ - │ arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:security-group/${VPCB9E5F0B4.DefaultSecurityGroup} │ Allow  │ ec2:AuthorizeSecurityGroupEgress  │ AWS:${Custom::VpcRestrictDefaultSGCustomResourceProvider/Role} │           │
│   │                                                                                                               │        │ ec2:AuthorizeSecurityGroupIngress │                                                                │           │
│   │                                                                                                               │        │ ec2:RevokeSecurityGroupEgress     │                                                                │           │
│   │                                                                                                               │        │ ec2:RevokeSecurityGroupIngress    │                                                                │           │
├───┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼───────────────────────────────────┼────────────────────────────────────────────────────────────────┼───────────┤
│ + │ arn:${AWS::Partition}:ec2:${AWS::Region}:654654314383:security-group/${VPC.DefaultSecurityGroup}              │ Allow  │ ec2:AuthorizeSecurityGroupEgress  │ AWS:${Custom::VpcRestrictDefaultSGCustomResourceProvider/Role} │           │
│   │                                                                                                               │        │ ec2:AuthorizeSecurityGroupIngress │                                                                │           │
│   │                                                                                                               │        │ ec2:RevokeSecurityGroupEgress     │                                                                │           │
│   │                                                                                                               │        │ ec2:RevokeSecurityGroupIngress    │                                                                │           │
└───┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴───────────────────────────────────┴────────────────────────────────────────────────────────────────┴───────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Resources
[~] Custom::VpcRestrictDefaultSG VPC/RestrictDefaultSecurityGroupCustomResource VPCRestrictDefaultSecurityGroupCustomResource59474679
 └─ [~] Account
     └─ @@ -1,3 +1,1 @@
        [-] {
        [-]   "Ref": "AWS::AccountId"
        [-] }
        [+] "654654314383"
[~] AWS::IAM::Role Custom::VpcRestrictDefaultSGCustomResourceProvider/Role CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0
 └─ [~] Policies
     └─ @@ -25,12 +25,8 @@
        [ ] {
        [ ]   "Ref": "AWS::Region"
        [ ] },
        [-] ":",
        [+] ":654654314383:security-group/",
        [ ] {
        [-]   "Ref": "AWS::AccountId"
        [-] },
        [-] ":security-group/",
        [-] {
        [ ]   "Fn::GetAtt": [
        [ ]     "VPCB9E5F0B4",
        [ ]     "DefaultSecurityGroup"
[~] AWS::Lambda::Function Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E
 └─ [~] Code
     └─ [~] .S3Bucket:
         └─ [~] .Fn::Sub:
             ├─ [-] cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}
             └─ [+] cdk-hnb659fds-assets-654654314383-${AWS::Region}
[~] AWS::EC2::Instance myEc2App myEc2App51DF0DDD replace
 └─ [~] KeyName (requires replacement)
     ├─ [-] rockaws
     └─ [+] windows



✨  Number of stacks with differences: 1
ninjamac@ip-192-168-1-2 app % cdk synth
[WARNING] aws-cdk-lib.aws_ec2.InstanceProps#keyName is deprecated.
  - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
  This API will be removed in the next major release.
Resources:
  VPCB9E5F0B4:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: AppStack/VPC
    Metadata:
      aws:cdk:path: AppStack/VPC/Resource

 

ninjamac@ip-192-168-1-2 app % cdk deploy
[WARNING] aws-cdk-lib.aws_ec2.InstanceProps#keyName is deprecated.
  - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair
  This API will be removed in the next major release.

✨  Synthesis time: 5.39s

This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

Stack AppStack
IAM Statement Changes
┌───┬──────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬───────────────────────────────────┬────────────────────────────────────────────────────────────────┬───────────┐
│   │ Resource                                                                                         │ Effect │ Action                            │ Principal                                                      │ Condition │
├───┼──────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼───────────────────────────────────┼────────────────────────────────────────────────────────────────┼───────────┤
│ + │ ${Custom::VpcRestrictDefaultSGCustomResourceProvider/Role.Arn}                                   │ Allow  │ sts:AssumeRole                    │ Service:lambda.amazonaws.com                                   │           │
├───┼──────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼───────────────────────────────────┼────────────────────────────────────────────────────────────────┼───────────┤
│ + │ ${simple-instance-1-role.Arn}                                                                    │ Allow  │ sts:AssumeRole                    │ Service:ec2.amazonaws.com                                      │           │
├───┼──────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼───────────────────────────────────┼────────────────────────────────────────────────────────────────┼───────────┤
│ + │ arn:${AWS::Partition}:ec2:${AWS::Region}:654654314383:security-group/${VPC.DefaultSecurityGroup} │ Allow  │ ec2:AuthorizeSecurityGroupEgress  │ AWS:${Custom::VpcRestrictDefaultSGCustomResourceProvider/Role} │           │
│   │                                                                                                  │        │ ec2:AuthorizeSecurityGroupIngress │                                                                │           │
│   │                                                                                                  │        │ ec2:RevokeSecurityGroupEgress     │                                                                │           │
│   │                                                                                                  │        │ ec2:RevokeSecurityGroupIngress    │                                                                │           │
└───┴──────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴───────────────────────────────────┴────────────────────────────────────────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                                                   │ Managed Policy ARN                                                                           │
├───┼────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${Custom::VpcRestrictDefaultSGCustomResourceProvider/Role} │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"} │
└───┴────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────┘
Security Group Changes
┌───┬───────────────────────────────────────────┬─────┬────────────┬─────────────────┐
│   │ Group                                     │ Dir │ Protocol   │ Peer            │
├───┼───────────────────────────────────────────┼─────┼────────────┼─────────────────┤
│ + │ ${myEc2App/InstanceSecurityGroup.GroupId} │ Out │ Everything │ Everyone (IPv4) │
└───┴───────────────────────────────────────────┴─────┴────────────┴─────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)


Do you wish to deploy these changes (y/n)? y
AppStack: deploying... [1/1]
AppStack: creating CloudFormation changeset...
AppStack: creating CloudFormation changeset...

 ✅  AppStack

✨  Deployment time: 186.83s

Stack ARN:
arn:aws:cloudformation:ap-southeast-2:654654314383:stack/AppStack/c1acb320-203d-11f0-9b14-0254438cd5a3

✨  Total time: 192.22s

登录aws console 验证

 

 销毁资源

ninjamac@ip-192-168-1-2 app % cdk destroy

结论

AWS CDK 让编写 IaC、配置、部署、更新和销毁基础设施变得非常轻松。您可以编写测试来确保部署正确。

这是一个简单的示例,部署一个 EC2 实例似乎需要花费不少功夫。但是,随着我们学习本系列的深入,您将意识到它对复杂的基础设施有多么有益。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云攀登者-望正茂

你的鼓励是我前进的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值