Full Stack App Automated deployment on AWS EKS

Full Stack Application on AWS EKS
This example automatically deploys a full-stack application with Kubernetes on AWS using their managed control plane called Elastic Kubernetes Service
Automation is performed with GruCloud, which is an infrastructure as code tool written in Javascript.
High-level description
This infrastructure combines 2 providers: AWS and Kubernetes.
A few modules for each of these providers are being used:
In this example, the load balancer, target groups, listeners, and rules are managed by GruCloud instead of the AWS Load Balancer Controller.
The benefit of not using the LBC is to free a lot of resources, the LBC depends on the Cert Manager which brings more resources,
By not using the AWS LBC and the Cert Manager, we can save 4 pods, and numerous other resources such as ServiceAcount, ClusterRole, ClusterRoleBinding, we can even get rid of the CRD stuff.
Fewer pods mean we can choose a cheaper worker node.
Modules for AWS resources
Modules for K8s resources
The local module defining the app on the k8s side is located at base.
There is no trace of manifests in YAML, instead, Kubernetes manifests are described in Javascript, allowing the use of variables, conditionals, loops, importing code, and even the use of a debugger. Therefore, GruCloud is an alternative to helm.
Resources
From the infrastructure code, 2 kinds of visual representation can be generated with the GruCloud CLI gc:
  • a mind map indicating the type of the resource: gc tree
  • a diagram showing the relationship between the resources: gc graph
  • Mindmap
    Diagram
    The following diagram shows the AWS and K8s resources and their relashionship:
    Workflow
    The next flowchart tells the actions to perform to configure, deploy, update and destroy this infrastructure:
    Requirements
    AWS CLI
    GruCloud CLI:
    Getting the source code

    This example is located at examples/starhackit/eks-lean

    Configuration
    Amazon EKS
    The first part of this deployment is to create an EKS control plane, a node group for the workers, and all their numerous dependencies.
    Configuration for the AWS resources is located at configAws.js
    Set the rootDomainName and domainName according to your use case

    For end-to-end automation, the rootDomainName should be registered or transferred to the AWS Route53 service.

    K8s
    The second part is the Kubernetes deployment of the full-stack application composed of a React front end, a Node backend, Postgres as the SQL database, and finally Redis for the cache and published/subscriber models.
    Configuration for the K8s resources is located at configK8s.js

    When the backend container is changed to another backend, do not forget to change the target group health check in configAWS.js

    GruCloud workflow
    This chart depicts the workflow with the main gc commands:
  • gc info
  • gc graph
  • gc apply
  • gc list
  • gc destroy
  • Listing
    Let's find out if everything is set up properly by listing the live resources from AWS:
    gc list
    Listing resources on 2 providers: aws, k8s
    ✓ aws
      ✓ Initialising
      ✓ Listing 29/29
    k8s
      Initialising
      Listing 0/8
    List Summary:
    Provider: aws
    ┌───────────────────────────────────────────────────────────────────────────────────────────────┐
    │ aws                                                                                           │
    ├────────────────────┬──────────────────────────────────────────────────────────────────────────┤
    │ IamPolicy          │ AmazonEKSClusterPolicy                                                   │
    │                    │ AmazonEKSVPCResourceController                                           │
    │                    │ AmazonEKSWorkerNodePolicy                                                │
    │                    │ AmazonEC2ContainerRegistryReadOnly                                       │
    │                    │ AmazonEKS_CNI_Policy                                                     │
    ├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
    │ Route53Domain      │ grucloud.org                                                             │
    ├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
    │ Vpc                │ default                                                                  │
    ├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
    │ InternetGateway    │ igw-9c2f1ae7                                                             │
    ├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
    │ SecurityGroup      │ default                                                                  │
    ├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
    │ Subnet             │ default                                                                  │
    │                    │ default                                                                  │
    │                    │ default                                                                  │
    │                    │ default                                                                  │
    │                    │ default                                                                  │
    │                    │ default                                                                  │
    ├────────────────────┼──────────────────────────────────────────────────────────────────────────┤
    │ RouteTable         │ rtb-19753867                                                             │
    └────────────────────┴──────────────────────────────────────────────────────────────────────────┘
    19 resources, 8 types, 1 provider
    Command "gc l" executed in 5s
    Note the presence of a default VPC, subnets, security group, and internet gateway.

    Verify that the domain name is registered with Route53Domain, in this case, grucloud.org

    The Kubernetes control created by EKS is not up yet, as a consequence, listing the k8s resources cannot be retrieved at this stage.
    Deploying
    It is show time for deploying all the AWS and Kubernetes resources in one command:
    gc apply
    The app should be now running with Kubernetes on AWS after 15 minutes.
    When all the resources are created, custom code can be invoked in hook.js.
    In this example, we verify access to the webserver and the API server securely.
    The kubeconfig has been updated with the endpoint from the EKS cluster.
    kubectl config current-context
    arn:aws:eks:eu-west-2:999541460000:cluster/cluster
    Let's list and produce a diagram of the AWS resources freshly created:
    gc list -p aws --graph -a --default-exclude --types-exclude Certificate --types-exclude Route53Domain --types-exclude NetworkInterface
    Notice that the NodeGroup has created an AutoScaling Group, which in turn creates EC2 instances, instance profiles, and volumes.
    Updating
    Let's update the cluster with another version of the front end.
    Edit configK8s.js and change the frontend version.
    The gc apply command will find out the difference between the expected version and the deployed version.
    Querying resources on 2 providers: aws, k8s
    ✓ aws
      ✓ Initialising
      ✓ Listing 30/30
      ✓ Querying
        ✓ HostedZone 1/1
        ✓ Certificate 1/1
        ✓ Route53Record 2/2
        ✓ Vpc 1/1
        ✓ InternetGateway 1/1
        ✓ Subnet 4/4
        ✓ RouteTable 3/3
        ✓ Route 3/3
        ✓ ElasticIpAddress 1/1
        ✓ NatGateway 1/1
        ✓ IamRole 2/2
        SecurityGroup 3/4
        ✓ SecurityGroupRuleIngress 6/6
        ✓ SecurityGroupRuleEgress 1/1
        ✓ KmsKey 1/1
        ✓ EKSCluster 1/1
        ✓ EKSNodeGroup 1/1
        ✓ LoadBalancer 1/1
        ✓ TargetGroup 2/2
        ✓ Listener 2/2
        ✓ Rule 3/3
    ✓ k8s
      ✓ Initialising
      ✓ Listing 8/8
      ✓ Querying
        ✓ Namespace 1/1
        ✓ ConfigMap 2/2
        ✓ StatefulSet 2/2
        ✓ Service 4/4
        ✓ Deployment 2/2
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │ 1 Deployment from k8s                                                                              │
    ├────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │ ┌───────────────────────────────────────────────────────────────────────────────────────────────┐  │
    │ │ UPDATE: name: default::web, id: web                                                           │  │
    │ ├───────────────────────────────────────────────────────────────────────────────────────────────┤  │
    │ │ Key: spec                                                                                     │  │
    │ ├───────────────────────────────────────────────┬───────────────────────────────────────────────┤  │
    │ │ - template:                                   │ + template:                                   │  │
    │ │   spec:                                       │   spec:                                       │  │
    │ │     containers:                               │     containers:                               │  │
    │ │       0:                                      │       0:                                      │  │
    │ │         image: fredericheem/ui:v10.14.0       │         image: fredericheem/ui:v10.15.0       │  │
    │ │                                               │                                               │  │
    │ └───────────────────────────────────────────────┴───────────────────────────────────────────────┘  │
    └────────────────────────────────────────────────────────────────────────────────────────────────────┘
    
    
    ┌─────────────────────────────────────────────────────────────────────────────────────────────┐
    │ Plan summary for provider aws                                                               │
    └─────────────────────────────────────────────────────────────────────────────────────────────┘
    ┌─────────────────────────────────────────────────────────────────────────────────────────────┐
    │ Plan summary for provider k8s                                                               │
    ├─────────────────────────────────────────────────────────────────────────────────────────────┤
    │ DEPLOY RESOURCES                                                                            │
    ├────────────────────┬────────────────────────────────────────────────────────────────────────┤
    │ Deployment         │ default::web                                                           │
    └────────────────────┴────────────────────────────────────────────────────────────────────────┘
    ? Are you sure to deploy 1 resource, 1 type on 1 provider? › (y/N)
    It is the equivalent of kubectl apply, except that kubectl is "fire and forget", but gc apply the changes and waits for the resources to be ready before returning.
    Destroying
    Running Kubernetes cluster on AWS or other cloud providers is not cheap. Stop paying when the cluster is not used with one command:
    gc destroy
    Resources will be destroyed in the right order and automatically.
    Links

    23

    This website collects cookies to deliver better user experience

    Full Stack App Automated deployment on AWS EKS