{{announcement.body}}
{{announcement.title}}

A Cloud-Native Starter Kit

DZone 's Guide to

A Cloud-Native Starter Kit

For those thinking of starting with cloud native, here's a quick starting guide to help you do so.

· Cloud Zone ·
Free Resource

I have drawn my inspiration from articles published on this subject. While I was learning, I had to move around a bit to make sure I have the setup right, the steps, and the small workarounds in place. This article summarizes all of that in one place, shows the steps with screenshots and console outout. Hope this will be of some help!

Setup

Install Minikube locally. Details available https://kubernetes.io/docs/tasks/tools/install-minikube/

I downloaded the minikube installer exe and ran locally on Windows 10 Home, also installed kubectl 1.18.0 and enabled Hyper V

Important commands:

  • ‘kubectl version –client’
  • ‘minikube start --driver=hyperv’ (next time, we can only use ‘minikube start’ )

When we run the command for the first time, we will see the VMs getting created (1 for the Control Plane, 1 worker node, memory allocation of 2 GB each and a virtual disk space of 20 GB)

‘minikube status’ - output below

Shell
 




x
13


 
1
C:\windows\system32>minikube status
2
 
          
3
minikube
4
 
          
5
type: Control Plane
6
 
          
7
host: Running
8
 
          
9
kubelet: Running
10
 
          
11
apiserver: Running
12
 
          
13
kubeconfig: Configured


‘minikube dashboard’..output below

Opens the dashboard with default settings on Node, Services, Storage, Cluster Roles, Namespaces

Dashboard

