Deployment in AWS

Along with the Kubernetes cluster, GoodData.CN requires the following AWS resources:

  • ElastiCache cluster (with Redis interface)
  • Aurora RDS (Postgres family)

Before you start deploying these services, ensure that you know the name of the CloudFormation stack that was generated and deployed during the initial EKS deployment using the eksctl tool.

The name of the stack is usually eksctl-<name>-cluster, where <name> is the name that you gave to the EKS cluster when you created it. If you are unsure about the stack name, you can get it from the AWS console or by using aws cloudformation describe-stacks --query 'Stacks[*].StackName'.

ElastiCache Cluster

There are two options of deployment ElastiCache cluster - manual and using CloudFormation stack. Manual method is good for quick setup and also to see what needs to be done if you want to use another IaaC tool (e.g. Terraform). Both manual and CloudFormation methods are equivalent. These resources will be created within your EKS VPC:

  • Cache Parameter Group with necessary Redis configuration
  • Cache Subnet Group containing 3 private EKS subnets
  • Security Group allowing access to Redis from EKS worker nodes
  • Replication Group with 3 node Redis cluster

Manual setup

The following data needs to be collected before you start:

# VPC where the EKS cluster is deployed
VPC_ID='vpc-xxxxxxx'

# List of private EKS subnet ids
SUBNET_IDS=('subnet-aaaaaaa' 'subnet-bbbbbbb' 'subnet-ccccccc')

# Shared node security group of EKS cluster (or any SG that is attached to
# all the EKS worker nodes where GoodData.CN will be running)
SOURCE_SG='sg-1111111'

# Redis AUTH token, matching the following regex: ^[a-zA-Z0-9!&#$^<>-]{16,128}$
REDIS_AUTH_TOKEN='Sup3r$3#e^p4$$w3rt'

Now you can create AWS resources using script:

aws elasticache \
    create-cache-parameter-group \
    --cache-parameter-group-name gooddata-cn-redis-param-group \
    --cache-parameter-group-family redis6.x \
    --description "Parameter group for GoodData.CN Redis"

aws elasticache \
    modify-cache-parameter-group \
    --cache-parameter-group-name gooddata-cn-redis-param-group \
    --parameter-name-values \
        "ParameterName=cluster-enabled, ParameterValue=yes" \
        "ParameterName=maxmemory-policy, ParameterValue=allkeys-lru"

aws elasticache \
    create-cache-subnet-group \
    --cache-subnet-group-name gooddata-cn-cache-subnet-group \
    --cache-subnet-group-description "Subnet group for GoodData.CN Redis" \
    --subnet-ids "${SUBNET_IDS[@]}"

REDIS_SG=$(aws ec2 \
    create-security-group \
    --group-name "gooddata-cn-redis-sg" \
    --description "SG for GoodData.CN Redis" \
    --vpc-id "$VPC_ID" | jq -r .GroupId)

aws ec2 \
    authorize-security-group-ingress \
    --group-id "$REDIS_SG" \
    --protocol tcp \
    --port 6379 \
    --source-group "$SOURCE_SG"

aws elasticache \
    create-replication-group \
    --replication-group-id gooddata-cn-redis \
    --replication-group-description "Redis cache for GoodData.CN" \
    --automatic-failover-enabled \
    --multi-az-enabled \
    --num-cache-clusters 3 \
    --num-node-groups 1 \
    --cache-node-type cache.t3.micro \
    --engine redis \
    --engine-version 6.2 \
    --cache-parameter-group-name gooddata-cn-redis-param-group \
    --cache-subnet-group-name gooddata-cn-cache-subnet-group \
    --security-group-ids "$REDIS_SG" \
    --preferred-maintenance-window "sun:23:00-mon:01:30" \
    --port 6379 \
    --auto-minor-version-upgrade \
    --auth-token "$REDIS_AUTH_TOKEN" \
    --transit-encryption-enabled

CloudFormation Stack

The other way is to use the elasticache-redis.yaml CloudFormation template to deploy ElastiCache.

You must add the following parameters to the template:

  • ParentVPCStack (eksctl-<name>-cluster as it was created by eksctl)
  • EngineVersion (Redis version, defaults to 6.2)
  • CacheNodeType (one of the supported instance sizes, defaults to cache.t3.micro)
  • RedisAuthToken (token used for Redis AUTH command)

Use the following command to provision the service:

aws cloudformation create-stack --stack-name gooddata-cn-cache-redis \
  --template-body file://elasticache-redis.yaml \
  --parameters \
      'ParameterKey=ParentVPCStack,ParameterValue=eksctl-<name>-cluster' \
      'ParameterKey=CacheNodeType,ParameterValue=cache.t4g.small' \
      'ParameterKey=RedisAuthToken,ParameterValue=Sup3r$3#e^p4$$w3rt'

Values as subnet ids or shared node security group are automatically retrieved from the parent eksctl-created stack.

The command returns the identifier of a created CloudFormation stack.

It takes several minutes to create resources. You can watch progress in the AWS console, or by using aws-cli:

aws cloudformation wait stack-create-complete --stack-name gooddata-cn-cache-redis

When the status is “CREATE_COMPLETE”, the resource is created.

aws cloudformation describe-stacks --stack-name gooddata-cn-cache-redis \
  --query 'Stacks[0].StackStatus'

RDS Aurora

Use the rds-aurora.yaml CloudFormation template to deploy RDS.

You must add following parameters to the template:

  • ParentVPCStack (eksctl-<name>-cluster)
  • DBUsername (username for database access, defaults to postgres)
  • DBPassword (password of the DB user)
  • DBInstanceType (one of the supported instance sizes, defaults to db.r4.large)
  • DBEngineVersion (version of the PostgreSQL engine, defaults to 14.4)
  • SnapshotARN (ARN of DB snapshot to restore - useful for major version upgrades, default is empty)

Use the following command to provision the service:

aws cloudformation create-stack --stack-name gooddata-cn-md-aurora \
  --template-body file://rds-aurora.yaml \
  --parameters \
      "ParameterKey=ParentVPCStack,ParameterValue=eksctl-<name>-cluster" \
      "ParameterKey=DBPassword,ParameterValue=secret123"

The command returns the identifier of a created CloudFormation stack.

It takes several minutes to create resources. You can watch progress in the AWS console, or by using aws-cli:

aws cloudformation wait stack-create-complete --stack-name gooddata-cn-md-aurora

When the status is “CREATE_COMPLETE”, the resource is created.

aws cloudformation describe-stacks --stack-name gooddata-cn-md-aurora \
  --query 'Stacks[0].StackStatus'