AWS CDK를 사용하여 Postgres 데이터베이스를 사용하여 확장 가능한 NodeJS 응용 프로그램 배포

이 간단한 강좌는 AWS 클라우드 개발 도구 패키지를 사용하여 AWS 클라우드에 모든 NodeJS 응용 프로그램을 배치하는 방법을 보여 줍니다.Google 응용 프로그램은 Postgress 데이터베이스를 사용하지만, 본 강좌의 코드는 응용 프로그램에 모든 데이터베이스를 배치하는 기초가 될 수 있습니다.
저는 AWS CDK의 기초 지식을 소개하지 않겠습니다. 좋은 자원이 많기 때문에 처음부터 모든 것을 설명하고 AWS CDK 프로젝트를 어떻게 이끌어가는지 보여 드리겠습니다.
만약 기초 지식을 검사해야 한다면, 여기에는 좋은 출처가 있다.
AWS CDK repo
여기서 나는 우리가 해야 할 일을 상세하게 설명했다.
  • AWS Secret Manager를 사용하여 기밀을 만들고 사용자 정의 스택
  • 에서 읽습니다.
  • 데이터베이스 정의를 사용하여 RDS 스택 만들기
  • 어플리케이션 배포를 위한 ElasticBeanstalk 스택 만들기
  • VPC 스택을 만들고 모든 콘텐츠를 연결
  • 주의: 본 강좌의 영감은 다른 두 편의 문장에서 나온다.만약 그들이 없었다면 나는 더 많은 시간을 들여야만 모든 것을 알 수 있었을 것이다.
    Complete AWS Elastic Beanstalk Application through CDK (TypeScript)
    그러니까 더 이상 귀찮게 하지 말고 시작합시다!

    AWS 기밀 관리자에서 기밀 작성
    AWS 콘솔로 이동하여 Secret Manager 서비스를 검색하고 데이터베이스에 연결된 사용자 이름과 암호를 저장할 두 개의 기밀을 만듭니다.AWS는 이름 규약을 유지할 것을 권장하기 때문에 사용자 기밀의 이름으로prod/service/db/user, 비밀번호의 이름으로prod/service/db/password를 사용하도록 합니다.
    일단 당신이 이 비밀을 만들고 ARN을 보류한다면 당신은 그것을 얻을 수 있을 것이다.그들은 우리의 관계를 맺도록 요구받을 것이다.

    자격 증명을 저장할 스택을 만듭니다.
    Secret Manager에 저장된 자격 증명을 읽을 수 있는 lib/credentials-stack.ts라는 파일을 만듭니다.
    import * as cdk from "@aws-cdk/core";
    import { ISecret, Secret } from "@aws-cdk/aws-secretsmanager";
    
    export interface Credentials {
      username: ISecret;
      password: ISecret;
    }
    
    export class CredentialsStack extends cdk.Stack {
      readonly credentials: { username: ISecret; password: ISecret };
    
      constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        const secretUsername = Secret.fromSecretCompleteArn(
          this,
          "BackendPersistenceUsername",
          // Pass your username secret ARN
          ""
        );
    
        const secretPassword = Secret.fromSecretCompleteArn(
          this,
          "BackendPersistencePassword",
          // Pass your password secret ARN
          ""
        );
    
        this.credentials = {
          username: secretUsername,
          password: secretPassword,
        };
      }
    }
    
    데이터베이스에 연결하는 데 필요한 기밀을 읽고 이 창고에 첨부된 credentials 속성에 저장하는 새로운 창고를 만들었습니다.잠시 후, 우리는 이 증빙서류들을 다른 창고에 전달할 수 있을 것이다.

    Postgress 데이터베이스를 사용하여 RDS 스택 만들기
    Postgress 데이터베이스에 대한 정의를 저장하기 위해 창고를 만들어야 합니다.이를 위해 lib/rds-stack.ts라는 파일을 만듭니다.
    import * as cdk from "@aws-cdk/core";
    import * as ec2 from "@aws-cdk/aws-ec2";
    import * as rds from "@aws-cdk/aws-rds";
    import { Credentials } from "./credentials-stack";
    
    export interface RdsStackProps extends cdk.StackProps {
      credentials: Credentials;
      vpc: ec2.Vpc;
    }
    
    export class RdsStack extends cdk.Stack {
      readonly postgreSQLinstance: rds.DatabaseInstance;
    
      constructor(scope: cdk.Construct, id: string, props: RdsStackProps) {
        super(scope, id, props);
    
        const username = props.credentials.username.secretValue.toString();
        const password = props.credentials.password.secretValue;
    
        this.postgreSQLinstance = new rds.DatabaseInstance(this, "Postgres", {
          engine: rds.DatabaseInstanceEngine.postgres({
            version: rds.PostgresEngineVersion.VER_12_4,
          }),
          instanceType: ec2.InstanceType.of(
            ec2.InstanceClass.T2,
            ec2.InstanceSize.MICRO
          ),
          vpc: props.vpc,
          vpcPlacement: {
            subnetType: ec2.SubnetType.PUBLIC,
          },
          storageType: rds.StorageType.GP2,
          deletionProtection: false,
          databaseName: username,
          port: 5432,
          credentials: {
            username,
            password,
          },
        });
    
        this.postgreSQLinstance.connections.allowDefaultPortFromAnyIpv4();
        this.postgreSQLinstance.connections.allowDefaultPortInternally();
      }
    }
    
    AWS의 모든 데이터베이스는 특정한 전용 네트워크의 범위 내에서 만들어야 하기 때문에, 우리는 우리의 창고에 도구 인터페이스를 정의하고, 이 창고를 실례화할 때 전달해야 한다고 지정한다. vpc그 밖에 우리는 credentials-stack에 저장된 증거를 통과해야 한다.
    이 Postgress 실례를 정의했습니다. 기본 T2 MICRO 실례를 사용하고 공공 범위에 놓여 있습니다. 저희 데이터베이스는 인터넷에서 접근할 수 있습니다.우리는 실례적으로 특수한 방법(allowDefaultPortFromAnyIpv4allowDefaultPortInternally을 호출하여 연결을 허용합니다.

    ElasticBeanstalk을 사용한 배포 작성
    그리고 프로그램 파일을 S3로 복사한 다음 Elastic Beanstalk 서비스에 배치하는 스택을 만들 수 있습니다.lib/ebs-stack.ts라는 파일을 만들고 다음 코드를 붙여넣습니다.
    import * as cdk from "@aws-cdk/core";
    import * as EB from "@aws-cdk/aws-elasticbeanstalk";
    import * as S3Assets from "@aws-cdk/aws-s3-assets";
    
    import { Credentials } from "./credentials-stack";
    
    export interface EbsStackProps extends cdk.StackProps {
      dbCredentials: Credentials;
      dbHost: string;
      dbPort: string;
      dbName: string;
    }
    
    export class EbsStack extends cdk.Stack {
      constructor(scope: cdk.App, id: string, props: EbsStackProps) {
        super(scope, id, props);
    
        const username = props.dbCredentials.username.secretValue.toString();
        const password = props.dbCredentials.password.secretValue;
    
        // Here you can specify any other ENV variables which your application requires
        const environmentVariables: Record<string, any> = {
          POSTGRES_USER: username,
          POSTGRES_PASSWORD: password,
          POSTGRES_DB: props.dbName,
          DB_HOST: props.dbHost,
          DB_PORT: props.dbPort,
          DB_SCHEMA: username,
        };
    
        const environmentOptions = Object.keys(environmentVariables).map(
          (variable) => {
            return {
              namespace: "aws:elasticbeanstalk:application:environment",
              optionName: variable,
              value: environmentVariables[variable],
            };
          }
        );
    
        const applicationName = "Server";
    
        const assets = new S3Assets.Asset(this, `${applicationName}-assets`, {
          // Change path to your applications dist files
          // In my case I've created a monorepo, so path was like ../server/dist
          path: "path/to/your/application/dist",
          exclude: ["node_modules",],
        });
    
        const application = new EB.CfnApplication(this, `${applicationName}-app`, {
          applicationName,
        });
    
        const appVersionProps = new EB.CfnApplicationVersion(
          this,
          `${applicationName}-version`,
          {
            applicationName,
            sourceBundle: {
              s3Bucket: assets.s3BucketName,
              s3Key: assets.s3ObjectKey,
            },
          }
        );
    
        const options: EB.CfnEnvironment.OptionSettingProperty[] = [
          {
            namespace: "aws:autoscaling:launchconfiguration",
            optionName: "IamInstanceProfile",
            value: "aws-elasticbeanstalk-ec2-role",
          },
          {
            namespace: "aws:ec2:instances",
            optionName: "InstanceTypes",
            value: "t3.small",
          },
        ];
    
        new EB.CfnEnvironment(this, `${applicationName}-environment`, {
          environmentName: "develop",
          applicationName: application.applicationName || applicationName,
          solutionStackName: "64bit Amazon Linux 2 v5.2.3 running Node.js 12",
          optionSettings: [...options, ...environmentOptions],
          versionLabel: appVersionProps.ref,
        });
    
        appVersionProps.addDependsOn(application);
      }
    }
    
    첫 번째 단계는 프로그램의 원본 파일을 포함하는 S3 버킷을 만드는 것입니다.이 S3 로직은 CloudFormation 템플릿이 EBS에 사용되기 전에 트리거됩니다.
    그리고 응용 프로그램의 환경을 만들고 응용 프로그램을 분배합니다.업로드된 원본 파일에 유일한 프로그램 버전 addDependsOn 을 지정했습니다.

    VPC 스택 작성 및 모든 스택 연결
    VPC는 우리 서비스 범위 내의 개인 네트워크와 같이 서로 통신할 수 있다.AWS의 모든 데이터베이스는 항상 특정한 전용 네트워크의 범위 내에서 만들어져야 하기 때문에 이 데이터베이스를 정의합니다.lib/vpc-stack.ts라는 파일을 만듭니다.이것은 매우 짧다.
    import * as cdk from "@aws-cdk/core";
    import * as ec2 from "@aws-cdk/aws-ec2";
    
    export class VpcStack extends cdk.Stack {
      readonly vpc: ec2.Vpc;
    
      constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        this.vpc = new ec2.Vpc(this, "VPC");
      }
    }
    
    우리는 이미 새로운 기본 VPC 실례를 만들어서 vpcVpcStack 속성에 분배했다.
    현재, 우리는 모든 부분을 준비했다. 우리는 bin/infrastructure-stack.ts에 실행 가능한 창고를 만들어서 그것을 연결할 수 있다
    #!/usr/bin/env node
    import * as cdk from "@aws-cdk/core";
    
    import { EbsStackProps, EbsStack } from "../lib/ebs-stack";
    import { CredentialsStack } from "../lib/credentials-stack";
    import { RdsStack } from "../lib/rds-stack";
    import { VpcStack } from "../lib/vpc-stack";
    
    const app = new cdk.App();
    
    const vpcStack = new VpcStack(app, "VpcStack");
    const vpc = vpcStack.vpc;
    
    const credentialsStack = new CredentialsStack(
      app,
      "CredentialsStack"
    );
    
    const rdsStack = new RdsStack(app, "RdsStack", {
      credentials: credentialsStack.credentials,
      vpc,
    });
    
    const dbInstance = rdsStack.postgreSQLinstance;
    
    const ebsEnvironment: EbsStackProps = {
      dbCredentials: credentialsStack.credentials,
      dbName: credentialsStack.credentials.username.secretValue.toString(),
      dbHost: dbInstance.instanceEndpoint.hostname.toString(),
      dbPort: "5432",
    };
    
    new EbsStack(app, "EbsStack", ebsEnvironment);
    
    모든 사용자 정의 창고를 가져오고 VpcStack, CredentialsStack 실례를 만듭니다.그리고 우리는 RdsStack를 사용하여 새로운 데이터베이스 실례를 만들 수 있다.VPC와 인증서를 도구로 전달하는 것을 잊지 마세요.그리고 우리는 EbsStack 실례를 만들고 데이터베이스 연결에 모든 환경 변수를 전달할 수 있다.
    운이 좋으면, 런닝 yarn build && cdk deploy --all 은 응용 프로그램을 클라우드 포메이션에 포장하여 배치합니다.여기서 ElasticBeanstalk 및 RDS 서비스가 생성되어 제대로 작동하는지 확인할 수 있습니다.
    읽어주셔서 감사합니다. 언제든지 연락 주세요!

    좋은 웹페이지 즐겨찾기