Skip to content

Cloudformation Setup

Get the template

From the Caktus AWS WebStacks repository find the template that suits your needs. For the vast majority of cases you will want to use eks-nat.yaml. After downloading it is a good idea to set the version (e.g. eks-nat-2.1.2.yaml). You can grab that from the latest tag.

Copy the file into your project's deploy/stack folder.

Configure the ansible variables

The variables for your stack are often found in the deploy/group_vars/all.yaml.

EXAMPLE:

# ----------------------------------------------------------------------------
# AWS Web Stacks: Configuration variables to be used by the
#                 caktus/aws-web-stacks role
# ----------------------------------------------------------------------------

cloudformation_stack_profile: '{{ aws_profile }}'
cloudformation_stack_region: '{{ aws_region }}'
cloudformation_stack_name: '{{ app_name }}-{{ env_name }}-stack'
cloudformation_stack_template_local_path: '{{ playbook_dir + "/stack/eks-nat-2.1.2.yaml" }}'
cloudformation_stack_template_bucket: 'aws-web-stacks-{{ app_name }}'
cloudformation_stack_template_bucket_path: 'templates/{{ env_name }}/{{ cloudformation_stack_name }}.yml'
cloudformation_stack_create_changeset: true
cloudformation_stack_template_parameters:
  PrimaryAZ: "{{ aws_region }}a"
  SecondaryAZ: "{{ aws_region }}b"
  DesiredScale: 2
  MaxScale: 2
  UseAES256Encryption: "true"
  CustomerManagedCmkArn: ""
  ContainerInstanceType: t3a.medium
  ContainerVolumeSize: 30
  DatabaseClass: db.t3.small
  DatabaseEngineVersion: "14"
  DatabaseParameterGroupFamily: postgres14
  DatabaseMultiAZ: "true"
  DatabaseUser: "{{ admin_database_user|default(app_name) }}"
  DatabasePassword: "{{ admin_database_password }}"
  DatabaseName: "{{ admin_database_name|default(app_name) }}"
  DomainName: "{{ app_name }}." ## What should this be
  DomainNameAlternates: ""
  AssetsUseCloudFront: "false"
  # Bastion host
  BastionKeyName: <some-pre-existing-key-pair>

Note: You may ask yourself, what is going on with that BastionKeyName variable, I don't need a bastion server. That may be true but head to the appendix to find out why it is needed. The Trouble With Bastion

Note: If you need to encrypt cluster secrets follow head on down to Envelope encryption

Add ansible role to the deployment

To use WebStacks we need to install Caktus AWS Web Stacks Role into the project.

Add the following to deploy/requirements.yaml:

- src: https://github.com/caktus/ansible-role-aws-web-stacks
  name: caktus.aws-web-stacks
  version: ''

Install the role

$ ansible-galaxy install -f -r deploy/requirements.yaml

Run the CloudFormation Stack Playbook

$ ansible-playbook deploy/deploy-cf-stack.yaml

Configure Services

After cloudformation has run, it will have created a bunch of services within the AWS account.

  1. An EKS cluster.
  2. An ECR repository.
  3. An RDS database.

the ansible process will print into the terminal a list of resources that you will use to populate variables in the deploy files.

TASK [caktus.aws-web-stacks : print cf_stack_outputs] ****************************************************************************************************************************************************************************************************
ok: [aws.amazon.com] => 
  cloudformation_stack_result.stack_outputs:
    AssetsBucketDomainName: <VALUE>
    ClusterEndpoint: https://<VALUE>.eks.amazonaws.com
    DatabaseAddress: <VALUE>.rds.amazonaws.com
    DatabasePort: '5432'
    DatabaseURL: postgres://<VALUE>.rds.amazonaws.com:5432/<APP_NAME>
    PrivateAssetsBucketDomainName: <VALUE>-privateassetsbucket-y1hs1zsetsnc.s3.amazonaws.com
    RepositoryURL: <VALUE>-us-east-2.amazonaws.com/<VALUE>-applicationrepository-wh5tljkspmgv

Now you can take this information and Configure your services

Appendix

The trouble with Bastion

Currently, there is a known limitation with WebStacks and Bastion Even if your project does not need a Bastion server, the cloudformation process will fail because of a Type validation check. So a workaround is to create a key pair in EC2, and use the keyname in the BastionKeyName variable.

Create a Key Pair

NOTE: Make sure you are in the same region the cluster will be created in.

  1. Navigate to EC2 in the AWS console.
  2. Under Network and Security menu on the left select Key Pairs
  3. Click the Create Pair button in the top right.
  4. Enter the Key name you wish to use.
  5. Select ED25519 type.
  6. Click Create Key Pair

Envelope Encryption of Cluster Secrets

One of the considerations for the security of the cluster is whether you want to encrypt the Cluster secrets. The decision-making process for this is well beyond the scope of this doc, but if you do, you will need to add a Customer Managed Key to the account.

  1. In the AWS console, navigate to Key Management Service (KMS).
  2. In the top right click Add a Key.
  3. Leave Symmetric checked and click Next.
  4. Add an Alias for the CMK, and click Next.
  5. For Key administrators check CaktusAccountAccessRole-Admins and click Next.
  6. For Define key usage permissions check AWSServiceRoleForAmazonEKS and AWSServiceRoleForRDS
  7. Click Next, and Next

Now the key will be created, and you will need to copy the arn for the key into the CustomerManagedCmkArn entry.

  1. Click into the detail for key you created.
  2. Copy the ARN from the General Information section.

Last update: 2024-05-08