-
Notifications
You must be signed in to change notification settings - Fork 4
Setting up a new Deployment of the Upload Service
- Introduction
- Prerequisites
- Setup AWS Account
- Pick and Register Umbrella Domain Name
- Pick Bucket Prefix
- Pick Deployment Stage
- Create SSL Certificate
- Pick AWS Region
- Pick VPC CIDR Block
- Create EC2 Key Pair
- Create AMI for Batch Validation Workers
- Create Checksummer Docker Image
- Create Validator Base Docker Image
- DCP Ingest AMQP Endpoint
- Configuration So Far
- Setup your Environment
- Setup Terraform
- Terraform
- Setup DNS
- Install and Setup the DCP CLI
- Testing
- Subsequent Deploys
- Teardown
This document describes how to setup a new deployment of the Upload Service. There are several different factors that we will address here:
- Setting up a new domain (i.e. not under .data.humancellatlas.org)
- Setting up in a new AWS account
- Setting up a new deployment stage (i.e. other than dev / integration / staging / prod)
Depending on your situation you might need to address one, two or all three of these factors. This document will try to cover the comprehensive case where you are doing all three of the above. Each major heading will be suffixed with letters D, A, S or * in square brackets to indicate this step should be executed for Domain, Account, New Stage or all. Omit steps as necessary if some of these factors do not apply to you.
- A Linux / Unix / OS X machine to deploy from.
- Installed:
- Python 3.6
- Docker (e.g. Docker for Mac)
-
terraform
(Mac:brew install terraform
) -
jq
(Mac:brew install jq
) -
envsubst
(Mac:brew install gettext
, add/usr/local/opt/gettext/bin
to your path)
- Check out the upload-service repo
- Install packages:
pip install -r requirements-dev.txt
Your AWS account needs to have completed activation and setup billing.
You need an IAM user with:
* Console and Programmatic access (access keys).
* Attached policy AdministratorAccess
.
* Access keys.
Install the AWS CLI on your local machine and configure using the above access keys, e.g.
pip install awscli
aws configure
If you’re deploying under a new DNS domain, e.g. you are forking the DCP for your own purposes, you have some decisions to make.
Decide upon a domain name for your DCP deployment. The DCP contains several services that coordinate by finding each other under a central umbrella domain name. It is also the convention that the pre-production deployments have the stage name inserted between the service name and the domain. For example the umbrella domain for the Human Cell Atlas DCP is data.humancellatlas.org. Production services live directly under this domain:
ingest.data.humancellatlas.org
upload.data.humancellatlas.org
pipelines.data.humancellatlas.org
etc…
The pre-production “staging” deployment stage services live under .staging.
at:
ingest.staging.data.humancellatlas.org
upload.staging.data.humancellatlas.org
pipelines.staging.data.humancellatlas.org
Example: in this document, we will assume we are setting up a under a new domain bogodata.org. Production services will live at *.bogodata.org
and pre-production services will live at *.<stage>.bogodata.org
.
Register your domain name and decide where your DNS records will be hosted. We recommend using Amazon Route53 for this purpose.
Decide on a naming strategy (prefix) for the Upload Service S3 buckets. This should generate globally unique names, e.g the HCA uses its DNS domain in reverse order: org-humancellatlas-upload-
. Note the dash on the end of the prefix. The deployment stage name will be appended to this prefix to generate the actual bucket name.
Example: org-bogodata-upload-
Decide upon the “deployment stage” of your deployment. You may either be performing a production (prod
) deployment, or a pre-production deployment, e.g. dev
, staging
or foo
. Only the prod
stage has special meaning in the deployment scripts (because of the different DNS implications). Pre-production stages can have any name.
Example: in this document, we will assume we are setting up a new deployment called demo
.
Note that when setting up DNS records for this deployment, DNS does not require you to create a new zone (SOA) for a subdomain such as demo.bogodata.org. You can just provide hostnames like upload.demo
in your CNAME records under zone bogodata.org.
If you are setting up a new deployment or domain, you will need to source SSL certificate(s) for the deployment-domain combination. I find it easiest to get a free wildcard certificate from the AWS Certificate Manager (ACM). If you don’t use ACM, you will still need to import your certificate into it.
Example: get wildcard SSL certificate for *.demo.bogodata.org
Decide which AWS region you are going to use. Note that some work is already done for you if you use us-east-1
. See section “AMI for Batch Validation Workers” below for details.
Actually, looking at the Terraform config (modules/database/database.tf
), today only us-east-1
is supported.
The Upload Service Terraform configuration will create a VPC for you, but you must select the IP address range for the VPC network in CIDR format, e.g. 172.16.0.0/16
. You must pick a network that does not overlap with any of the other VPCs in your account.
Setup an EC2 key pair. This key pair will be used when booting Batch workers, and may be used to log in to them to debug them. Either create a key pair or upload a public SSH key to AWS Console -> Services -> EC2 -> Key Pairs. I suggest naming your key pair upload-<stage>
, e.g. upload-demo
.
Decide what Amazon Machine Image (AMI) to use for your Batch workers that perform validation. You need an ECS optimized AMI that has sufficient storage space for the size of the files you will be validating. The HCA provides an AMI in us-east-1
region that allocates a 1 TB volume for this purpose: ami-f7a6ca8d
(ecso-with-data-vol-v2
). You can either:
- use the
ami-f7a6ca8d
AMI if you are using regionus-east-1
- copy that AMI to another region if you are using a different region (see Copying an AMI - Amazon Elastic Compute Cloud).
- build your own AMI using the instructions in
amis/README.md
Note the ID of your API.
::TBD::
::TBD::
::TBD::
So far in our example we have gathered the following information:
- Domain umbrella:
bogodata.org
- Bucket prefix:
org-bogodata-upload-
- Deployment Stage:
demo
- AWS Region:
us-east-1
- VPC CIDR Block:
172.16.0.0/16
- Default VPC Security Group ID:
sg-xxxxxxxxxxxxxxxxx
- Key pair for batch workers:
upload-demo
- validation cluster AMI ID:
ami-f7a6ca8d
Edit config/environment
:
vi config/environment
# Changes values:
AWS_DEFAULT_REGION="us-east-1"
DCP_DNS_DOMAIN="bogodata.org"
BUCKET_NAME_PREFIX="org-bogadata-"
# Save it.
echo "export INGEST_API_KEY=long-random-string-i-just-generated" > config/deployment_secrets.dev
export DEPLOYMENT_STAGE=demo
source config/environment
source config/deployment_secrets.demo
Edit config/database.ini
and create a stanza for demo (copy the one for dev).
Create an S3 bucket where you will store your terraform state:
aws s3 mb s3://org-bogodata-upload-infra
cd terraform/envs
mkdir demo
cp dev/Makefile dev/main.tf demo
cd demo
ln -s ../dev/variables.tf
ln -s ../dev/terraform.tfvars.example
Edit Makefile
and set DEPLOYMENT_STAGE
and TF_STATE_BUCKET
:
DEPLOYMENT_STAGE=demo
TF_STATE_BUCKET=org-bogodata-upload-infra
Edit main.tf
and fill in bucket
, region
and profile
where appropriate.
profile
is the name of the profile from ~/.aws/config
that has access to the terraform state bucket, and the deployment, respectively. This could be default
if you only have one account and IAM user.
terraform {
required_version = "=0.11.7"
backend "s3" {
bucket = "org-bogodata-upload-infra" // <----
key = "terraform/envs/demo/state.tfstate"
encrypt = true
region = "us-east-1" // <----
profile = "bogodata" // <----
}
}
provider "aws" {
version = ">= 1.31"
region = "us-east-1" // <----
profile = "bogodata" // <----
}
Setup terraform.tfvars
. Copy the example file:
cp terraform.tfvars.example terraform.tfvars
Then insert all the configuration data we generated in previous steps, together with made-up values for:
ingest_api_key
-
db_username
only use characters [A-Za-z0-9_] db_password
Initialize Terraform and save the vars file in S3:
make init
make upload-vars
Terraforming needs to be broken into a couple of steps the first time, as follows.
First, create the VPC, a bucket to use to deploy Lambdas, and setup the database server and database:
cd terraform/envs/demo
# Preload data used in calculations
terraform apply --target=data.aws_availability_zones.available
# Create VPC
terraform apply --target=module.upload-service.module.upload-vpc.null_resource.vpc
# Create bucket, boot database server, store database secrets
terraform apply --target=module.upload-service.aws_s3_bucket.lambda_area_bucket --target=module.upload-service.module.upload-service-database.aws_secretsmanager_secret_version.database-secrets
# Migrate the database (create tables)
cd ../../..
alembic -x db=${DEPLOYMENT_STAGE} -c=./config/database.ini upgrade head
Next , deploy the API Lambda:
cd chalice
make deploy
Prepare to deploy the Checksum Daemon (this will be done in a moment by Terraform):
cd ../daemons/upload-checksum-daemon
make stage
# Create a dummy version number for now.
aws secretsmanager create-secret --name="dcp/upload/${DEPLOYMENT_STAGE}/upload_service_version" --secret-string='{ "upload_service_version": "'foo'" }'
Complete the terraforming:
cd ../terraform/envs/demo
# Import the API lambda resources you created
tf import module.upload-service.aws_lambda_function.upload_api_lambda upload-api-demo
tf import module.upload-service.aws_iam_role.upload_api_lambda upload-api-demo
make apply
Chalice created an API Gateway for you, but you need to setup an AWS Custom Domain, and DNS entry.
Go to AWS Console -> Services -> API Gateway -> Custom Domain Names -> Create Custom Domain Name. Fill out the form: Domain Name “upload.demo.bogodata.org” Endpoint Configuration Regional ACM Certificate select the cert you created / imported from the dropdown
Click “Save”. Add a “Base Path Mapping” for “/“; select the API gateway you created from the dropdown, select stage “demo”, click “Save”.
Note the “Target Domain Name”.
Go to Route53 (or your DNS hosting). Create a new record under bogodata.org
upload.demo CNAME <target domain name>
Wait a few minutes for DNS to propagate.
If you now point a web browser at http://upload.demo.bogodata.org
you should see the API browser.
To install (this will likely have been done already when you did pip install -r requirements-dev.txt
):
pip install hca
The DCP CLI needs a little tweaking if you are not under the HCA umbrella. Edit ~/.config/hca/config.json
(mkdir -p ~/.config/hca
if necessary) and tweak the “upload” section to know about your API endpoint URL structure and bucket prefix:
{
"upload": {
"preprod_api_url_template": "https://upload.{deployment_stage}.bogodata.org/v1",
"production_api_url": "https://upload.bogodata.org/v1",
"bucket_name_template": "org-bogodata-upload-{deployment_stage}",
}
}
The hca
script that is installed may be renamed to something else without affecting its behavior.
To test your deployment run:
make functional-tests
# This command is very noisy. You can ignore the warnings.
scripts/deploy.sh
To undo all this configuration, terraform destroy
gets rid of most things, but there is a little extra work to do:’
- Empty your buckets first. Terraform can’t delete non-empty buckets.
- Delete the DNS record.
- Delete the API Gateway Custom Domain Name and API Gateway.
terraform destroy
- If you are going to repeat this exercise, really delete your secrets, otherwise Terraform gets confused. Find out the ARN of each of your secrets (deleted or otherwise) then:
aws secretsmanager delete-secret --secret-id="<arn>" --force-delete-without-recovery
- Delete the
*-upload-infra
bucket.