Рубрики
Uncategorized

Развертывание масштабируемого приложения Nodejs с базой данных Postgres с использованием AWS CDK

Этот простой учебник покажет, как развернуть любое приложение Nodejs в AWS Cloud с AWS Cloud Devel … Tagged с AWS, узлом, JavaScript, DevOps.

Этот простой учебник покажет, как развернуть любое приложение Nodejs в AWS Cloud с использованием комплекта разработки AWS. Наше приложение будет использовать базу данных Postgres, но код из этого урока может стать основой для развертывания любой базы данных с вашим приложением.

Я не буду охватывать основы CDK AWS, так как есть много хороших ресурсов, которые объясняют все с нуля и показывают, как загрузить ваш проект AWS CDK.

Если вам нужно проверить основы, вот несколько хороших источников:

Что такое AWS CDK (комплект разработки облаков) и почему это потрясающе AWS CDK Repo

Здесь я указываю, что мы собираемся сделать:

  • Создайте секреты, используя AWS Secret Manager и прочитайте их из нашего пользовательского стека
  • Создайте стек RDS с определением базы данных
  • Создайте стек Elasticbeanstalk для развертывания приложений
  • Создайте стек VPC и все подключите все

Примечание: этот учебник вдохновлен двумя другими сообщениями. Без них мне потребовалось бы гораздо больше времени, чтобы выяснить все:

Я говорю вам секрет: Предоставьте учетные данные базы данных для задачи ECS FARGATE в AWS CDK Полное приложение AWS Elastic Beanstalk через CDK (TypeScript)

Так Без лишних слов, давайте начнем!

Создать секреты в секретном менеджере AWS

Зайдите на свою консоль AWS и найдите Сервис Secret Manager и создайте два секрета для хранения вашего имени пользователя и пароля для подключения к базе данных. AWS предлагает вам сохранить их соглашения об именах, поэтому давайте использовать prod/service/db/user как имя для пользовательской секрета и Prod/Service/DB/пароль как имя для пароля.

Как только вы создадите эти секреты, сохраните ARN, который вы вернете. Они должны будут настроить наше соединение.

Создайте стек для сохранения учетных данных

Давайте создадим файл с именем lib/detrentys-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,
    };
  }
}

Мы сделали новый стек, в котором мы читаем секреты, необходимые для подключения к нашей базе данных, и сохранить их в Учетные данные свойство прикреплено к этому стеку. Позже мы сможем передать эти полномочия в другие стеки.

Создать стек RDS с базой данных Postgres

Теперь нам нужно создать стек, который будет иметь определения для вашей базы данных Postgres. Для этого давайте создадим файл с именем 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, мы определили интерфейс для реквизита в нашем стеке и указали, что VPC Должен быть передан при создании этого стека. Кроме того, нам нужно будет передать учетные данные, которые мы сохраняем в Условные данные Анкет

Этот постгрный экземпляр, который мы определили, использует базовый T2 Micro экземпляр, и находится в общедоступном объеме — наша база данных будет доступна из Интернета. Обратите внимание, что мы разрешаем подключения, вызывая специальные методы ( AllieFaultPortFomanyiPv4 и AllingDefaultportinternally ) в нашем случае.

Создание развертывания с помощью ElasticBeanstalk

Затем мы можем создать стек, ответственный за копирование файлов наших приложений в S3, а затем развернуть его в службу Elasticbeanstalk. Давайте создадим файл с именем 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 = {
      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 всегда должна быть создана в объеме некоторых VPC, поэтому давайте определим стек для этого. Создайте файл с именем 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 по умолчанию и присвоили его VPC собственность на VPCStack Анкет

Теперь, так как у нас есть все детали, мы можем подключить его, создав исполняемый стек в 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 и Указание . Затем мы можем создать новый экземпляр базы данных, используя Rdsstack Анкет Не забудьте передать VPC и полномочия в качестве реквизита. Затем мы можем создать EBSstack экземпляр и передайте каждую переменную среды для подключения к базе данных.

С некоторой удачей, бег Сборка пряжи && cdk Deploy -All будет упаковаться и развернуть ваше приложение для Cloudformation. Там вы можете убедиться, что услуги Elasticbeanstalk и RDS были созданы и работают правильно.

Спасибо за чтение, и не стесняйтесь связаться со мной!

Оригинал: «https://dev.to/skona27/deploy-scalable-nodejs-application-with-postgres-database-using-aws-cdk-22l4»