Thursday, July 8, 2021

AWS : NodeJS : Hello World on EC2

 Although I have an account in AWS for over a decade, I really did not do much with it other than launching a EC2 instance and then say print Hello World.

A decade has passed and now AWS has caught up with me professionally so need to build come competencies around it.

First is to get the the Hello world back again using Node on a Web Page.

Assumptions:

  1. You have a AWS account. I am using the free tier one.
  2. Have basic understanding of Node
  3. Have basic understanding of AWS specially EC2, VPC and ACLs.

Steps:
  1. Go to EC2. Select "Amazon Linux 2 AMI (HVM), SSD Volume Type" of type "t2.micro" and launch it. 

  2. You will get a public key .pem file. Keep it safely.

  3. On Windows, you will need to set the permissions of the file correctly to mimic chmod 400 of linux:
    1. icacls.exe key.pem /reset
    2. icacls.exe key.pem /grant:r "$($env:username):(r)"
    3. icacls.exe key.pem /inheritance:r

  4. Go to Security Group and Edit Inbound rule to allow:
    1. SSH (port 22) from anywhere
    2. HTTP (port 3000) from anywhere

      This will allow you to connect to the EC2 instance from your local laptop as well as browse the Hello World node site in there.

  5. Coming back to EC2 dashboard, you should see 1 Instance running

  6. You should be able to connect to it using SSH client and see the welcome logo:
           __|  __|_  )
           __|  __|_  )
           _|  (     /   Amazon Linux 2 AMI
          ___|\___|___|
    https://aws.amazon.com/amazon-linux-2/

  7. Now that you have a shell access to your EC2 instance, lets install Node JS.

  8. We will use nvm for it.

  9. curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash

  10. Activate nvm using simply bash or . ~/.nvm/nvm.sh

  11. nvm install node

  12. check node installed:
    node -v
    v16.4.2

  13. Now let just start a simple Express web app
    mkdir myapp
    cd myapp
    npm init (and just enter till the end)
    npm install express --save
    vi app.js
    const express = require('express')
    const app = express()
    const port = 3000

    app.get('/', (req, res) => {
      res.send('Hello World!')
    })

    app.listen(port, () => {
      console.log(`Example app listening at http://localhost:${port}`)
     
    })
  14. node app.js
    Example app listening at http://localhost:3000
  15. So our web app is up are running on 3000 but its still within the EC2 instance. To be able to access it from the internet, we need to modify the security group of the EC2 instance to allow the port 3000 be exposed. This has been done in Step 2.

  16. So access the web app using the public IP or hostname of the EC2 instance. Note to use http:// and not https:// and append the port 3000 at the end. It should show up as :

    Hello World!
Thats all for today. Next we will connect the mighty Database :)

Wednesday, April 14, 2021

Kubernetes : Getting started on Windows

I had setup Kubernetes on local laptop and had tried a few things 2-3 years back. In the meantime the laptop got replaced and recently got some work around it. So it was time to set it up again.

I found that Docker Desktop does now support Kubernetes so thought it will be pretty easy to get up back again. So went to Docker Desktop -> Settings -> Kubernetes and selected Enable Kubernetes. In a few minutes it got enabled and on the command prompt I got kubectl. Wow, its all done.

Now the problems started.

First, when I executed kubectl version, I did get the client version but for the server version I got:

kubectl unable to connect to server: x509: certificate signed by unknown authority

So spent quite a few hours trying to work this out. There is enough documentation on the web but nothing specific to docker desktop. So despite the trials and errors, it did not work so abandoned it and went back to my earlier trusty minikube.

First had to remove Kubernetes from Docker Desktop but it was not allowing me to do it !!. So had to uninstall the whole of Docker Desktop.

Then installed the following using Chocolatey:

  1. Install kubectl : choco install kubernetes-cli
  2. Install Minikube : choco install minikube
Then installed Docker Desktop as well as had uninstalled it earlier.

All done, lets check all things are fine:

  1. Start the cluster : minikube start
  2. Check kubectl : kubectl version

    Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"windows/amd64"}
    Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:20:00Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}

  3. Check cluster : kubectl cluster-info

    Kubernetes control plane is running at https://127.0.0.1:61152
    KubeDNS is running at https://127.0.0.1:61152/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

  4. All good, lets start the dashboard : minikube dashboard

    * Enabling dashboard ...
      - Using image kubernetesui/dashboard:v2.1.0
      - Using image kubernetesui/metrics-scraper:v1.0.4
    * Verifying dashboard health ...
    * Launching proxy ...
    * Verifying proxy health ...
    * Opening http://127.0.0.1:60036/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

    Open the browser and view the brand new Kubernetes cluster in all its glory :)

So we have our K8 cluster setup. Lets start some sample applications just to test it out and revise some of the old stuff. So I tried to setup nginx as will be working on application which will have a HTTP interface.

So first create the nginx.yml file for the deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx

and apply it on the K8 cluster : 

> kubectl apply -f nginx.yml
deployment.apps/nginx created

Go to the MiniKube dashboard and under deployments, you will find:


 Under Pods, you will find:


The equivalent command line will be 
  • kubectl get deployments
  • kubectl get pods

So all good, we have deployed nginx which is running in a container within pod. Still we need to expose nginx on a port in the container so that it is accessible. Update the yaml file to:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
          name: nginx

and apply it : kubectl apply -f nginx.yml

So now we have set port 80 where it will receive the request and forward it to nginx. Still this port is exposed within the K8 cluster and not to outer world. To expose it to outer world or host, we need to create a service which will do so. 

So create the nginx_service.yml as:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      targetPort: 80
      port: 8082

and apply it :
>kubectl apply -f nginx_service.yml
service/nginx created

In the minikube dashboard, you will find:

As you can well see that it was exposed the port 8082 for the app: nginx

Now you can check it on your local browser : http://localhost:8082 or http://127.0.0.1:8082/

All good. Now get will app development and deployment on K8 cluster :)