Intro to Kubernetes Series - Part 2 - Stepping it up to Kubernetes



With an understanding of some basic docker concepts in mind, we can begin to introduce Kubernetes. In the first article we looked at what docker has to offer, and saw how to deploy docker containers by hand, including building up a docker image. In this installation of the kubernetes mini-series, we'll dip our toes into some surface-level concepts and more practical workings of what kubrnetes has to offer.

Who this article is for:

If you've read or heard about this miracle technology Kubernetes, that is supposed to relieve the agonizing tasks of managing infrastructure surrounding application delivery but have no idea where to start or how to use it, this article is for you. I won't be expecting you to be a hardened IT veteran with a decade of experience. This is intended to be a gentle introduction.
This article meant to be a high-level view of what Kubernetes can do, why it is valuable, and some basic examples of how to implement it.

What is not covered:

I won't be focusing on the deep technical understandings of how everything in the Kubernetes components work together. I won't drag the concepts down with lengthy technical explanation.

Before we begin:

The following is written with a few assumptions in mind if you intend to follow along with some of the concepts and examples.
  • You have a working kubernetes environment. Some good places to start are the built in Kubernetes engine already present in the Docker Desktop client, or MiniKube. Alternatively you can use the browser based Kubernetes environment play-with-k8s.com
  • You have a text editor of some sort. I'll be using nano (built into ubuntu), just to illustrate that the configuration of yaml files doesn't require a full-blown coding suite.

What is Kubernetes?

Simply put, Kubernetes provides a framework of infrastructure that interfaces with the docker engine in order to provide some automation and ease of management. In reality, this means that you can use both declarative, and imperative statements to build out your application architecture. A good thing to remember is that everything in Kubernetes is an object of some sort. Here's a list of a few of the resource objects we'll be working with in this article, these definitions are meant to be simple and easy to conceptualize:
  • Pods: Simply put, the "house" for the container we build up
  • Service: The network service for how we'll be reaching the pod application.
  • Deployment: a description of multiple objects, including pods and services, as well as a strategy for maintaining presence of the application.
We'll be looking at creating each of these in this article.
As a quick primer, I'll try to simply explain the basics of the kubernetes services so we can have a good grasp of how we'll be accomplishing things. Kubernetes is built on 3 main parts: A database that stores all the definitions of the objects, an API interface to pass information in and out of the database, and the kubelet service, which relays the info from the API server to the host server's docker engine to build the objects.





This image has an empty alt attribute; its file name is BasicKubeArch.jpg

Don't get too caught up on the details at this point. The main take away from this image is that the database is the only source of truth, and only the API service can talk to it.

Being that everything is an object in Kubernetes, all of these objects have strict definitions within kubernetes. These definitions can be created in multiple ways. Two of the main ways are with the kubectl tool, and YAML files.
With the kubectl tool, we can interact with the kubernetes api server with the command line interface on the host operating system. This will send our intention to create the objects to the API server, and the API server will relay those instructions to the kubelet services.
Here's an example of creating a pod containing the docker image we created in the part 1 article: dockerdemohelloworld, using the kubectl command:


This image has an empty alt attribute; its file name is kubectlcreatepod.gif

kubectl run is an example of a command that works the same way that the docker run command works. In this example we merely created the container within a kubernetes pod. Looking at the description we can see various info about it, as well as the event logs. For instance, we can look at the node where the pod is running.


This image has an empty alt attribute; its file name is image.png

We can create this exact same pod with a YAML file. Here's what it would look like. (note: yaml files are sensitive to white-space, meaning indentation is important).



apiVersion: v1
metadata:
  name: helloworld
  labels:
    app: helloworld
kind: Pod
spec:
  containers:
  - image: jfranzen/dockerdemohelloworld
    name: helloworld


With this file, we're telling the API server: "Using API v1, create a Pod called 'helloworld' and label it 'app:helloworld', using the jfranzen/dockerdemohelloworld' image in a container called helloworld".
You can save this as a yaml file on your host computer and then create the object with the command kubectl create -f helloworldpod.yaml
Heres a quick demo showing the steps:


This image has an empty alt attribute; its file name is kubectlcreatepodyaml.gif

Now that we have our running container, we'll need to set up a Service object (essentially just a network connection), to access the container.
We can do this with the kubectl command using the expose option, like this: kubectl expose pod helloworld --type=NodePort --port=8000 --target-port=8000 --protocol=TCP. If you're familiar with firewall rules, you'll recognize that this looks a lot like a port forwarding rule, because that's what it is. We're forwarding port 8000 within the cluster, to port 8000 on the container. The "NodePort" type will then create another forwarder from the Master node to the worker node where this pod is running.





This image has an empty alt attribute; its file name is kubectlcreateservice.gif

Once the service is exposed, all we need to do is get the port that kubernetes linked to the service on the master node:





This image has an empty alt attribute; its file name is image-1.png

