Build Your First Kubernetes Service with ReplicaSet

JiaMin Ning
6 min readAug 3, 2018

--

Kubernetes is an open-source system for DevOps. It provides bundles of API to manage docker containers. In this blog, I will walk through the steps from beginning of create docker image to exposing a service in Kubernetes cluster to show you how to set up a basic Kubernetes cluster.

0. Prequest

1. Build your first docker image

To begin with, create an Express app first. Create a folder called /kubernetes_experiments and in that folder run

npm init && npm i express --save

you can type enter for the coming questions in your console. Next, create a file called app.js. The app.js will provide us with API to get the hostname of a working server. Type or copy the following code to the file

const express = require('express');
const os = require('os');
const app = express();
app.post('/getHostName', (req, res) => {
res.writeHead(200);
res.end("Hostname is: " + os.hostname());
})
app.listen(8081, () => {});

Now, we have an Express app that listen to port 8081 and are ready to build our docker image. Then, we are going to build our Docker image with Dockerfile. Create a file called Dockerfile in /kubernetes_experiments and type or copy the following code to the Dockerfile

FROM node:8WORKDIR /usr/src/appCOPY package*.json ./RUN npm install
COPY . .
EXPOSE 8081
CMD [ "npm", "start" ]
  • FROM node: 8 create a layer from node:8 docker image
  • WORKDIR /usr/src/app set the work directory to /usr/src/app in docker image
  • COPY package*.json ./ copy package.json and package-lock.json to /usr/src/app
  • RUN npm install install node modules in docker image
  • COPY . . copy the remain files to /usr/src/app
  • EXPOSE 8081 document port 8081 for use for docker image (EXPOSE command is just to document the port not to open the port)
  • CMD [“npm”, “start” ] set the default command “npm start” to be executed when container runs without other commands

Before build our first Docker image, let us start the minikube cluster with

minikube start

and run the following command to make minikube use local docker registry

eval $(minikube docker-env)

Otherwise, minikue will seek image from other public Docker registery and fails our following steps. Now we can build our Docker image with following line in /kubernetes_experiments

docker build -t kubernetes/node-web-app .

The process is like above, while -t is to give the image a name kubernetes/node-web-app. Type command

docker images

you will see

The first one is our kubernetes/node-web-app. Docker image is ready and we are able to create our first kubernete service

2. Create and expose kubernetes Service

Before deploying Docker image to minikube, let me introduce some concepts to get you familiar with kubernetes.

Pods

Pod is the basic building block of kubernetes. A pod may contains single or multiple Docker containers and all containers in the pod share the same IP address as well as network and ports namespace. The following command will help you check the current pods

kubectl get pods

Node

Pods run in node and node is the worker in kubernetes. It could be virtual machine or physical machine. The following command will help you check the current nodes

kubectl get nodes

The kubernetes cluster provde an inner flat network so each two pods could communicate with each other. The simplified illustration of kubernetes cluster is like this:

Simplified Illustration of Kubernetes Cluster Structure

Controller

Controller is a set of APIs to organize and manage pods or nodes. In this experiments, we use ReplicaSet to deploy our container. ReplicaSet is actually the next-generation Replication Controller and support more expressive selectors. For example, ReplicaSet can use match expression whereas Replication Controller can not. A ReplicaSet keep a specific number of pod replicas running at the same time. It means that ReplicaSet will monitor the statuses of these pod replicas and will create new pod replicas to replace the original ones when they failed or lost. The process is like the following:

To deploy a ReplicaSet for out Docker container, let’s create a YAML file called replicaset.yaml in /kubernetes_experiments and copy the following code to the file

apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: kubernetes-node-server-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: kubernetes-node-server-replicaset
template:
metadata:
labels:
app: kubernetes-node-server-replicaset
spec:
containers:
- name: kubernetes-node-server-replicaset
image: kubernetes/node-web-app
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8081
  • apiVersion: different api version contains different set up rules for your service. ReplicaSet is in apps/v1beta2
  • kind: name of the object that you are going to create
  • metadata: the meta data of the object that will be created. For first metadata, we define the name of our ReplicaSet
  • spec: the specific configuration
  • replicas: how many replicas that will be keep in our ReplicaSet
  • selector: choose the specific pods to use in our ReplicaSet.
  • template: the specific configuration for pods in ReplicaSet
  • containers: the policies of running Docker containers in pods
  • name: the name of our ReplicaSet, here is kebernetes-node-server-replicaset. It should be the same as the app name in selector
  • image: the Docker image name which is kubernetes/node-web-app
  • imagePullPolicy: the default is IfNotPresent which make the kubernetes to pull an image if it does not exist
  • containerPort: specify which port container uses

If you choose to type the above code, do not use tab in YAML file. Then run the following command in /kubernetes_experiments

kubectl create -f replicaset.yaml
  • -f is the shorthand of filename.

Service

To make the controllers or pods accessible from outside, we need to expose a constant service(the pods could be recreated by ReplicaSet and their IP will be changed). A service is a REST object in kubernetes cluster. We could also use YAML file to define our service.

Service Illustration

Kubernetes service has an iptable which allow us to configure route for every pod inside Node. In this experiment, we just expose ReplicaSet to the Service. Create a YAML file called replica-set-service.yaml in /kubernetes_experiments and copy the following code to the file

apiVersion: v1
kind: Service
metadata:
name: kubernetes-node-server-replicaset-service
spec:
type: NodePort
ports:
- protocol: TCP
nodePort: 30036
port: 9090
targetPort: 8081
selector:
app: kubernetes-node-server-replicaset
  • protocol: TCP and UDP, we use TCP for HTTP API
  • type: there are two types NodePort and LoadBalancer. For local development, NodePort will make Kubernetes to allocate a port from 30000–32767 to service. The Nodes which is connected to the service will also proxy the same port to the service
  • nodePort: the port which is accessible from outside
  • port: other services in kubernetes cluster can visit the service through this port
  • targetPort: the port on which the pod is actually running
  • selector: select the previous created ReplicaSet

Run the following command in /kubernetes_experiments to create our service

kubectl create -f replica-set-service.yaml

A good thing is that Minikube provides a web interface for us to view all node in cluster, type

minikube dashboard

you can get all the information, statuses of the Pods, ReplicaSets and Services

Almost done, now we can use the following command to check the local url for our service

minikube service kubernetes-node-server-replicaset-service —-url

Now, we can visit our service(like in postman)

3. Clean up

To delete the services, ReplicaSet , following command will help

kubectl delete svc kubernetes-node-server-replicaset-service
kubectl delete rs kubernetes-node-server-replicaset

where svc and rs are the shorthand for service and replicaset. You can also do it on Minikube dashboard.

Then, shut down the minikube

minikube stop

To disconnect Minikube and local Docker registry

eval $(minikube docker-env -u)

To delete out first builded docker image

docker rmi kubernetes/node-web-app

--

--