Install Docker Desktop for Windows 10 (Professional or Enterprise based on our home PC. OS). Do not try the hacks of making it work for Windows 10 Home as the results may be unpredictable. Instead install Docker toolbox, which works with Windows 10 Home. (https://docs.docker.com/toolbox/toolbox_install_windows/), download the latest 19.03.1. After installing Docker Toolbox, from the desktop icon, right-click and ‘Run as Administrator’. It will open the terminal, run the initial setup, and gives you the default command prompt for you to run the docker commands

Docker toolbox

At the time of start, you might get an error that says that there is a VirtualBox error check that failed. All you need to do is the following:

  • Open file C:\Program Files\Docker Toolbox\start and look for “STEP="Checking if machine $VM exists".
  • In the last line of that IF block, where you see the below line, add the check(highlighted in BOLD). This means that this check will be bypassed and the hyper-v will be used as the default driver 

          

Shell
 




xxxxxxxxxx
1


 
1
"${DOCKER_MACHINE}" create -d virtualbox --virtualbox-no-vtx-check $PROXY_ENV "${VM}"


If there is a problem in startup (next time you open) with the message about certificate error/cannot reach server, you can do the following. 

  • Run “docker-machine ls”  to list the machine
  • “docker-machine rm -f default” – to remove the machine
  • Recreate through “docker-machine create -d virtualbox default”
  • Close the session and re-open

Important Commands to Check the Installation

  • ‘docker-machine version’
  • ‘docker run hello-world’ (to test if the docker toolbox is installed properly)
  • ‘docker-machine ls’ (will list the virtual box that is running the docker).
  • $ docker-machine ls
Plain Text
 




xxxxxxxxxx
1


 
1
NAME      ACTIVE    DRIVER       STATE     URL                         SWARM   DOCKER       ERRORS
2
 
          
3
default   *         virtualbox   Running   tcp://192.168.99.102:2376           v19.03.12


Code Setup and Testing the Above Configuration:

You will find details at the link https://nodejs.org/de/docs/guides/nodejs-docker-webapp/

Write a simple Node.js program:

JavaScript
 




xxxxxxxxxx
1
33


 
1
var express = require("express");
2
//var cors = require("cors");
3
 
          
4
var app = express();
5
//app.use(cors())
6
//CORS Middleware
7
// Add headers
8
app.use(function (req, res, next) {
9
    // Website you wish to allow to connect
10
    res.setHeader('Access-Control-Allow-Origin', '*');
11
    // Request methods you wish to allow
12
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
13
    // Request headers you wish to allow
14
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
15
    // Set to true if you need the website to include cookies in the requests sent
16
    // to the API (e.g. in case you use sessions)
17
    res.setHeader('Access-Control-Allow-Credentials', true);
18
    // Pass to next layer of middleware
19
    next();
20
});
21
 
          
22
app.get("/", function (req, res) {
23
    res.send("Rudranil's first Node.js application is working well and still strongerrrr")
24
}
25
)
26
 
          
27
var server = app.listen(8081, function () {
28
 
          
29
    var host = server.address().address
30
    var port = server.address().port
31
}
32
)
33
 
          


In the folder structure you created for your node program, create a Docker file.

Docker file

DockerFile: (the usual commands you would run, if you were to run it locally, which is download node runtime, installing npm package dependencies, copying main JS file, opening listening port, running command ‘node app.js’

Dockerfile
 




xxxxxxxxxx
1


 
1
FROM node:12
2
# Create app directory
3
WORKDIR /usr/src/app
4
COPY package*.json ./
5
RUN npm install
6
COPY . .
7
EXPOSE 8081
8
CMD [ "node", "app.js" ]
9
 
          


You will also add the folders/files that you don’t want to be included in the final build in .dockkerignore (e.g node_modules as we are running command ‘npm install’ to download dependencies anyway)

Run the docker commands for Build and Run now

Shell
 




xxxxxxxxxx
1


 
1
docker build -t rudra1/node-js-sample1 .


If you run ‘docker images’, you will see the new image.

Docker images

Shell
 




xxxxxxxxxx
1


1
docker run -p <machine-port>:<container_port> -d rudra1/node-js-sample1


49062 mapped to 8081

So we have now 49062 mapped to 8081. We have to get the IP address of the Docker toolbox virtual machine.

Docker VM

Run the curl command to test it or through your browser.

Curl command

Now that we have tested the Node program, let’s see how it can be tested from an Angular app (to give you the end-end full stack flow)

We already have the URL to the application in the container now: http://192.168.99.102:40962

Angular application: I am not going into the details of Angular as you can learn from the tutorials as I did. The HTTP call is being made in the lines highlighted in Yellow below

TypeScript
 




xxxxxxxxxx
1
63


 
1
import{ Component, OnInit } from '@angular/core';
2
import { HttpClient } from '@angular/common/http';
3
import { MyserviceService } from './../myservice.service';
4
import { Observable } from 'rxjs';
5
import { FormGroup, FormControl } from '@angular/forms';
6
 
          
7
@Component({
8
  selector: 'app-new-component',
9
  templateUrl: './new-component.component.html',
10
  styleUrls: ['./new-component.component.css']
11
})
12
export class NewComponentComponent implements OnInit {
13
  newComponent = "Rudranil's new component!"
14
  months = ["Jan", "Feb"];
15
  todaydate;
16
  httpdata;
17
  formdata;
18
  emailid;
19
  isavailable = true;
20
  constructor(private myservice: MyserviceService, private http: HttpClient) { console.log("sss");}
21
 
          
22
  ngOnInit(): void {
23
    console.log("Hello");
24
    this.todaydate = this.myservice.showTodayDate();
25
    console.log(this.todaydate);
26
    this.formdata = new FormGroup({
27
      emailid: new FormControl("default value")
28
    }
29
    );
30
    
31
 
          
32
this.getResponseFromServer().subscribe(data => {
33
      this.httpdata = data;
34
    });
35
  }
36
 
          
37
  getResponseFromServer(): Observable<any> {
38
    //return this.http.get("http://localhost:8081/", { responseType: 'text' });
39
    return this.http.get("http://192.168.99.102:40962", { responseType: 'text' });
40
 
          
41
  }
42
 
          
43
  showData(data) {
44
    console.log("Hi");
45
    console.log(data);
46
    //this.httpdata = JSON.stringify(data);
47
    this.httpdata = data;
48
  }
49
 
          
50
  onClickSubmit(data) {
51
    alert("Form data" + data.emailid);
52
    this.emailid = data.emailid;
53
  }
54
 
          
55
  myclickfunct(event) {
56
    alert("Button is clicked for Rudranil")
57
  }
58
 
          
59
  changeevent(event) {
60
    alert("Changed")
61
  }
62
}
63
 
          


After you start the Angular runtime and type the URL: http://localhost:4200/ you will see the response output of the node application. Enable Developer Tools console for debugging.

Dev Tools

Publishing the Image to The Minikube One Node Cluster

‘docker images’ command shows the images from local docker repository/environment. But when we run ‘kubectl create deployment node-sample1 –image=<image_tag>’, the image is pulled from the minikube repository and not from the local docker repo. So the command when executed will show an error on minikube dashboard that repository for the image cannot be found

You can look at https://medium.com/bb-tutorials-and-thoughts/how-to-use-own-local-doker-images-with-minikube-2c1ed0b0968  to see how the minikube can work with local docker images and don’t always have to pull from a central registry

a) C:\windows\system32>minikube docker-env (running the following command will give the below output)

  • SET DOCKER_TLS_VERIFY=1
  • SET DOCKER_HOST=tcp://172.17.246.60:2376
  • SET DOCKER_CERT_PATH=C:\Users\91983\.minikube\certs
  • SET MINIKUBE_ACTIVE_DOCKERD=minikube
  • REM To point your shell to minikube's docker-daemon, run:
  • REM @FOR /f "tokens=*" %i IN ('minikube -p minikube docker-env') DO @%i
  • b) Execute the last command to set the environment
  • @FOR /f "tokens=*" %i IN ('minikube -p minikube docker-env') DO @%i