Here we can see that it's 32322. In my cluster, the master node is 172.0.1.70, so I'll use the URL http://172.0.1.70:32322 to access the pod:





This image has an empty alt attribute; its file name is helloworldweb.gif

As with the pod, we can also declare the service resource with a YAML file:

apiVersion: v1
metadata:
  name: helloworld-service
  labels:
    app: helloworld
kind: Service
spec:
  type: NodePort
  ports:
  - nodePort: 32322
    port: 8000
    protocol: TCP
    targetPort: 8000
  selector:
    app: helloworld


As an important note, you'll notice the "selector" parameter declared in the service, this tells the service that it should connect to pods with the app: helloworld label. Pods can have as many labels as you'd like, and the selectors to attach the service to the pod just needs to have the correct labels.
Once again, we run the command to create a resource with the file: kubectl create -f helloworld-service.yaml





This image has an empty alt attribute; its file name is helloworldserviceyaml.gif

We can verify that the service is connected to the pod by using the describe command and looking at the Endpoints within the service, it has an internal cluster IP, so we know that the service is forwarding.
Now we get to what I like to call a "lightbulb" moment regarding kubernetes. We can create a single file to declare both of these resources as well as ensuring that the application is up and running at all times. With a Deployment resource type, we can tell the kubernetes service what resources we want to deploy and to automatically recreate the pods if something should happen to them. This can only be done with a YAML file, here's what this one would look like:

apiVersion: v1
apiVersion: v1
metadata:
  name: helloworld-service
  labels:
    app: helloworld
kind: Service
spec:
  type: NodePort
  ports:
  - nodePort: 32322 # I've left this in place so that we can use the same 
                    # url as the example. You would omit this line 
                    # otherwise.
    port: 8000
    protocol: TCP
    targetPort: 8000
  selector:
    app: helloworld
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: helloworld
  labels:
    app: helloworld
spec:
  selector:
    matchLabels:
      app: helloworld
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: helloworld
    spec:
      containers:
      - image: jfranzen/dockerdemohelloworld
        name: helloworld
With the differences between the Pod and Deployment resources aside, it really is as simple as putting both definitions into the same file. Realistically, there are some details that separate a Pod definition from a Deployment definition, namely the "matchLabels" parameter, which tells the deployment which pods to keep an eye on, and the "strategy" parameter, which tells the deployment what to do if a pod fails. Then there's the "template" section, which tells the deployment what it's deploying. Without getting too deep into it, we're basically telling the Deployment resource to create a pod with the dockerdemohelloworld image, and recreate it if it fails. Similarly, we create these resources with the kubectl create -f commands.





This image has an empty alt attribute; its file name is helloworlddeploymentyaml.gif

And now we can show off where kubernetes shines. This is the most basic form of container orchestration that kubernetes has to offer. I'll delete the pod created in this deployment, and we can see it get recreated instantly, maintaining service of the web app.





This image has an empty alt attribute; its file name is helloworldrecreatepod.gif

And since the deployment uses the template we defined to create the pod, it will have the same labels, allowing the service to connect to it once it comes online. From the web page perspective, we may not even notice the site went down.
To take this concept a bit further, we can even save this YAML configuration file in a git repository or file share, and call the file down with an HTTP address instead of a local file address, allowing the bootstrapping of services without needing to create the files every time, as well as having source control for your configurations.

Wrap-up

There are more complex versions of the deployment that have many more uses such as ReplicaSets, and StatefulSets. Which can maintain many instances of the same container and allow for seamless rolling out of updates to your environement. These types of configurations are where Kubernetes really shines: allowing for continuous lifecycle management of containerized applications.
Where does this fit in terms of an enterprise environment? Well, this would work in place of places where your developers are deploying their applications to things like VM's and web servers. Instead of publishing their code to the file structure of a web server, they would publish it, for example, to a git repository, then create a container that downloads those files and installs them to the container web service, and then that container would be used to build the service within kubernetes.
As a high view of the practicality within Kubernetes, I hope this article was informative enough to illustrate the concepts and the value it can bring to containerized infrastructure and help to understand a bit of container orchestration in comparison to the base docker environment. I'll be writing another corresponding step-by-step article for brining the Bedrock Minecraft server image into kubernetes as a deployment. Join me then as I'll be diving a bit deeper into the inner workings of the configurations.

Comments

  1. You'll discover your preferred title by utilizing the search characteristic within the foyer. The larger sportsbooks may have the liquidity to pay you out when their books are thin, and they’ll have a reputation to uphold so their customer service is often 메리트카지노 going to be higher. If you seek for a sportsbook or casino on-line and you can’t discover any info on them exterior of their very own website, it’s probably a rip-off.

    ReplyDelete

Post a Comment

Popular posts from this blog

Creating Ubuntu Bedrock Minecraft image with Docker

Intro to Kubernetes Series - Part 1 - What is Docker?