Late-to-the-Table Kubernetes Part 3: Yet Another Explanation of Kubernetes

For Whom The Post Tolls, The Post Tolls for Thee1

In Part 1, I made a reference to Kubernetes being a software defined, “datacenter in a box”. I stand by that statement. Here we are going to delve further into that idea.

In Part 2, we talked about resources for studying Kubernetes and what worked for me.

Here we are looking to further grasp the basic concept of Kubernetes. Therefore, this post is not for people who already understand the basics of Kubernetes, or for experienced Kubernetes Admins. If you are a Kubernetes admin, we’ll see you next post I guess, but it’s always nice to get feedback about what I get right or where I am dead wrong. Just don’t be a dick about it!

This post is also not for people who want to learn kubectl commands. I am explaining the concept of kubernetes for beginners here, not how to run it. kubectl will be in an ensuing post.

One disclaimer I would like to put out there is that Kubernetes is not a panacea. It’s not for every application, nor is it for every company.

Know This

But before we dive deeper, drawing from my own experiences, there is some prerequisite knowledge that I would recommend. Trust me, as much as anyone, I hate it when people “gatekeep” anything and make implications that, “this knowledge is only for me and my experienced engineering friends, n00b. #DealWithIt.

I despise that kind of talk, but you should be aware of your expectations.

Far be it from me to dictate who is and who is, “not ready to learn K8s,” but if you just got your A+ last week and have never dealt with REST APIs or datacenter-level concepts like network load balancing or HTTP headers, this is going to be a long haul for you. Breaking this down to the bare minimum of “required knowledge” I would recommend the following before you move ahead with Kubernetes:

  1. The basics of the BASH Shell.
  2. Containers – At least do a docker build from a docker file and know the basics of containerization, especially container networking.
  3. Network Load Balancing concepts and Ingress.
  4. How a REST API works. I have an easy example here, but you can also read up on the actual Kubernetes API.
  5. YAML.
  6. You should also know what a Kubernetes Node is, and what a Kubernetes Pod is.
  7. That an application runs inside a pod.

A Short Aside for My VMware Peeps

If this is so far escaping you. Think of it this way:

  1. Kubernetes and the Kubernetes API = vCenter
  2. Node = ESXi Host (but I feel compelled to say that K8s nodes can be physical or virtual).
  3. Pod = VM
  4. Container(s) in that Pod = Application

You’re welcome . . .

Now that we have all that out of the way . . . Here we go.

Once More Unto the Breach, Dear Friends2

Let’s get back to our discussion about the components of a datacenter, and how it all translates into Kubernetes. Let’s forget about Kubernetes for a second and ask ourselves what we need in order to have a functional, enterprise-level physical datacenter?

  1. Redundant compute.
  2. Redundant networking with load balanced access to applications.
  3. Redundant storage.

Assuming all the physical hardware all of this runs on is redundant and obfuscated, Kubernetes provides all of these things, but does it all through a software-defined API. That’s it. That’s the tweet.

See you next post everyone! . . . .

Seriously though, of course, all of this runs on physical hardware ultimately. You can’t defy the laws of physics, you silly goose.

But one common theme you will find, as a result of this whole “API-defined” (I made that phrase up) idea, one could argue that this gives a lot of people a lot of power to do things that would ordinarily take the coordination of multiple teams of people. Since Kubernetes is a “datacenter in a box”, depending on the scale, fewer people would be required coordinate rolling out many applications. Since the datacenter is software-defined, running apps at scale becomes trivial.

Kubernetes Services

You should also know what a Kubernetes Service is, and that end-users access the resources defined in that service directly over the network. The official documentation does a much better job than I could:

“In Kubernetes, a Service is an abstraction which defines a logical set of Pods and a policy by which to access them (sometimes this pattern is called a micro-service).”

It’s a defined combination of resources (load balancer, pod, port number, etc.) that Kubernetes knows about that manages the lifecycle, availability, security, and access to an application.

And that’s Kubernetes’ superpower. Since it’s “API-defined”, the ability to implement, change, or improve the application can be mostly done on the fly, rather than having to alter physical hosts or switches, or anything.

Don’t want to wait for the network team to configure the load balancer for your application? Implement your own load balancer like metallb or Kube-vip.

EHRMERGERD KURBERNERTERS!

Server team slowing you down and just want to make your application more resilient during development? Implement a deployment with readiness probes independently of other teams.

EHRMERGERD KURBERNERTERS!

. . . and so on.

I MADE A THING!

I made (yet another) Kubernetes drawing, but most of the credit does go to the official documentation at kubernetes.io with the section on using a service to expose your app, I simply added the Kubernetes API and ETCD (the Kubernetes “database”) part.

Basic Kubernetes Drawing

I do not make any claims about this drawing being the be-all-end-all of Kubernetes Drawings. It’s actually very simplified, but it brings home a lot of the vocabulary we have been throwing around so far.

Let’s Look at the Kubernetes API

I want to bring home this “Datacenter in a Box” idea, particularly referring to the resources defined in the drawing above. Let’s take a look at what a node is. Everything runs on nodes, but how is a node defined in Kubernetes? Well, once a node is entered into the Kubernetes API, it is now a “node resource”. It’s the equivalent of racking and stacking a physical machine that is now ready to be used in the datacenter. But in the world of Kubernetes, it’s just another API Object.

The best way to show you this is by literally showing you how this all looks in the Kubernetes API. If you’d like to do this yourself, all you need is a MAC/Linux machine with a Kubernetes implementation like minikube and Postman, or curl if you are so inclined.

