(Photo by Scott Webb on Unsplash)
In the previous post, we had a look at the concept of Worker nodes. Now let's look at how we do deployments of applications to Worker nodes.
Kubernetes has a couple of basic objects that host your applications and services. These are, in order, Pods, ReplicaSets and Deployments.
Kubernetes uses YAML files to create these entities, so let's see how this works. A Kubernetes YAML file always contains the following required default statements.
Pods
Lets create the following file, awesome-app-pod.yaml.
apiVersion: v1
kind: Pod /* This is the object type being created */
metadata:
name: my-awesome-app
labels:
app: awesome-app
spec:
containers: // this is a list/array
- name: awesome-app-container // the dash means list item
image: awesome-app
You would create the above object as a Pod in you Kubernetes cluster by issuing the following command;
kubectl create -f awesome-app-pod.yaml
The '-f' tells kubectl to read from the file specified.
If you're not familiar with YAML, please note that indentation really, really matters and also that YAML doesn't like tabs, so be sure to user spaces!
When you have indented statements - like those under metadata - you're in actuality creating a key-value dictionary/object with hierarchies and nesting defined by the level of indentation. So app: is a child of labels:, which in turn is a child of metadata:.
To view your newly created pod, run;
kubectl get pods
Or, to see more details for a specific pod in particular
kubectl describe pod my-awesome-app
And there you go, you have just deployed your application to your cluster.
ReplicaSets
So what do you do when your fancy new pods gets deployed, serves users for a good while and then unexpectedly crashes? Do you need to constantly keep an eye on your pods and delete ones that have crashed and create new ones to replace them?
What about sudden surges in requests from users? If your application gets shared on HackerNews and you suddenly have to serve 50x the requests, could you rely on that one, lonesome pod to just keep on chugging along and hold its own?
ReplicationSets and Replication Controllers to the rescue!
ReplicationSets and/or Replication Controllers are processes that ensure that a certain number of identical pods are always running on your cluster, allowing for more redundancy and fallover protection. If a pod fails, the ReplicationSet or Replication Controller will remove it and replace it with a new one.
They will also makes sure that you have a specified minimum amount of replicated pods running at all times, in order to make sure your application can meet your traffic needs.
ReplicationSets/Controllers can operate over multiple nodes in your cluster too, so you won't be limited to the resource availability of a single node either.
Replication Controller VS ReplicaSet
So what's the difference between ReplicaSets and Controllers?
Well, they do more or less the same thing, ReplicationSets are just the new and improved implementation of the older Replication Controller. Both will do just fine, but ReplicationSets are the way forward and offer you a little bit more control, so we'll be focussing on them for this post.
Let's set up a ReplicationSet with YAML, create the file awesome-app-replicaset.yml
apiVersion: apps/v1 // <-- Note the addition of 'apps/'. This is required.
kind: ReplicaSet
metadata: // <-- metadata for replicaset
name: awesome-app-replicaset
labels:
app: awesome-app
type: web-app
spec:// <-- spec for replicaset
template:
metadata // <-- metadata for pods to be replicated
name: awesome-app-pod
labels:
app: awesome-app
type: web-app
spec: // <-- spec for pods to be replicated
containers:
- name: awesome-app-container
image: awesome-app-image
replicas: 3
selector: // <-- can be used to include existing pods
matchLabels:
type: web-app
Then create the ReplicationSet with the following command;
kubectl create -f awesome-app-replicaset.yml
and then view them with
kubectl get replicaset
You can also view the pods created by the ReplicaSet by running
kubectl get pods
You'll see that the pods are named based on the name property in your ReplicaSet metadata.
So now how do we scale up the replicated pods? By updating the replicas property in the YAML file and then replacing the deployed ReplicaSet with;
kubectl replace -f awesome-app-replicaset.yml
Another way is to directly update the running ReplicaSet process with
kubectl scale --replicas=8 replicaset awesome-app-replicaset
or alternatively, to edit any other properties of the running ReplicaSet, run;
kubectl edit replicaset awesome-app-replicaset
Note that using the kubectl scale command doesn't update the YAML file itself, only the running process.
There are of course ways to automatically scale replicas up or down based on traffic load, but we'll get to automation a little bit later.
Deployments
A Deployment is a Kubernetes entity/object one level higher than a ReplicaSet, ie Deployments contain ReplicaSets, which in turn contain Pods.
Deployments control the updating of its underlying entities.
Deployments can do the following;
- Create instances of running applications as ReplicaSets.
- Upgrade outdated containers with new ones via rolling updates, where running instances are updated one after the other, in order to not disrupt containers currently interacting with users.
- Roll back failed updates.
- Updating the environment properties like scaling settings, deployment version or resource allocations.
Deployments are also defined using YAML files. Let's have a look at deployment.yaml.
You'll see it looks exactly like a ReplicaSet YAML file, except the kind property changed to Deployment, and other references for replicaset changed to deployment.
apiVersion: apps/v1 // <-- Note the addition of 'apps/'. This is required.
kind: Deployment
metadata: // <-- metadata for deployment
name: awesome-app-deployment
labels:
app: awesome-app
type: web-app
spec:// <-- spec for deployment
template:
metadata // <-- metadata for pods to be deployed
name: awesome-app-pod
labels:
app: awesome-app
type: web-app
spec: // <-- spec for pods to be deployed
containers:
- name: awesome-app-container
image: awesome-app-image
replicas: 3
selector: // <-- can be used to include existing pods
matchLabels:
type: web-app
Create it with;
kubectl create -f deployment.yaml
View your deployment with;
kubectl get deployments
You can also view you deployment in more detail with;
kubectl describe deployment awesome-app-deployment
Pro tip! To save time you can use kubectl to generate the YAML file boilerplate by running;
kubectl create deployment --image=awesome-app-image awesome-app-deployment --dry-run -o yaml
This will log out a good starting template for you to copy and paste, and get up to speed faster.
Conclusion
We had a look at the basic objects used to deploy services in a Kubernetes cluster. These include Pods, ReplicaSets and Deployments. We also had a look at some of the commands kubectl uses to create, view and edit these objects.
Here's a handy little command to view everything that is currently running on your cluster
kubectl get all
That's it for now, I hope that was helpful. In the upcoming posts we'll start exploring Namespaces and Services. Thanks for reading!