Quickstart with AWS ECS
Introduction
This tutorial will help you set up a cluster, register a task definition, run the Hasura GraphQL Engine as a Linux Fargate task, and perform other common tasks in Amazon ECS with the AWS CLI.
This guide requires HGE versions v2.12.0
and above. Installation instructions are below.
Deploying Hasura Enterprise Edition on ECS
Prerequisites
This tutorial assumes that the following prerequisites have been met:
- The latest version of the AWS CLI is installed and configured. For more information about installing or upgrading your AWS CLI, see Installing the AWS Command Line Interface.
- The steps in Set up to use Amazon ECS have been completed.
- Your AWS user has the required permissions specified in the Amazon ECS first-run wizard permissions.
- You have a Postgres database for storing Metadata and Redis for caching / rate limiting, preferably a managed service, which is accessible from the ECS containers.
- You have a VPC and security group created to use. This tutorial uses a container image hosted on the Public docker hub
so your task must have internet access. To give your task a route to the internet, use one of the following options:
- Use a private subnet with a NAT gateway that has an elastic IP address.
- Use a public subnet and assign a public IP address to the task.
- For more information, see Create a virtual private cloud.
Step 1: Create a Cluster
If your account already has an ECS cluster you would like to use, skip this step.
Create your own cluster with a unique name with the following command:
aws ecs create-cluster --cluster-name hasura-fargate-cluster
Step 2: Get the ECS task definition
The install manifests repo contains all installation manifests required to deploy Hasura anywhere. Get the ECS task definition files from there:
wget https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/enterprise/aws-ecs/hasura-fargate-task.json
Step 3: Set the Metadata database URL, Redis database URL and the admin secret
Edit hasura-fargate-task.json
and set the right values:
---
{
"environment": [
{
"name": "HASURA_GRAPHQL_METADATA_DATABASE_URL",
"value": "postgres://<username>:<password>@hostname:<port>/<dbname>"
},
{
"name": "HASURA_GRAPHQL_REDIS_URL",
"value": "redis://hostname:6379"
},
{
"name": "HASURA_GRAPHQL_RATE_LIMIT_REDIS_URL",
"value": "redis://hostname:6379"
},
{
"name": "HASURA_GRAPHQL_ADMIN_SECRET",
"value": "myadminsecretkey"
}
]
}
Examples of HASURA_GRAPHQL_METADATA_DATABASE_URL
:
postgres://admin:[email protected]:5432/my_db
postgres://admin:@db-name.region.rds.amazonaws.com:5432/my_db
(if there is no password)
Examples of HASURA_GRAPHQL_REDIS_URL
and HASURA_GRAPHQL_RATE_LIMIT_REDIS_URL
:
redis://admin:[email protected]:6379
redis://db-name.region.cache.amazonaws.com:6379
(if there is no password)
If your password contains special characters (e.g. #, %, $, @, etc.), you need to URL encode them in the
HASURA_GRAPHQL_METADATA_DATABASE_URL
env var (e.g. %40 for @).The Hasura GraphQL Engine needs access permissions on your Postgres database as described in Postgres permissions.
The
HASURA_GRAPHQL_ADMIN_SECRET
should never be passed from the client to the Hasura GraphQL Engine as it would give the client full admin rights to your Hasura instance. See Authentication & Authorization for information on setting up authentication.Convert confidential environment variables such as Postgres / Redis URLs, admin / metrics secrets to fetch from secrets, see here for more information.
Configure logging and monitoring for your Hasura graphql engine instance, see here for more information.
For AWS users deploying Hasura behind a load balancer, note that the HTTP server used by Hasura has a fixed 30-second
keep-alive timeout. If your load balancer's idle timeout exceeds 30 seconds, it might cause intermittent
502 Bad Gateway
errors as the load balancer could attempt to reuse connections that have already been closed by
Hasura.
Workaround: Set the idle timeout of your load balancer to be less than 30 seconds (e.g., 29 seconds) to prevent this issue. This solution has been verified for AWS environments, but no equivalent workaround has been confirmed for GCP or Azure.
Step 4: Set up a license key
If you don't have a license key, you can skip this step and proceed with this guide to set up Hasura. Once you have the Hasura up and running, you can sign up for a free 30 day Enterprise Edition trial from the Hasura console.
If you have been provided a license key by the Hasura team, add it as an environment variable to Hasura. Edit
hasura-fargate-task.json
and set the license key as the value for HASURA_GRAPHQL_EE_LICENSE_KEY environment variable.
---
{
"environment": [
{
"name": "HASURA_GRAPHQL_METADATA_DATABASE_URL",
"value": "postgres://<username>:<password>@hostname:<port>/<dbname>"
},
{
"name": "HASURA_GRAPHQL_REDIS_URL",
"value": "redis://hostname:6379"
},
{
"name": "HASURA_GRAPHQL_RATE_LIMIT_REDIS_URL",
"value": "redis://hostname:6379"
},
{
"name": "HASURA_GRAPHQL_ADMIN_SECRET",
"value": "myadminsecretkey"
},
{
"name": "HASURA_GRAPHQL_EE_LICENSE_KEY",
"value": "<license key>"
}
]
}
Step 5: Register the Task Definition
aws ecs register-task-definition --cli-input-json file://hasura-fargate-task.json
Step 6: List Task Definitions
You can list the task definitions for your account at any time with the list-task-definitions command. The output of
this command shows the family
and revision
values that you can use together when calling run-task or
start-task or create-service or update-service.
aws ecs list-task-definitions
Output:
{
"taskDefinitionArns": ["arn:aws:ecs:region:aws_account_id:task-definition/hasura:1"]
}
Step 7: Create a Service
After you have registered a task for your account, you can create a service for the registered task in your cluster. For
this example, you create a service with one instance of the hasura:1
task definition running in your cluster.
The task requires a route to the internet, so there are two ways you can achieve this. One way is to use a private subnet configured with a NAT gateway with an elastic IP address in a public subnet. Another way is to use a public subnet and assign a public IP address to your task. We provide both examples below.
Substitute subnets and security groups in the below commands:
Example using a private subnet:
aws ecs create-service \
--cluster hasura-fargate-cluster \
--service-name hasura-fargate-service \
--task-definition hasura:1 \
--desired-count 1 \
--launch-type "FARGATE" \
--network-configuration "awsvpcConfiguration={subnets=[subnet-abcd1234],securityGroups=[sg-abcd1234]}"
Example using a public subnet:
aws ecs create-service \
--cluster hasura-fargate-cluster \
--service-name hasura-fargate-service \
--task-definition hasura:1 \
--desired-count 1 \
--launch-type "FARGATE" \
--network-configuration "awsvpcConfiguration={subnets=[subnet-abcd1234],securityGroups=[sg-abcd1234],assignPublicIp=ENABLED}"
The create-service command returns a description of the task definition after it completes its registration.
Step 8: Describe the Running Service
Describe the service using the service name retrieved earlier to get more information about the task.
aws ecs describe-services --cluster hasura-fargate-cluster --services hasura-fargate-service
If successful, this will return a description of the service failures and services. For example, in the services section, you will find information on deployments, such as the status of the tasks as running or pending.
You may also find information on the task definition, the network configuration and time-stamped events. In the failures section, you will find information on failures, if any, associated with the call. For troubleshooting, see Service Event Messages.
Step 9: Open the Hasura Console
Copy the task id from the previous step and describe the task in the service so that you can get the Elastic Network Interface (ENI) for the task.
Describe the task and locate the ENI ID.
aws ecs describe-tasks --cluster hasura-fargate-cluster --tasks <task-id-here>
The attachment information is listed in the output
{
"tasks": [
{
"attachments": [
{
"id": "d9e7735a-16aa-4128-bc7a-b2d5115029e9",
"type": "ElasticNetworkInterface",
"status": "ATTACHED",
"details": [
{
"name": "subnetId",
"value": "subnetabcd1234"
},
{
"name": "networkInterfaceId",
"value": "eni-0fa40520aeEXAMPLE"
},
]
}
…
}
Copy the ENI from the above describe-tasks output. Describe the ENI to get the public IP address.
aws ec2 describe-network-interfaces --network-interface-id eni-0fa40520aeEXAMPLE
The public IP address is in the output.
{
"NetworkInterfaces": [
{
"Association": {
"IpOwnerId": "amazon",
"PublicDnsName": "ec2-34-229-42-222.compute-1.amazonaws.com",
"PublicIp": "198.51.100.2"
},
…
}
Enter the public IP address in your web browser and you should see a webpage that displays the Hasura GraphQL Engine console.
Updating Hasura GraphQL Engine
This guide will help you update the Hasura GraphQL Engine running on ECS. This guide assumes that you already have the Hasura GraphQL Engine running on ECS.
Step 1: Check the latest release version
The current latest version is:
hasura/graphql-engine:v2.3.0
All the versions can be found at: https://github.com/hasura/graphql-engine/releases.
Step 2: Update the container image
In the hasura-fargate-task.json
file, update the image tag to this latest version.
For example, if you had:
"containerDefinitions": [
{
"image": "hasura/graphql-engine:v2.0.1",
...
}
you should change it to:
"image": "hasura/graphql-engine:v2.3.0",
Step 3: Roll out the change
Register the updated task definition and copy the taskDefinitionArn
revision number:
aws ecs register-task-definition --cli-input-json file://hasura-fargate-task.json
{
"taskDefinition": {
"taskDefinitionArn": "arn:aws:ecs:region:aws_account_id:task-definition/hasura:7",
aws ecs update-service --cluster hasura-fargate-cluster --service hasura-fargate-service --task-definition hasura:7
If you are downgrading to an older version of the GraphQL Engine, you might need to downgrade your Metadata catalogue version as described in Downgrading Hasura GraphQL Engine.