c) Typing now command ‘docker images’ will show the images from the Docker daemon in the Minikube environment

Images in Minikube

d) Run the command ‘docker build -t rudra2/node- sample2.’ The image will be created in the minikube environment. If you run the ‘docker images’ command now, you will see the newly created image

New image

e) Run the command ‘kubectl create deployment node-sample1 –image=rudra2/node-sample-2’. The POD will be visible on the dashboard (but will have to disable the imagePullPolicy)

f) Edit the YAML file of the node from the Dashboard. Change to ‘imagePullPolicy:Never’ from ‘imagePullPolicy:Always’. This means that it will look in the local repo and not a remote repo. The deployments will change to GREEN from RED.

YAML file


Deployment

g) 

Second command

The service will expose the POD outside the cluster. Service will have a Cluster IP. The pods will also have unique IPs. Run the second command as shown above and your new service will be listed as shown below

New service


h) Run the command ‘minikube service node-sample1’

minikube service node-sample1

This command will open a browser and show the output

i) OR you can type the following URL: http://172.17.246.60:31058 The Host/Cluster Server IP 172.17.246.60 IP is visible in C:\Users\91983\.kube\config file. The IP could change when you stop/start your apiserver. But the IP will always be found in the kube\config file and also on the dashboard under Nodes->Internal IP Address.

This, they say is the primitive way of making the service accessible to the outside world. But if the Node IP changes, a new port will be assigned and we will have to change every calling application with the new port. This approach cannot be used in PROD. For learning purpose/POC/Demo, we can use.

 So the loadbalancer/ingress controller is the standard way of exposing a service

  • Run the command

          C:\windows\system32>minikube addons enable ingress

  • Verify the status by running the command Kubectl get pods -n kube-system 

Status


  •   Create the Ingress resource (YAML file)
YAML
 




xxxxxxxxxx
1
27


1
apiVersion: networking.k8s.io/v1beta1
2
 
          
3
kind: Ingress
4
 
          
5
metadata:
6
 
          
7
  name: example-ingress
8
 
          
9
  annotations:
10
 
          
11
     nginx.ingress.kubernetes.io/rewrite-target: /$1
12
 
          
13
spec:
14
 
          
15
  rules:
16
 
          
17
  - http:
18
 
          
19
      paths:
20
 
          
21
      - path: /
22
 
          
23
        backend:
24
 
          
25
           serviceName: node-sample1
26
 
          
27
           servicePort: 8081


  • Run the command “kubectl apply -f sample-ingress.yaml”  to create the Ingress resource (set of Rules)

ingress resource

  • “Minikube ip” will give the IP address to access.

