Skip to content

Step-By-Step Instructions To Deploy A Node.Js App To Kubernetes on EKS

Published: at 03:42 AM

You have this cool app you wrote in Node.js. You’re a great developer, and learned how to transform your app into a scalable app with ECS. However, the powers that be have decided that you need to use Kubernetes. and you understand the basic building blocks and have drawn the parallels with ECS, but you’re not sure how to go from code to app deployed in EKS.

We’re going to use the following AWS services:

Solution step by step

Note: The first steps of installing Docker and dockerizing the app are the same as the previous issue. I’m adding them in case you didn’t read it, but if you followed them last week, feel free to start from the 6th step, right after pushing the Docker image to ECR.

# Use the official Node.js image as the base image
FROM node:latest

# Set the working directory for the app
WORKDIR /app

# Copy package.json and package-lock.json into the container
COPY package*.json ./

# Install the app's dependencies
RUN npm ci

# Copy the app's source code into the container
COPY . .

# Expose the port your app listens on
EXPOSE 3000

# Start the app
CMD ["npm", "start"]
docker build -t cool-nodejs-app .
docker run -p 3000:3000 cool-nodejs-app
aws ecr create-repository --repository-name cool-nodejs-app
docker tag cool-nodejs-app:latest {AWSAccountId}.dkr.ecr.{AWSRegion}.amazonaws.com/cool-nodejs-app:latest
docker push {AWSAccountId}.dkr.ecr.{AWSRegion}.amazonaws.com/cool-nodejs-app:latest
Resources:
  EKSCluster:
    Type: AWS::EKS::Cluster
    Properties:
      Name: cool-nodejs-app-eks-cluster
      RoleArn: !GetAtt EKSClusterRole.Arn
      ResourcesVpcConfig:
        SubnetIds: [{SubnetIDs}]
        EndpointPrivateAccess: true
        EndpointPublicAccess: true
      Version: '1.22'

  EKSClusterRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: eks.amazonaws.com
            Action: sts:AssumeRole
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
        - arn:aws:iam::aws:policy/AmazonEKSServicePolicy

  EKSFargateProfile:
    Type: AWS::EKS::FargateProfile
    Properties:
      ClusterName: !Ref EKSCluster
      FargateProfileName: cool-nodejs-app-fargate-profile
      PodExecutionRoleArn: !GetAtt FargatePodExecutionRole.Arn
      Subnets: [{SubnetIDs}]
      Selectors:
        - Namespace: {Namespace}

  FargatePodExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: 'eks-fargate-pods.amazonaws.com'
            Action: 'sts:AssumeRole'
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKS_Fargate_PodExecutionRole_Policy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cool-nodejs-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cool-nodejs-app
  template:
    metadata:
      labels:
        app: cool-nodejs-app
    spec:
      containers:
        - name: cool-nodejs-app
          image: {AWSAccountId}.dkr.ecr.{AWSRegion}.amazonaws.com/cool-nodejs-app:latest
          ports:
            - containerPort: 3000
          resources:
            limits:
              cpu: 500m
              memory: 512Mi
            requests:
              cpu: 250m
              memory: 256Mi
      serviceAccountName: fargate-pod-execution-role

---

apiVersion: v1
kind: Service
metadata:
  name: cool-nodejs-app
spec:
  selector:
    app: cool-nodejs-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: cool-nodejs-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: cool-nodejs-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

Solution explanation

Best Practices

Operational Excellence

Security

Reliability

Performance Efficiency

Cost Optimization

Resources

Bad news: the cluster you created with eksctl or with my CloudFormation snippet is full of security holes. You should instead use this free tool to create an opinionated and very secure cluster. It’s so great I was on the verge of just using it on the solution step by step.

The official Kubernetes docs are great as a technical reference, but awful for learning. Instead, check out this workshop.

Instead of Horizontal Pod Autoscaler, check out Karpenter, which does a better job of managing resources.

To implement Network Policies, check out Calico. Here’s how to set it up.

Something new: this platform promises to make shipping applications more enjoyable. I haven’t tried it yet.