constructor()

in LambdaWordpress/lib/lambda_wordpress-stack.ts [12:220]


  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    var DB_HOST = null;
    var HTTP_HOST = null;
    const DB_NAME = 'wordpress';
    const DB_USER = 'wordpressuser';
    const BASE_PATH = '/mnt/efs';
    const ACCESSPOINT_PATH = '/wordpress';
    const WORDPRESS_PATH = '/mnt/efs';
    const KEY_NAME = this.node.tryGetContext('keyName');
    const DOMAIN_NAME = this.node.tryGetContext('domainName');
    const DB_PASSWORD = this.node.tryGetContext('dbPassword');

    //set the certificate
    const myCertificate = new cm.Certificate(this, 'myCertificate',{
      domainName: DOMAIN_NAME,
      validation: cm.CertificateValidation.fromDns(),
    });

    //create VPC 
    const serverlessVPC = new ec2.Vpc(this, 'serverlessWordpressVPC', {
      cidr: '10.0.0.0/16',
      subnetConfiguration: [
        {
          subnetType: ec2.SubnetType.PUBLIC,
          name: 'public',
          cidrMask: 24,
        },
        {
          cidrMask: 24,
          name: 'private',
          subnetType: ec2.SubnetType.PRIVATE,
        },
      ],
    });

    /**
     * create security group in VPC
     */
    // NFS security group which used for ec2 to copy file
    const sgNFSSG = new ec2.SecurityGroup(this, 'NFSAllowAllSG', {
      vpc: serverlessVPC,
      description: 'allow 2049 inbound for ec2',
      allowAllOutbound: true,
    });
    sgNFSSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(2049), 'allow 2049 inbound from ec2')

    //ALB security group which allow 80 and 443
    const albSG = new ec2.SecurityGroup(this, 'albSG', {
      vpc: serverlessVPC,
      description: 'allow 80 and 443',
      allowAllOutbound: true,
    });
    albSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80), 'allow 80 inbound');
    albSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), 'allow 443 inbound');

    //EC2 security group which allow port 22
    const ec2SG = new ec2.SecurityGroup(this, 'ec2SG', {
      vpc: serverlessVPC,
      description: 'allow 22 inbound for ec2',
      allowAllOutbound: true,
    });
    ec2SG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow 22 inbound from ec2')

    // RDS security group which allow port 3306
    const rdsSG = new ec2.SecurityGroup(this, 'wordpressRdsSecurityGroup', {
      vpc: serverlessVPC,
      description: 'allow 3306 inbound',
      allowAllOutbound: true,
    });
    rdsSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(3306), 'allow 3306 inbound from lambda');

    /**
     * create EFS attached on Lambda
     */
    const fileSystem = new efs.FileSystem(this, 'wordpressEFS', {
      vpc: serverlessVPC,
      encrypted: false,
      performanceMode: efs.PerformanceMode.GENERAL_PURPOSE,
      throughputMode: efs.ThroughputMode.BURSTING,
      securityGroup: sgNFSSG,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });
    //create access point on efs
    const accessPoint = fileSystem.addAccessPoint('LambdaAccessPoint', {
      path: ACCESSPOINT_PATH,
      createAcl: {
        ownerUid: '1000',
        ownerGid: '1000',
        permissions: '0777',
      },
      posixUser: {
        uid: '1000',
        gid: '1000',
      },
    });

    /**
     * Create lambda function
     */
    const lambdaFunc = new lambda.Function(this, 'wordpressLambdaFUnction', {
      code: lambda.Code.fromAsset(path.join(__dirname, 'phpLambdaFunc')),
      handler: 'handler.php',
      memorySize: 1024,
      timeout: cdk.Duration.minutes(15),
      tracing: lambda.Tracing.ACTIVE,
      runtime: lambda.Runtime.PROVIDED,
      layers: [lambda.LayerVersion.fromLayerVersionArn(this, 'customPhpLayer', 'arn:aws:lambda:us-east-1:887080169480:layer:php73:3')],
      vpc: serverlessVPC,
      filesystem: lambda.FileSystem.fromEfsAccessPoint(accessPoint, BASE_PATH),
    });

    /*
     * create alb and integrate it with lambda
     */
    const lb = new elbv2.ApplicationLoadBalancer(this, 'serverlessALB', {
      vpc: serverlessVPC,
      internetFacing: true,
      securityGroup: albSG,
    });

    const lambdaTarget = new targets.LambdaTarget(lambdaFunc);
    const albTargetGroup = new elbv2.ApplicationTargetGroup(this,'albTargetGroup',{
      targets: [lambdaTarget],
    });
    albTargetGroup.setAttribute('lambda.multi_value_headers.enabled', 'true');

    const listener80 = lb.addListener('Listener80', {
      port: 80,
      open: true,
    });
    listener80.addAction('80action',{
      action: ListenerAction.forward([albTargetGroup])
    });

    const listener443 = lb.addListener('Listener443', {
      port: 443,
      open: true,
      certificateArns:[myCertificate.certificateArn],
    });
    listener443.addAction('443action',{
      action: ListenerAction.forward([albTargetGroup])
    });

    /**
     * create RDS
     */

    const secret = cdk.SecretValue.plainText(DB_PASSWORD);
    const auroraServerlessCluster = new rds.DatabaseCluster(this, 'ServerlessWordpressAuroraCluster', {
      engine: rds.DatabaseClusterEngine.AURORA_MYSQL,
      credentials: rds.Credentials.fromPassword(DB_USER,secret),
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      instanceProps: {
        vpc: serverlessVPC,
        securityGroups: [rdsSG],
      },
      defaultDatabaseName: DB_NAME,
    });

    /***
     *  set the DB_HOST and HTTP_HOST which will used in the lambda environment
     */
    DB_HOST = auroraServerlessCluster.clusterEndpoint.hostname;
    HTTP_HOST = lb.loadBalancerDnsName;

    //SET lambda enviromnent
    lambdaFunc.addEnvironment('DB_HOST', DB_HOST);
    lambdaFunc.addEnvironment('DB_NAME', DB_NAME);
    lambdaFunc.addEnvironment('DB_USER', DB_USER);
    lambdaFunc.addEnvironment('DB_PASSWORD', DB_PASSWORD);
    lambdaFunc.addEnvironment('WORDPRESS_PATH', WORDPRESS_PATH);
    lambdaFunc.addEnvironment('HTTP_HOST', HTTP_HOST);

    // create EC2 which used to install wordpress files to EFS
    const amznLinux = ec2.MachineImage.latestAmazonLinux({
      generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX,
      edition: ec2.AmazonLinuxEdition.STANDARD,
      virtualization: ec2.AmazonLinuxVirt.HVM,
      storage: ec2.AmazonLinuxStorage.GENERAL_PURPOSE,
    });

    const ec2EFS = new ec2.Instance(this,'efsInstance',{
      vpc: serverlessVPC,
      vpcSubnets: {subnetType:ec2.SubnetType.PUBLIC},
      machineImage : amznLinux,
      instanceType: new ec2.InstanceType('t2.large'),
      securityGroup: ec2SG,
      keyName:KEY_NAME,
    });

    ec2EFS.userData.addCommands(
      //install efs tool and create mount point
      'sudo yum install -y amazon-efs-utils',
      'sudo mkdir /mnt',
      'sudo mkdir /mnt/efs',
    );

    new cdk.CfnOutput(this, 'outputEFS', {
      description: 'efs id',
      value: 'efs id: ' +fileSystem.fileSystemId,
    });

    new cdk.CfnOutput(this, 'outputALBDNS', {
      description: 'alb dns name',
      value: 'alb dns name: ' +lb.loadBalancerDnsName,
    });
  }