Bỏ qua để đến nội dung

Cơ sở hạ tầng CDK

AWS CDK là một framework để định nghĩa cơ sở hạ tầng đám mây bằng code và triển khai nó thông qua AWS CloudFormation.

Trình tạo cơ sở hạ tầng TypeScript tạo ra một ứng dụng cơ sở hạ tầng AWS CDK được viết bằng TypeScript. Ứng dụng được tạo ra bao gồm các phương pháp bảo mật tốt nhất thông qua kiểm tra bảo mật Checkov.

Bạn có thể tạo một dự án cơ sở hạ tầng mới theo hai cách:

  1. Install the Nx Console VSCode Plugin if you haven't already
  2. Open the Nx Console in VSCode
  3. Click Generate (UI) in the "Common Nx Commands" section
  4. Search for @aws/nx-plugin - ts#infra
  5. Fill in the required parameters
    • Click Generate
    Parameter Type Default Description
    name Required string - The name of the application.
    directory string packages The directory of the new application.
    enableStageConfig boolean Enable centralized stage configuration (credentials, account, region) for multi-environment CDK deployments.

    Trình tạo sẽ tạo cấu trúc dự án sau trong thư mục <directory>/<name>:

    • Thư mụcsrc
      • main.ts Điểm khởi đầu ứng dụng khởi tạo các CDK stage để triển khai
      • Thư mụcstages Định nghĩa CDK Stage
        • application-stage.ts Định nghĩa một tập hợp các stack để triển khai trong một stage
      • Thư mụcstacks Định nghĩa CDK Stack
        • application-stack.ts Stack ứng dụng chính
    • cdk.json Cấu hình CDK
    • project.json Cấu hình dự án và các target build
    • checkov.yml Tệp cấu hình Checkov

    Nếu bạn đặt tùy chọn enableStageConfig, trình tạo cũng tạo hai package được chia sẻ để quản lý thông tin xác thực tập trung (nếu chúng chưa tồn tại):

    • Thư mụcpackages/common
      • Thư mụcinfra-config Các loại cấu hình Stage và ánh xạ thông tin xác thực
        • Thư mụcsrc
          • stages.types.ts Định nghĩa kiểu cho thông tin xác thực và cấu hình stage
          • stages.config.ts Ánh xạ stage-to-credential của bạn (chỉnh sửa tệp này)
          • index.ts Re-exports để import từ các package khác
      • Thư mụcscripts Các script deploy/destroy tập trung
        • Thư mụcsrc
          • infra-deploy.ts Script bin deploy
          • infra-destroy.ts Script bin destroy
          • Thư mụcstage-credentials/ Logic được chia sẻ (tra cứu thông tin xác thực, xây dựng lệnh CDK)

    Bạn có thể bắt đầu viết cơ sở hạ tầng CDK của mình bên trong src/stacks/application-stack.ts, ví dụ:

    src/stacks/application-stack.ts
    import { Stack, StackProps } from 'aws-cdk-lib';
    import { Bucket } from 'aws-cdk-lib/aws-s3'
    import { Construct } from 'constructs';
    export class ApplicationStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    // Khai báo cơ sở hạ tầng của bạn ở đây
    new Bucket(this, 'MyBucket');
    }
    }

    CDK sử dụng Stages để nhóm các stack nên được triển khai cùng nhau đến một môi trường cụ thể. Tệp src/main.ts được tạo ra sẽ tạo một stage sandbox cho việc phát triển và thử nghiệm của riêng bạn:

    src/main.ts
    new ApplicationStage(app, 'my-app-sandbox', {
    env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION,
    },
    });

    Thuộc tính env cho CDK biết tài khoản AWS và region nào để triển khai. CDK_DEFAULT_ACCOUNTCDK_DEFAULT_REGION được CDK CLI tự động phân giải từ thông tin xác thực AWS đang hoạt động của bạn. Xem tài liệu về môi trường CDK để biết thêm chi tiết.

    Nếu bạn tạo với enableStageConfig, tệp main.ts sẽ đọc account và region từ một tệp cấu hình tập trung thay vì vậy, và quay lại sử dụng biến môi trường khi không có cấu hình được đặt:

    src/main.ts (với enableStageConfig)
    import stagesConfig from ':my-scope/common-infra-config';
    const projectStages = stagesConfig.projects?.['packages/infra']?.stages ?? {};
    const sandboxConfig = projectStages['my-app-sandbox'];
    new ApplicationStage(app, 'my-app-sandbox', {
    env: {
    account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
    region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
    },
    });

    Bạn có thể thêm nhiều stage hơn để triển khai đến các môi trường khác nhau. Ví dụ, các stage betaprod nhắm đến các tài khoản AWS riêng biệt:

    src/main.ts
    new ApplicationStage(app, 'project-beta', {
    env: {
    account: '123456789012',
    region: 'us-west-2',
    },
    });
    new ApplicationStage(app, 'project-prod', {
    env: {
    account: '098765432109',
    region: 'us-west-2',
    },
    });

    Một Stage nhóm một hoặc nhiều stack. Bạn có thể thêm bao nhiêu stack tùy thích bên trong một stage:

    src/stages/application-stage.ts
    import { Stage, StageProps } from 'aws-cdk-lib';
    import { Construct } from 'constructs';
    import { BackendStack } from '../stacks/backend-stack.js';
    import { FrontendStack } from '../stacks/frontend-stack.js';
    export class ApplicationStage extends Stage {
    constructor(scope: Construct, id: string, props?: StageProps) {
    super(scope, id, props);
    new BackendStack(this, 'Backend', {
    crossRegionReferences: true,
    })
    new FrontendStack(this, 'Frontend', {
    crossRegionReferences: true,
    });
    }
    }

    Khi bạn có nhiều stage nhắm đến các tài khoản AWS khác nhau, việc quản lý thông tin xác thực thủ công có thể dễ xảy ra lỗi, đặc biệt khi số lượng stage tăng lên.

    Tùy chọn enableStageConfig giải quyết vấn đề này bằng cách tạo hai package được chia sẻ:

    • packages/common/infra-config — Một tệp cấu hình duy nhất, nơi bạn ánh xạ mỗi stage với thông tin xác thực AWS, account và region của nó. Tệp này có thể import từ bất kỳ package nào trong workspace của bạn, vì vậy tệp main.ts CDK của bạn có thể đọc account và region từ cùng một nguồn chân lý.
    • packages/common/scripts — Các lệnh infra-deployinfra-destroy bao bọc CDK với khả năng phân giải thông tin xác thực tự động. Khi bạn chạy deploy, script sẽ đọc cấu hình, đặt các biến môi trường AWS phù hợp cho tiến trình con CDK, và chạy cdk deploy. Môi trường shell của bạn không bao giờ bị thay đổi.

    Chỉnh sửa packages/common/infra-config/src/stages.config.ts để ánh xạ các stage của bạn với thông tin xác thực AWS:

    packages/common/infra-config/src/stages.config.ts
    import type { StagesConfig } from './stages.types.js';
    const config: StagesConfig = {
    projects: {
    // Key là đường dẫn dự án tương đối với workspace root.
    // Điều này khớp với đường dẫn trong project.json và trong các lệnh deploy.
    'packages/infra': {
    stages: {
    // Tên stage phải khớp với các định danh CDK stage trong main.ts
    // (tham số đầu tiên của `new ApplicationStage(app, 'my-app-dev', ...)`).
    'my-app-dev': {
    credentials: { type: 'profile', profile: 'dev-account' },
    region: 'us-east-1',
    },
    'my-app-prod': {
    credentials: {
    type: 'assumeRole',
    assumeRole: 'arn:aws:iam::123456789012:role/DeployRole',
    },
    region: 'us-west-2',
    account: '123456789012',
    },
    },
    },
    },
    shared: {
    // Các stage được chia sẻ có sẵn cho tất cả các dự án infra.
    // Các mục cụ thể của dự án được ưu tiên hơn các mục được chia sẻ.
    stages: {
    sandbox: {
    credentials: { type: 'profile', profile: 'personal-sandbox' },
    region: 'us-east-1',
    },
    },
    },
    };
    export default config;

    Khi bạn triển khai, ví dụ:

    Terminal window
    pnpm nx run infra:deploy my-app-dev/*

    Script deploy sẽ:

    1. Trích xuất tên stage my-app-dev từ các tham số lệnh
    2. Tra cứu thông tin xác thực trong cấu hình: đầu tiên trong projects['packages/infra'], sau đó trong shared
    3. Nếu tìm thấy, đặt AWS_PROFILE (hoặc assume IAM role) chỉ cho tiến trình con CDK
    4. Nếu không tìm thấy, quay lại sử dụng bất kỳ thông tin xác thực AWS nào có trong môi trường của bạn

    Điều này có nghĩa là các workflow hiện có không có bất kỳ cấu hình nào vẫn tiếp tục hoạt động — script chỉ áp dụng thông tin xác thực khi tìm thấy một mục khớp.

    Hai chiến lược thông tin xác thực được hỗ trợ:

    • profile — Sử dụng một AWS CLI profile được đặt tên từ ~/.aws/config. Script đặt AWS_PROFILE cho tiến trình CDK.
    • assumeRole — Gọi STS AssumeRole với ARN role được chỉ định và truyền thông tin xác thực tạm thời cho CDK. Bạn có thể tùy chọn chỉ định một profile làm thông tin xác thực nguồn cho lệnh gọi AssumeRole, một externalId cho các chính sách ủy thác cross-account, và một sessionDuration tính bằng giây.

    Mỗi cấu hình stage bao gồm một region bắt buộc và một account tùy chọn:

    • region (bắt buộc) — AWS region để triển khai (ví dụ: us-east-1, eu-west-2).
    • account (tùy chọn) — ID tài khoản AWS. Nếu bỏ qua, CDK sẽ suy ra nó từ thông tin xác thực đang hoạt động tại thời điểm triển khai. Xem tài liệu về môi trường CDK để biết cách CDK phân giải account và region.

    Tệp main.ts được tạo ra đọc các giá trị này từ cấu hình để quá trình tổng hợp và triển khai CDK sử dụng cùng các thiết lập môi trường:

    src/main.ts
    const sandboxConfig = projectStages['my-app-sandbox'];
    new ApplicationStage(app, 'my-app-sandbox', {
    env: {
    account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
    region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
    },
    });

    Stage được chia sẻ so với Stage cụ thể của dự án

    Phần tiêu đề “Stage được chia sẻ so với Stage cụ thể của dự án”

    Các stage được chia sẻ (trong shared.stages) áp dụng cho bất kỳ dự án infra nào trong workspace. Điều này hữu ích khi nhiều dự án triển khai đến cùng một tài khoản sandbox — bạn định nghĩa thông tin xác thực một lần thay vì lặp lại cho từng dự án.

    Các stage cụ thể của dự án (trong projects['packages/infra'].stages) chỉ áp dụng cho dự án đó. Khi cả hai tồn tại cho cùng một tên stage, mục cụ thể của dự án được ưu tiên.

    Nếu bạn đã sử dụng trình tạo tRPC API hoặc FastAPI để tạo API, bạn sẽ nhận thấy bạn đã có một số construct có sẵn trong packages/common/constructs để triển khai chúng.

    Ví dụ, nếu bạn đã tạo một tRPC API có tên là my-api, bạn chỉ cần import và khởi tạo construct để thêm tất cả cơ sở hạ tầng cần thiết để triển khai nó:

    src/stacks/application-stack.ts
    import { Stack, StackProps } from 'aws-cdk-lib';
    import { Construct } from 'constructs';
    import { MyApi } from ':my-scope/common-constructs';
    export class ApplicationStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    // Thêm cơ sở hạ tầng cho API của bạn
    new MyApi(this, 'MyApi', {
    integrations: MyApi.defaultIntegrations(this).build(),
    });
    }
    }

    Nếu bạn đã sử dụng trình tạo CloudScape website, bạn sẽ nhận thấy bạn đã có một construct trong packages/common/constructs để triển khai nó. Ví dụ:

    src/stacks/application-stack.ts
    import { Stack, StackProps } from 'aws-cdk-lib';
    import { Construct } from 'constructs';
    import { MyWebsite } from ':my-scope/common-constructs';
    export class ApplicationStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    // Thêm cơ sở hạ tầng cho website của bạn
    new MyWebsite(this, 'MyWebsite');
    }
    }

    Điều quan trọng là đảm bảo rằng website được khai báo sau bất kỳ construct API nào để Runtime Config của website bao gồm tất cả cấu hình API.

    Như một phần của target build, cũng như chạy các target compile, lint và test mặc định, dự án cơ sở hạ tầng của bạn được tổng hợp thành CloudFormation. Điều này cũng có thể được thực thi một cách độc lập, bằng cách chạy target synth:

    Terminal window
    pnpm nx run <my-infra>:synth

    Bạn sẽ tìm thấy cloud assembly đã tổng hợp của mình trong thư mục dist gốc, dưới dist/packages/<my-infra-project>/cdk.out.

    Một target checkov được thêm vào dự án của bạn để chạy kiểm tra bảo mật trên cơ sở hạ tầng của bạn bằng Checkov.

    Terminal window
    pnpm nx run <my-infra>:checkov

    Bạn sẽ tìm thấy kết quả kiểm tra bảo mật của mình trong thư mục dist gốc, dưới dist/packages/<my-infra-project>/checkov.

    Có thể có những trường hợp bạn muốn loại trừ một số quy tắc nhất định trên các tài nguyên. Bạn có thể làm điều này theo hai cách:

    Loại trừ một quy tắc trên một construct nhất định

    Phần tiêu đề “Loại trừ một quy tắc trên một construct nhất định”
    import { suppressRules } from ':my-scope/common-constructs';
    // loại trừ CKV_AWS_XXX cho construct đã cho.
    suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');

    Loại trừ một quy tắc trên một construct con cháu

    Phần tiêu đề “Loại trừ một quy tắc trên một construct con cháu”
    import { suppressRules } from ':my-scope/common-constructs';
    // Loại trừ CKV_AWS_XXX cho construct hoặc bất kỳ construct con cháu nào của nó nếu nó là một instance của Bucket
    suppressRules(construct, ['CKV_AWS_XXX'], 'Reason', (construct) => construct instanceof Bucket);

    Nếu bạn đang triển khai một ứng dụng CDK đến một tài khoản AWS lần đầu tiên, nó sẽ cần được bootstrap. Bootstrap tạo ra các tài nguyên mà CDK cần để quản lý các lần triển khai (một S3 bucket cho các assets, IAM roles, v.v.).

    Đầu tiên, đảm bảo rằng bạn đã cấu hình thông tin xác thực cho tài khoản AWS của mình.

    Tiếp theo, chạy lệnh bootstrap cho mỗi account và region bạn định triển khai:

    Terminal window
    npx cdk bootstrap aws://<account-id>/<region>

    Để biết thêm chi tiết, vui lòng tham khảo tài liệu bootstrapping CDK.

    Sau khi build, bạn có thể triển khai cơ sở hạ tầng của mình lên AWS bằng target deploy.

    Đầu tiên, đảm bảo rằng bạn đã cấu hình thông tin xác thực AWS. Nếu bạn tạo với enableStageConfig và đã cấu hình thông tin xác thực stage trong packages/common/infra-config/src/stages.config.ts, lệnh deploy sẽ tự động phân giải và áp dụng thông tin xác thực chính xác cho stage đích. Nếu không, hãy đảm bảo thông tin xác thực AWS của bạn được đặt trong môi trường của bạn (ví dụ: thông qua AWS_PROFILE hoặc biến môi trường). Xem tài liệu thông tin xác thực AWS để biết các tùy chọn có sẵn.

    Sau đó chạy target deploy:

    Terminal window
    pnpm nx run <my-infra>:deploy <my-infra>-sandbox/*

    Sử dụng target deploy-ci nếu bạn đang triển khai lên AWS như một phần của pipeline CI/CD.

    Terminal window
    pnpm nx run <my-infra>:deploy-ci my-stage/*

    Target này khác một chút so với target deploy thông thường ở chỗ nó triển khai một cloud assembly đã được tổng hợp trước thay vì tổng hợp ngay lập tức. Điều này giúp tránh các vấn đề tiềm ẩn với tính không xác định do thay đổi phiên bản package, đảm bảo rằng mọi giai đoạn pipeline triển khai sử dụng cùng một cloud assembly.

    Sử dụng target destroy để xóa bỏ tài nguyên của bạn:

    Terminal window
    pnpm nx run <my-infra>:destroy <my-infra>-sandbox/*

    Để biết thêm thông tin về CDK, vui lòng tham khảo CDK Developer GuideAPI Reference.