IP address

  • http://<IP_Address_Above>/ will invoke the service
  • We can get public static IPs for long running applications. Public cloud providers can create public static IPs for use with the Ingress resource
  • Multiple rules can be setup on the ingress resource(pointing to multiple services) and serviced through the same loadbalancer

j) Scaling the application: You can see the internal structure (YAML) of Deployments/POD, Services from the dashboard. Every such object type will have a SPEC and STATUS

This is primarily done by changing the number of replicas

‘Kubectl get rs’ shows the number of replicas

replicas


New replicas can be configured either by running the kubectl command or we can edit the YAML file directly.

Edit yaml file

YAML File

On the Dashboard, we will see the 2 pods.

Pods

Running the image on a Kubernetes cluster on a hosted service (Azure cloud)

The basic steps would include the following. To start with, you can get the free account trial activated

a) Setting up the remote registry on Azure. We need a place to store the docker image so that the AKS can access that

I had some problems running from docker-toolbox. But it can be run from Docker. I installed Azure CLI for Windows, open a command prompt and executed the following commands

  • “az login” – it opened a browser, logged me in successfully, but gave me an error on the command prompt “No subscriptions found”

 Subscription Link is here. You can go for the free trial and give your card number to verify. You won’t be charged unless you upgrade. The amount we pay via the merchant site for the free trial is INR 2

 When you type “az login” now, you will get the following information in your command promptazlogin


Now if you go to the HOME link and Navigate to subscriptions, you will see the default subscription

default subscription

az group create --name dbiTestGroup --location southindia create group

Navigating to Home-Resource Groups will show the new entry

resource group

az acr create --resource-group dbiTestGroup --name dbiTestACR1 --sku Basic 

If you navigate to Home-All Resources, you will see the new entry

resources

b) Import the image into the Azure container registry

Login to the acr

az acr login --name dbiTestACR1 login

TAG a container image for ACR. The image needs to be tagged with the login server of the registry

az acr list --resource-group dbiTestGroup --query "[].{acrLoginServer:loginServer}" --output table Tag local image

TAG the local image to ACR

docker tag rudra2/node-sample-2 dbitestacr1.azurecr.io/node-sample-2

View the Image in the ACR

docker images” will show the new tag (third entry from the top)

new tag

Before pushing the image, we have to enable the Access Key, otherwise the ‘docker push…’ command will throw an Unauthorized Error in the end

access keys

Push the image to the Azure Container Registry

docker push dbitestacr1.azurecr.io/node-sample-2 push image

List the images in the Azure Container Registry

az acr repository list --name dbiTestACR1 --output table repo list

c) Build the AKS cluster and set up the application container

Shell
 




xxxxxxxxxx
1


 
1
az aks create   --resource-group dbiTestGroup   --name dbiTestCluster   --node-count 2 
2
 
          
3
     --generate-ssh-keys  --attach-acr dbiTestACR1


You might get this error

errorTo fix this, we have to add the extension aks-preview (as the issue is provided in the preview)

az extension add --name aks-preview extension

Run the command again to create the cluster and you should get a JSON output showing the cluster

Shell
 




xxxxxxxxxx
1


 
1
az aks create   --resource-group dbiTestGroup   --name dbiTestCluster   --node-count 2 --generate-ssh-keys   --attach-acr dbiTestACR1
2
 
          



 To connect kubectl to the Kubernetes cluster

Shell
 




xxxxxxxxxx
1


 
1
az aks get-credentials --resource-group dbiTestGroup --name dbiTestCluster
2
 
          



 To verify if kubectl is connected to the right AKS, run the command and we will see the details for the node on AKS.

kubectl get nodes

Create a YAML file with the following mappings/details to map the container. The YAML file is bigger than this, which will have the Deployment details.

containers:

- name: node-sample-2

  image: dbiTestACR1.azurecr.io/node-sample-2

 

Run the command kubectl apply -f <above_YAML_File> 

You can run “kubectl get service node-sample-2” for the IP

Details can be found in https://docs.microsoft.com/en-in/azure/aks/tutorial-kubernetes-deploy-application

Topics:
aws, cloud, cloud native, getting started, kubernetes, minikube, starter kit

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}