Build and deploy a simple Apollo GraphQL federated schema using AWS EKS (Kubernetes)-Pt.3

Ason @ Maison AM
5 min readJan 27, 2021

This tutorial is part 3 of this series.

In this section we’ll deploy our federated services into a kubernetes cluster managed by AWS EKS, our application containers will be rolled out with AWS Fargate 🚀.

Why AWS EKS Kubernetes service & AWS Fargate?

From an architectural standpoint, consider our original diagram from the first tutorial, where we have several interlinked applications. To deploy the application to individual servers we would have to provision several servers, manage the scaling, patching and security then deep dive into the networking of said servers.

With AWS EKS managed Kubernetes we can deploy all of our applications into one cluster that manages networking, horizontal and vertical scaling, patching and security between the applications. By leveraging AWS Fargate we can deploy our cluster applications into on-demand, right-sized, serverless compute containers, which provide improved security through application isolation, removes the need to provision and manage servers and we only pay for the application resources we use.

Architecture recap:

Apollo federated schema architecture

To expose our Apollo gateway services publicly we’ll create an application load balancer and point it to the Gateway. This will be the only service exposed publicly, which limits our attack vectors and improves security. The other services will only be assigned cluster IPs for internal networking.

Prerequisites

Open your terminal, navigate to the /kubernetes directory, and follow the steps below:

Create the cluster and policies

  1. Create the cluster (approx. 15mins)
eksctl create cluster --name apollo-federation-eks --version 1.16 --fargate

2. Allow the cluster to use AWS Identity and Access Management (IAM) for service accounts

eksctl utils associate-iam-oidc-provider --cluster apollo-federation-eks --approve

3. Create an IAM policy for the service account and copy the “Arn”

aws iam create-policy --policy-name ALBIngressIAMPolicy --policy-document file://alb-ingress-iam-policy.json

4. Create a service account

eksctl create iamserviceaccount --name apollo-service-account --namespace kube-system --cluster apollo-federation-eks --attach-policy-arn *paste copied "Arn" here* --approve --override-existing-serviceaccounts

5. Verify service account role creation and copy the service account role ARN that’s output

eksctl get iamserviceaccount --cluster apollo-federation-eks --name apollo-service-account --namespace kube-system

6. Open the /kubernetes/rbac-role.yaml file in a text editor, then paste the service account role ARN as the value for the ‘eks.amazonaws.com/role-arn:’ property.

7. Save the rbac-role.yaml file, then run the following command in your terminal:

kubectl apply -f rbac-role.yaml

Set up the ALB Ingress Controller

Next we’ll run the ALB Ingress Controller as a Fargate pod.

  1. Open /kubernetes/alb-ingress-controller.yaml in your text editor and make the following amendments:
  • Verify and copy your VPC ID output
aws eks describe-cluster --name apollo-federation-eks --query “cluster.resourcesVpcConfig.vpcId” --output text
  • Add your VPC ID value to the attribute ‘- — aws-vpc-id=’
  • Add your pre-configurred region value to the attribute ‘- — aws-region=’
  • Add your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY under the ‘env:’ section where instructed. In production we’d create a role instead!

2. Run the following command to deploy the ingress controller

kubectl apply -f alb-ingress-controller.yaml

Deploy the application containers

  1. Create a Fargate profile
eksctl create fargateprofile --namespace apollo-federation-dev --cluster apollo-federation-eks --name apollo-federation-profile

2. Setup the above namespace in Kubernetes

kubectl apply -f namespace.yaml

3. Switch to the /kubernetes/deployment directory and open the /cryptocurrency-api.yaml file in your editor.

Paste in your Coinmarketcap api as an env variable. In production we would handle secrets in a more secure way.

Then save the file and run the following block of code to create a Fargate deployment container for each application

kubectl apply -f user-api.yamlkubectl apply -f cryptocurrency-api.yamlkubectl apply -f wallet-api.yaml

4. Switch to the /kubernetes/service directory and run the following block to create a service for each application

kubectl apply -f user-api.yamlkubectl apply -f cryptocurrency-api.yamlkubectl apply -f wallet-api.yaml

5. Check the progress of the deployments and wait for them to be in the ‘Running’ state by running the following block

kubectl -n apollo-federation-dev rollout status -w deployment user-api-deploymentkubectl -n apollo-federation-dev rollout status -w deployment wallet-api-deploymentkubectl -n apollo-federation-dev rollout status -w deployment cryptocurrency-api-deployment

6. Once all pods are “successfully rolled out”, switch to the /kubernetes/deployment directory and run the following block to create a Fargate deployment container for the gateway

kubectl apply -f gateway-api.yaml

switch to the /kubernetes/service directory and run the following block to create a service for the gateway

kubectl apply -f gateway-api.yamlkubectl -n apollo-federation-dev rollout status -w deployment gateway-api-deployment

7. Once the Gateway-api pod is running, we’ll deploy our ingress controller and start the application load balancer. Our ingress is responsible for routing HTTP/S requests to the application services. Switch to the /kubernetes/ingress directory and run the following

kubectl apply -f apollo-ingress.yaml

Log into the AWS Console and navigate to the EC2 service, then open the ‘Load Balancers’ page to see the status of the load balancer we just created. Then navigate to the ‘Target groups’ page, and open the ‘Targets’ tab to watch the registration of the Gateway service with the load balancer’s target group. Once the status has changed to ‘unhealthy’ we’re ready to test our deployment. (note. it’s only in the unhealthy state because we haven’t created health checks)

Test our deployed application

  1. Get the load balancer DNS name
kubectl get ingress/apollo-ingress -n apollo-federation-dev

2. Open Postman and create a new POST request (set the body type to GraphQL) using the following data

  • URL: http://*YOUR DNS ADDRESS*/graphql
  • Paste the Query and Query variables below

Your response will contain user data resolved from the applications in the cluster and externally retrieved data 🚀👨‍💻

Teardown:

Run the following commands to delete all resources!

/deployments & /services
kubectl delete -f user-api.yaml
kubectl delete -f cryptocurrency-api.yaml
kubectl delete -f wallet-api.yaml
kubectl delete -f gateway-api.yaml
/ingress
kubectl delete -f apollo-ingress.yaml
eksctl delete fargateprofile --name apollo-federation-profile \ --cluster apollo-federation-ekseksctl delete cluster apollo-federation-eks --wait

In the next series, we’ll explore how to create a fully production ready version of the federated schema using NestJs, Typescript, Apollo Managed schemas and Terraform to manage our Kubernetes deployment and secrets.

--

--