Kubernetes — Exploring ReplicaSet, Service & Deployment
Part III — Scale application using ReplicaSet. Type of service and overview of Deployment in AKS.
In the previous article, we saw the pod management usage of kubectl.
We ran the applications directly and via YAML and then exposed the application using service from the command line. Today we’ll discuss how to run multiple instances of the app using ReplicaSet, usage and types of service and using deployment instead of directly running pods.
Note: kctl is an shell alias I have set for kubectl command.
All other abbreviation like svc for service, rs for replicset etc are built into k8s.
ReplicaSet:
It is an object that ensures a specified number of identical pod replicas are running at all times. It is responsible for maintaining the desired state of a set of pods in a cluster. Whenever a pod dies for some reason, ReplicaSet creates another pod with the same specification.
We can create rs (ReplicaSet) using the command line but will stick to YML.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp
spec:
replicas: 5
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: one
image: nginx
Apply the config with kubectl apply -f replilcaset.yml. This will create 5 replicas of the nginx application.
To test the work of ReplicaSet, I’ll delete a pod and we should see one more pod generated automatically.
So, there is the magic that ReplicaSet does. Delete the ReplicaSet with:
kubectl delete <fiename.yml>
Service:
A Kubernetes service provides a way to expose our application and provides stable connection end points.
In k8s pods are ephemeral meaning they die at random times and new pods are created to replace them (example above), so having an IP attached to a pod is not ideal because every time a new pod is created a new IP will be assigned.
Service however assigns a static ip so whenever a pod is recreated the same ip is assigned. It also provides a load balancing mechanism so we can have one service in Infront of multiple pods and now we have a single public IP address for all the instances of our application and hence can be used from outsiders of the cluster.
Note: There is one default service called "Kubernetes" which is always available
and is not managed by us. This service provides connectivity to the API server
There are multiple types of services.
- ClusterIP: This is the default service type created if we don't specify anything explicitly (although we can specify it as ClusterIP). This creates only private ip which can be used for communication inside the cluster for example containers inside a pod, app pod to db pod etc.
Example:
## clusterip.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: webapp
spec:
replicas: 5
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: mycontainer
image: nginx
---
apiVersion: v1
kind: Service
metadata:
name: mysvc
spec:
type: ClusterIP
ports:
- targetPort: 80
port: 5000
selector:
app: web
You can create a service as a different YAML or attach it to other components such as ReplicaSet. In the above example I have both config in single file, so when I apply it, both configs are applied.
To verify, we can enter the node in debug mode and curl the mysvc ip:port.
To enter a node in debug mode use the below command. The curl package won’t be available so install it.
kubectl debug node/<NODE NAME> -it --image=mcr.microsoft.com/dotnet/runtime-deps:6.0
# apt update && apt install curl
# curl 10.0.107.223:5000
- NodePort: This type of service assigns an IP to the worker node/machine. We have to specify the type as NodePort to have nodeport service created. Now with service and we’ll have a port configuration for the node, so we can access the application using the node IP and port number. However, this port configuration is limited to a range of 30000 to 32767. This however is not secure as we are directly accessing the node.
## nodeport.yml
<same as above>
---
apiVersion: v1
kind: Service
metadata:
name: web-node-port
spec:
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 30002
selector:
app: web
- LoadBalancer: This type of service is based on the load balancer of the cloud provider. This creates a node port and cluster ip however clients are only connected through the load balancer. LoadBalancer routes the external traffic to the node port.
## lb.yml
<same replicaset config>
---
apiVersion: v1
kind: Service
metadata:
name: mylbrsvc
spec:
type: LoadBalancer
ports:
- targetPort: 80
port: 5000
selector:
app: web
[ ~ ]$ kctl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 41m
lbservice LoadBalancer 10.0.102.237 20.207.105.218 5000:32190/TCP 41s
Since this is a public URL, we should be able to access the webpage at the specified IP and port. Although we don’t see any differences on the page, it is still being load balanced.
Deployment:
Deployment is a YAML-based configuration where we can define our application, define service and the corresponding port. We can also manage how many instances of our application run at all the times using ReplicaSet.
First, let's create a deployment using the command line. Increase the pod instance by using ReplicaSet and then expose it using LoadBalancer svc.
### creating deployment
kctl create deployment mywebsvc --image='nginx:1.24'
### creating service of type LoadBalancer
kubectl expose deployment mywebsvc --target-port=80 --port=80 --type=LoadBalancer
Scale the deployment, this creates a ReplicaSet component as well.
### scaling deployment
kctl scale deployment mywebsvc --replicas=3
kctl get rs
Alright, we’ll dig deep into deployment using YML, updating the new version of the application and rolling back to previous and types of deployment in the next article. Thanks for reading.
Check out the full K8s list here:
References: Kubernetes Docs