. . . OK, so I just realized I have to use a kubectl command for this, so I guess I lied earlier about not showing you kubectl commands . . . DAMMIT!

You can do this yourself if you like. I am using minikube here because if I show you our prod Kubernetes implementations I will get justifiably fired. The api objects are the same with minikube, so it works.

Also, an FYI: WordPress automatically makes anything with http in front of it a link, so beware with those curl commands:

  1. Once minikube is running, type:
    kubectl proxy --port=8080 &
  2. Now enter this into Postman or use curl (I will use curl here):
    curl http://localhost:8080/api/v1
  3. You will see that what you get is a list of defined Kubernetes objects. Make your way down to the nodes section:
. . .
{
      "name": "nodes",
      "singularName": "",
      "namespaced": false,
      "kind": "Node",
      "verbs": [
        "create",
        "delete",
        "deletecollection",
        "get",
        "list",
        "patch",
        "update",
        "watch"
      ],
      "shortNames": [
        "no"
      ],
    },
. . .

Aren’t you excited! I am! You’re literally seeing the inner workings of Kubernetes. But we’re not done yet.

Side lesson alert!

  1. Now take a look at the nodes that are in this Kubernetes cluster by adding /nodes to the url:
    curl http://localhost:8080/api/v1/nodes
{
  "kind": "NodeList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/nodes",
    "resourceVersion": "39036"
  },
  "items": [
    {
      "metadata": {
        "name": "minikube",
        "selfLink": "/api/v1/nodes/minikube",
        "uid": "ea1f74a8-c58c-49f6-b998-31c059834151",
        "resourceVersion": "38939",
        "creationTimestamp": "2020-10-20T16:32:58Z",
        "labels": {
          "beta.kubernetes.io/arch": "amd64",
          "beta.kubernetes.io/os": "linux",
          "kubernetes.io/arch": "amd64",
          "kubernetes.io/hostname": "minikube",
          "kubernetes.io/os": "linux",
          "minikube.k8s.io/commit": "b09ee50ec047410326a85435f4d99026f9c4f5c4",
          "minikube.k8s.io/name": "minikube",
          "minikube.k8s.io/updated_at": "2020_10_20T09_33_01_0700",
          "minikube.k8s.io/version": "v1.14.0",
          "node-role.kubernetes.io/master": ""
        },
        "annotations": {
          "kubeadm.alpha.kubernetes.io/cri-socket": "/var/run/dockershim.sock",
          "node.alpha.kubernetes.io/ttl": "0",
          "volumes.kubernetes.io/controller-managed-attach-detach": "true"
        }
      },
. . .

Holy crap! So that’s how it works.

Wait . . . you think we can do the same thing for pods? Hmmmmmmm.

curl http://localhost:8080/api/v1/pods

 . . .
 "items": [
    {
      "metadata": {
        "name": "kubia-7969cf94fc-tnbp7",
        "generateName": "kubia-7969cf94fc-",
        "namespace": "default",
        "selfLink": "/api/v1/namespaces/default/pods/kubia-7969cf94fc-tnbp7",
        "uid": "a064eb5e-3683-4775-856e-3e087eca5e34",
        "resourceVersion": "37887",
        "creationTimestamp": "2020-11-10T21:47:25Z",
        "labels": {
          "app": "kubia",
          "pod-template-hash": "7969cf94fc"
        },
        "ownerReferences": [
          {
            "apiVersion": "apps/v1",
            "kind": "ReplicaSet",
            "name": "kubia-7969cf94fc",
            "uid": "3ede91e5-243a-4dfe-ac34-4dcb18e61b72",
            "controller": true,
            "blockOwnerDeletion": true
          }
        ]
      },
      "spec": {
        "volumes": [
          {
            "name": "default-token-w85lx",
            "secret": {
              "secretName": "default-token-w85lx",
              "defaultMode": 420
            }
          }
        ],
        "containers": [
          {
            "name": "kubia",
            "image": "bryansullins/kubia",
            "ports": [
              {
                "containerPort": 8080,
                "protocol": "TCP"
              }
            ],
            "resources": {

            },
            "volumeMounts": [
              {
                "name": "default-token-w85lx",
                "readOnly": true,
                "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
              }
            ],
            "terminationMessagePath": "/dev/termination-log",
            "terminationMessagePolicy": "File",
            "imagePullPolicy": "Always"
          }
        ],
        "restartPolicy": "Always",
        "terminationGracePeriodSeconds": 30,
        "dnsPolicy": "ClusterFirst",
        "serviceAccountName": "default",
        "serviceAccount": "default",
        "nodeName": "minikube",
        "securityContext": {

        },
        "schedulerName": "default-scheduler",
        "tolerations": [
          {
            "key": "node.kubernetes.io/not-ready",
            "operator": "Exists",
            "effect": "NoExecute",
            "tolerationSeconds": 300
          },
          {
            "key": "node.kubernetes.io/unreachable",
            "operator": "Exists",
            "effect": "NoExecute",
            "tolerationSeconds": 300
          }
        ],
        "priority": 0,
        "enableServiceLinks": true
      },
. . .

The above pod is from when I was practicing my K8s learning with Kubernetes Up and Running.

IS YOUR BRAIN EXPLODING YET OR WHAT?

I don’t know about you, but I could poor myself a dram and spend hours doing that for all the various resources in a Kubernetes cluster. Try /services and see what comes up.

I suppose it would not surprise you, dear readers, to know that I have done just that!

Questions? Hit me up on twitter @RussianLitGuy or email me at bryansullins@thinkingoutcloud.org. I would love to hear from you.

1 A play of words with John Donne’s work.
2 Shakespeare

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s