DOKK Library

Orchestration with Kubernetes

Authors Ben Finkel Bryant Son Jiaqi Liu Mike Calizo Nived Velayudhan Ricardo Gerardi Seth Kenlon

License CC-BY-SA-4.0

Plaintext
Orchestration with
Kubernetes
We are Opensource.com

Opensource.com is a community website publishing stories about creating, adopting, and
sharing open source solutions. Visit Opensource.com to learn more about how the open
source way is improving technologies, education, business, government, health, law,
entertainment, humanitarian efforts, and more.

Do you have an open source story to tell? Submit a story idea at opensource.com/story

Email us at open@opensource.com
Table of Contents
What's the difference between orchestration and automation?......................................................4
Getting started with Minikube: Kubernetes on your laptop...............................................................7
Getting started with Kubernetes.........................................................................................................10
Automate your container orchestration with Ansible modules for Kubernetes.............................15
A beginner's guide to Kubernetes Jobs and CronJobs....................................................................21
A beginner's guide to Kubernetes container orchestration.............................................................28
A beginner's guide to load balancing.................................................................................................34
A guide to Kubernetes architecture...................................................................................................38
Getting started with OKD....................................................................................................................43
What's the difference between
orchestration and automation?

By Seth Kenlon

For the longest time, it seemed the only thing any sysadmin cared about was automation.
Recently, though, the mantra seems to have changed from automation to orchestration,
leading many puzzled admins to wonder: "What's the difference?"

The difference between automation and orchestration is primarily in intent and tooling.
Technically, automation can be considered a subset of orchestration. While orchestration
suggests many moving parts, automation usually refers to a singular task or a small number of
strongly related tasks. Orchestration works at a higher level and is expected to make decisions
based on changing conditions and requirements.

However, this view shouldn't be taken too literally because both terms—automation and
orchestration—do have implications when they're used. The results of both are functionally the
same: things happen without your direct intervention. But the way you get to those results,
and the tools you use to make them happen, are different, or at least the terms are used
differently depending on what tools you've used.

For instance, automation usually involves scripting, often in Bash or Python or similar, and it
often suggests scheduling something to happen at either a precise time or upon a specific
event. However, orchestration often begins with an application that's purpose-built for a set
of tasks that may happen irregularly, on demand, or as a result of any number of trigger
events, and the exact results may even depend on a variety of conditions.


Decisionmaking and IT orchestration
Automation suggests that a sysadmin has invented a system to cause a computer to do
something that would normally have to be done manually. In automation, the sysadmin has


Creative Commons Attribution Share-alike 4.0                                                      3
already made most of the decisions on what needs to be done, and all the computer must do
is execute a "recipe" of tasks.

Orchestration suggests that a sysadmin has set up a system to do something on its own
based on a set of rules, parameters, and observations. In orchestration, the sysadmin knows
the desired end result but leaves it up to the computer to decide what to do.

Consider Ansible and Bash. Bash is a popular shell and scripting language used by sysadmins
to accomplish practically everything they do during a given workday. Automating with Bash is
straightforward: Instead of typing commands into an interactive session, you type them into a
text document and save the file as a shell script. Bash runs the shell script, executing each
command in succession. There's room for some conditional decisionmaking, but usually, it's
no more complex than simple if-then statements, each of which must be coded into the
script.

Ansible, on the other hand, uses playbooks in which a sysadmin describes the desired state of
the computer. It lists requirements that must be met before Ansible can consider the job
done. When Ansible runs, it takes action based on the current state of the computer
compared to the desired state, based on the computer's operating system, and so on. A
playbook doesn't contain specific commands, instead leaving those decisions up to Ansible
itself.

Of course, it's particularly revealing that Ansible is referred to as an automation—not an
orchestration—tool. The difference can be subtle, and the terms definitely overlap.


Orchestration and the cloud
Say you need to convert a file type that's regularly uploaded to your server by your users.

The manual solution would be to check a directory for uploaded content every morning, open
the file, and then save it in a different format. This solution is slow, inefficient, and probably
could happen only once every 24 hours because you're a busy person.



You could automate the task. Were you to do that, you might write a PHP or a Node.js script
to detect when a file has been uploaded. The script would perform the conversion and send
an alert or make a log entry to confirm the conversion was successful. You could improve the
script over time to allow users to interact with the upload and conversion process.



Creative Commons Attribution Share-alike 4.0                                                         4
Were you to orchestrate the process, you might instead start with an application. Your custom
app would be designed to accept and convert files. You might run the application in a
container on your cloud, and using OpenShift, you could launch additional instances of your
app when the traffic or workload increases beyond a certain threshold.


Learning automation and orchestration
There isn't just one discipline for automation or orchestration. These are broad practices that
are applied to many different tasks across many different industries. The first step to learning,
though, is to become proficient with the technology you're meant to orchestrate and
automate. It's difficult to orchestrate (safely) the scaling a series of web servers if you don't
understand how a web server works, or what ports need to be open or closed, or what a port
is. In practice, you may not be the person opening ports or configuring the server; you could
be tasked with administrating OpenShift without really knowing or caring what's inside a
container. But basic concepts are important because they broadly apply to usability,
troubleshooting, and security.

You also need to get familiar with the most common tools of the orchestration and
automation world. Learn some Bash, start using Git and design some Git hooks, learn some
Python, get comfortable with YAML and Ansible, and try out Minikube, OKD, and OpenShift.

Orchestration and automation are important skills, both to make your work more efficient and
as something to bring to your team. Invest in it today, and get twice as much done tomorrow.




Creative Commons Attribution Share-alike 4.0                                                        5
Getting started with Minikube:
Kubernetes on your laptop

By Bryant Son

Minikube is advertised on the Hello Minikube tutorial page as a simple way to run Kubernetes
for containers.


Prerequisites
    1. You have installed either Podman or Docker.
    2. Your computer is an RHEL, CentOS, or Fedora-based workstation.
    3. You have installed a working KVM2 hypervisor, such as libvirt.
    4. If you're using Docker, you must have a working docker-machine-driver-kvm2. The
      following commands installs the driver:

       $ curl -Lo docker-machine-driver-kvm2 \
       https://storage.googleapis.com/minikube/releases/latest/docker-machine-
       driver-kvm2
       $ chmod +x docker-machine-driver-kvm2 \
       && sudo cp docker-machine-driver-kvm2 /usr/local/bin/ \
       && rm docker-machine-driver-kvm2




Download, install, and start Minikube
    1. Create a directory for the two files you will download: minikube and kubectl.

    2. Open a terminal window and run the following command to install minikube.

       $ curl -Lo minikube \
       https://storage.googleapis.com/minikube/releases/latest/minikube-linux-
       amd64




Creative Commons Attribution Share-alike 4.0                                                   6
      Note that the minikube version (for example, minikube-linux-amd64) may differ based
      on your computer's specs.

   3. Use chmod to make it executable.

       $ chmod +x minikube


   4. Move the file to the /usr/local/bin path so you can run it as a command.

       $ sudo mv minikube /usr/local/bin


   5. Install kubectl using the following command (similar to the minikube installation
      process).

       $ curl -Lo kubectl \
       https://storage.googleapis.com/kubernetes-release/release/$(curl -s \
       https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/
       linux/amd64/kubectl


      Use the curl command to determine the latest version of Kubernetes.

   6. Use chmod to make kubectl executable.

       $ chmod +x kubectl


   7. Move kubectl to the /usr/local/bin path to run it as a command.

       $ mv kubectl /usr/local/bin


   8. Run minikube start. To do so, you need to have a hypervisor available. I used KVM2,
      but you can also use Virtualbox. Make sure to run the following command as a user
      instead of root so the configuration will be stored for the user instead of root.

       $ minikube start --vm-driver=kvm2


      It can take quite a while, so wait for it.

   9. Minikube should download and start. Use the following command to make sure it was
      successful.

       $ cat ~/.kube/config




Creative Commons Attribution Share-alike 4.0                                                7
   10.Execute the following command to run Minikube as the context. The context is what
      determines which cluster kubectl is interacting with. You can see all your available
      contexts in the ~/.kube/config file.

       $ kubectl config use-context minikube


   11. Run the config file command again to check that context Minikube is there.

       $ cat ~/.kube/config


   12.Finally, run the following command to open a browser with the Kubernetes dashboard.

       $ minikube dashboard




Creative Commons Attribution Share-alike 4.0                                                 8
Getting started with Kubernetes

By Ben Finkel

Kubernetes allows you to create a portable and scalable application deployment that can be
scheduled, managed, and maintained easily. As an open source project, Kubernetes is
continually being updated and improved, and it leads the way among container cluster
management software.

Kubernetes uses various architectural components to describe the deployments it manages.

    • Pods are a group of one or more containers that share network and storage. The
      containers in a pod are considered "tightly coupled," and they are managed and
      deployed as a single unit. If an application were deployed in a more traditional model,
      the contents of the pod would always be deployed together on the same machine.

    • Nodes represents a worker machine in a Kubernetes cluster. The worker machine can
      be either physical or (more likely) virtual. A node contains all the required services to
      host a pod.

    • A cluster always requires a master node, where the controlling services (known as the
      master components) are installed. These services can be distributed on a single
      machine or across multiple machines for redundancy. They control communications,
      workload, and scheduling.

    • Deployments are a way to declaratively set a state for your pods or ReplicaSets
      (groups of pods to be deployed together). Deployments use a "desired state" format
      to describe how the deployment should look, and Kubernetes handles the actual
      deployment tasks. Deployments can be updated, rolled back, scaled, and paused at
      will.

The following tutorial explains the basics of creating a cluster, deploying an app, and creating
a proxy, then send you on your way to learning even more about Kubernetes. In this article, I


Creative Commons Attribution Share-alike 4.0                                                       9
assume you're using Minikube for a local instance of Kubernetes. Of course, you're free to use
an actual Kubernetes install instead, if you have one available to you.


Create a cluster
In your terminal, start Minikube:

$ minikube start


View the cluster information with the command:

$ kubectl cluster-info
Kubernetes is running at http://example.local:8080 [...]

List the available nodes with the command:

$ kubectl get nodes
NAME      STATUS    AGE
host01    Ready     22s



Your output may differ a little, but as long as you see similar reports, you know you're on the
right track.


Deploy an app
In the next step in the interactive tutorial, you'll deploy a containerized application to your
cluster with a deployment configuration. This describes how to create instances of your app,
and the master will schedule those instances onto nodes in the cluster.

In the interactive terminal, create a new deployment with the kubectl run command:

$ kubectl run kubernetes-bootcamp \
--image=docker.io/jocatalin/kubernetes-bootcamp:v1 --port=8080


This creates a new deployment with the name kubernetes-bootcamp from a public
repository at docker.io and overrides the default port to 8080.




Creative Commons Attribution Share-alike 4.0                                                      10
View the deployment with the command:

$ kubectl get deployments
NAME                   DESIRED    CURRENT   UP-TO-DATE    AVAILABLE     AGE
kubernetes-bootcamp     1          1           1           1             12s



The deployment is currently on a single node, because only one node is available.


Create a proxy
Now you can create a proxy into your deployed app. A pod runs on an isolated private network
that cannot be accessed from outside. The kubectl command uses an API to communicate
with the application, and a proxy is needed to expose the application for use by other
services.

Open a new terminal window and start the proxy server with the command:

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

This creates a connection between your cluster and the virtual terminal window. Notice it's
running on port 8001 on the local host.

Return to the first terminal window and run a curl command to see this in action:

$ curl http://localhost:8001/version
{ "major": "1",
"minor": "5",
"gitVersion": "v1.5.2",
"gitCommit": "3187edd66737c1265299e1ed47505cd78eb1e6d4",
"gitTreeState": "clean",
[...]



The JSON output displays the version information from the cluster itself.

You can also get a detailed output of your pod by using the command:

$ kubectl describe pods




Creative Commons Attribution Share-alike 4.0                                                  11
This output includes very important information, like the pod name, local IP address, state,
and restart count.


Moving forward
Kubernetes is a full-fledged deployment, scheduling, and scaling manager and is capable of
deciding all of the myriad details of how to deploy an app on your cluster. The few commands
explored here are just the beginning of interacting with and understanding a Kubernetes
deployment. The crucial takeaway is how fast and easy it is to do and how few details you
need to provide to use Kubernetes.

Follow the online interactive tutorial to learn more about how Kubernetes works and all that
you can do with it.




Creative Commons Attribution Share-alike 4.0                                                   12
Automate container orchestration
with Ansible modules

By Seth Kenlon

Ansible is one of the best tools for automating your work. Kubernetes is one of the best tools
for orchestrating containers. What happens when you combine the two? As you might expect,
Ansible combined with Kubernetes lets you automate your container orchestration.


Ansible modules
On its own, Ansible is basically just a framework for interpreting YAML files. Its true power
comes from its many modules. Modules are what enable you to invoke external applications
with just a few simple configuration settings in a playbook.

There are a few modules that deal directly with Kubernetes, and a few that handle related
technology like Podman and Docker. Learning a new module is often similar to learning a new
terminal command or a new API. You get familiar with a module from its documentation, you
learn what arguments it accepts, and you equate its options to how you might use the
application it interfaces with.


Access a Kubernetes cluster
To try out Kubernetes modules in Ansible, you must have access to a Kubernetes cluster. If
you don't have that, then you might try to open a trial account online, but most of those are
short term. Instead, you can install Minikube, as described on the Kubernetes website or in
Bryant Son's article in the book. Minikube provides a local instance of a single-node
Kubernetes install, allowing you to configure and interact with it as you would a full cluster.




Creative Commons Attribution Share-alike 4.0                                                      13
Before installing Minikube, you must ensure that your environment is ready to serve as a
virtualization backend. You may need to install libvirt and grant yourself permission to the
libvirt group:

$   sudo dnf install libvirt
$   sudo systemctl start libvirtd
$   sudo usermod --append --groups libvirt `whoami`
$   newgrp libvirt



Install Python modules
To prepare for using Kubernetes-related Ansible modules, you should also install a few helper
Python modules:

$ python3 -m pip install kubernetes --user
$ python3 -m pip install openshift --user



Start Kubernetes
If you're using Minikube instead of a Kubernetes cluster, use the minikube command to start
up a local, miniaturized Kubernetes instance on your computer:

$ minikube start --driver=kvm2 --kvm-network default


Wait for Minikube to initialize. Depending on your internet connection, this could take several
minutes.


Get information about your cluster
Once you've started your cluster successfully, you can get information about it with the
cluster-info option:

$ kubectl cluster-info
Kubernetes master is running at https://192.168.39.190:8443
KubeDNS is running at https://192.168.39.190:8443/api/v1/[...]/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.




Use the k8s module
The entry point for using Kubernetes through Ansible is the k8s module, which enables you to
manage Kubernetes objects from your playbooks. This module describes states resulting from

Creative Commons Attribution Share-alike 4.0                                                  14
kubectl instructions. For instance, here's how you would create a new namespace with
kubectl:

$ kubectl create namespace my-namespace


It's a simple action, and the YAML representation of the same result is similarly terse:

- hosts: localhost
tasks:
  - name: create namespace
    k8s:
    name: my-namespace
       api_version: v1
       kind: Namespace
       state: present


In this case, the host is defined as localhost, under the assumption that you're running this
against Minikube. Notice that the module in use defines the syntax of the parameters
available (such as api_version and kind).

Before using this playbook, verify it with yamllint:

$ yamllint example.yaml


Correct any errors, and then run the playbook:

$ ansible-playbook ./example.yaml


Verify that the new namespace has been created:

$ kubectl get namespaces
NAME             STATUS        AGE
[...]
my-namespace     Active        3s



Pull a container image with Podman
Containers are Linux systems, almost impossibly minimal in scope, that can be managed by
Kubernetes. Much of the container specifications have been defined by the LXC project and
Docker. A recent addition to the container toolset is Podman, which is popular because it runs
without requiring a daemon.



Creative Commons Attribution Share-alike 4.0                                                 15
With Podman, you can pull a container image from a repository, such as Docker Hub or
Quay.io. The Ansible syntax for this is simple, and all you need to know is the location of the
container, which is available from the repository's website:

     - name: pull an image
       podman_image:
         name: quay.io/jitesoft/nginx


Verify it with yamllint:

$ yamllint example.yaml


And then run the playbook:

$ ansible-playbook ./example.yaml
[WARNING]: provided hosts list is empty, only localhost is available.
Note that the implicit localhost does not match 'all'
PLAY [localhost] ************************
TASK [Gathering Facts] ************************
ok: [localhost]
TASK [create k8s namespace] ************************
ok: [localhost]
TASK [pull an image] ************************
changed: [localhost]
PLAY RECAP ************************
localhost: ok=3 changed=1 unreachable=0 failed=0
           skipped=0 rescued=0 ignored=0




Deploy with Ansible
You're not limited to small maintenance tasks with Ansible. Your playbook can interact with
Ansible in much the same way a configuration file does with kubectl. In fact, in many ways,
the YAML you know by using Kubernetes translates to your Ansible plays.




Creative Commons Attribution Share-alike 4.0                                                      16
Here's a configuration you might pass directly to kubectl to deploy an image (in this
example, a web server):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-webserver
spec:
  selector:
    matchLabels:
      run: my-webserver
  replicas: 1
  template:
    metadata:
      labels:
        run: my-webserver
    spec:
      containers:
      - name: my-webserver
        image: nginx
        ports:
        - containerPort: 80


If you know these parameters, then you mostly know the parameters required to accomplish
the same with Ansible. You can, with very little modification, move that YAML into a
definition element in your Ansible playbook:

     - name: deploy a web server
       k8s:
         api_version: v1
         namespace: my-namespace
         definition:
            kind: Deployment
               metadata:
               labels:
               app: nginx
               name: nginx-deploy
               spec:
               replicas: 1
               selector:
               matchLabels:
               app: nginx
               template:
               metadata:
               labels:
               app: nginx
               spec:


Creative Commons Attribution Share-alike 4.0                                               17
                  containers:
                     - name: my-webserver
                       image: quay.io/jitesoft/nginx
                       ports:
                       - containerPort: 80
                           protocol: TCP


After running this, you can see the deployment with kubectl, as usual:

$ kubectl -n my-namespace get pods
NAME                      READY    STATUS
nginx-deploy-7fdc9-t9wc2 1/1       Running




Modules for the cloud
As more development and deployments move to the cloud, it's important to understand how
to automate the important aspects of your cloud. The k8s and podman_image modules are
only two examples of modules related to Kubernetes and a mere fraction of modules
developed for the cloud. Take a look at your workflow, find the tasks you want to track and
automate, and see how Ansible can help you do more by doing less.




Creative Commons Attribution Share-alike 4.0                                                  18
A beginner's guide to Kubernetes
Jobs and CronJobs

By Mike Calizo

Kubernetes is the default orchestration engine for containers. Its options for controlling and
managing pods and containers include:

    1. Deployments
    2. StatefulSets
    3. ReplicaSets

Each of these features has its own purpose, with the common function to ensure that pods
run continuously. In failure scenarios, these controllers either restart or reschedule pods to
ensure the services in the pods continue running.

As the Kubernetes documentation explains, a Kubernetes Job creates one or more pods and
ensures that a specified number of the pods terminates when the task (Job) completes.

Just like in a typical operating system, the ability to perform automated, scheduled jobs
without user interaction is important in the Kubernetes world. But Kubernetes Jobs do more
than just run automated jobs, and there are multiple ways to utilize them through:

    1. Jobs
    2. CronJobs
    3. Work queues (this is beyond the scope of this article)

Sounds simple right? Well, maybe. Anyone who works on containers and microservice
applications knows that some require services to be transient so that they can do specific
tasks for applications or within the Kubernetes clusters.

In this article, I explain why Kubernetes Jobs are important, how to create Jobs and CronJobs,
and when to use them for applications running on the Kubernetes cluster.


Creative Commons Attribution Share-alike 4.0                                                     19
Differences between Kubernetes Jobs and CronJobs
Kubernetes Jobs are used to create transient pods that perform specific tasks they are
assigned to. CronJobs do the same thing, but they run tasks based on a defined schedule.

Jobs play an important role in Kubernetes, especially for running batch processes or
important ad-hoc operations. Jobs differ from other Kubernetes controllers in that they run
tasks until completion, rather than managing the desired state such as in Deployments,
ReplicaSets, and StatefulSets.


How to create Kubernetes Jobs and CronJobs
With that background in hand, you can start creating Jobs and CronJobs.

Prerequisites
To do this exercise, you need to have the following:

    1. A working Kubernetes cluster or a Minikube install
    2. The kubectl Kubernetes command line

Here is the Minikube deployment I used for this demonstration:

$ minikube version
minikube version: v1.8.1
$ kubectl cluster-info
Kubernetes master is running at https://172.17.0.59:8443
KubeDNS is running at
https://172.17.0.59:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/
proxy
$ kubectl get nodes
NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   88s   v1.17.3



Kubernetes Jobs
Just like anything else in the Kubernetes world, you can create Kubernetes Jobs with a
definition file. Create a file called sample-jobs.yaml using your favorite editor.

Here is a snippet of the file that you can use to create an example Kubernetes Job:

apiVersion: batch/v1           ## The version of the Kubernetes API
kind: Job                  ## The type of object for jobs
metadata:



Creative Commons Attribution Share-alike 4.0                                                  20
 name: job-test
spec:                  ## What state you desire for the object
 template:
   metadata:
      name: job-test
   spec:
      containers:
    - name: job
      image: busybox         ## Image used
    command: ["echo", "job-test"]   ## Command used to create logs for
verification later
 restartPolicy: OnFailure ## Restart Policy in case container failed


Next, apply the Jobs in the cluster:

$ kubectl apply -f sample-jobs.yaml


Wait a few minutes for the pods to be created. You can view the pod creation's status:

$ kubectl get pod –watch


After a few seconds, you should see your pod created successfully:

$ kubectl get pods
  NAME         READY   STATUS      RESTARTS              AGE
 job-test          0/1     Completed    0               11s


Once the pods are created, verify the Job's logs:

$ kubectl logs job-test job-test


You have created your first Kubernetes Job, and you can explore details about it:

$ kubectl describe job job-test


Clean up the Jobs:

$ kubectl delete jobs job-test



Kubernetes CronJobs
You can use CronJobs for cluster tasks that need to be executed on a predefined schedule.
As the documentation explains, they are useful for periodic and recurring tasks, like running


Creative Commons Attribution Share-alike 4.0                                                    21
backups, sending emails, or scheduling individual tasks for a specific time, such as when your
cluster is likely to be idle.

As with Jobs, you can create CronJobs via a definition file. Following is a snippet of the
CronJob file cron-test.yaml. Use this file to create an example CronJob:

apiVersion: batch/v1beta1        ## The version of the Kubernetes API
kind: CronJob          ## The type of object for Cron jobs
metadata:
  name: cron-test
spec:
  schedule: "*/1 * * * *"        ## Defined schedule using the *nix style cron
syntax
  jobTemplate:
    spec:
    template:
    spec:
      containers:
       - name: cron-test
      image: busybox      ## Image used
         args:
            - /bin/sh

             - -c
             - date; echo Hello this is Cron test
          restartPolicy: OnFailure    ## Restart Policy in case container failed


Apply the CronJob to your cluster:

$ kubectl apply -f cron-test.yaml
 cronjob.batch/cron-test created


Verify that the CronJob was created with the schedule in the definition file:

$ kubectl get cronjob cron-test
 NAME      SCHEDULE    SUSPEND    ACTIVE         LAST SCHEDULE     AGE
 cron-test    */1 * * * *   False      0            <none>         10s


After a few seconds, you can find the pods that the last scheduled job created and view the
standard output of one of the pods:

$ kubectl logs cron-test-1604870760
  Sun Nov 8 21:26:09 UTC 2020
  Hello from the Kubernetes cluster




Creative Commons Attribution Share-alike 4.0                                                  22
You have created a Kubernetes CronJob that creates an object once per execution based on
the schedule schedule: "*/1 * * * *". Sometimes the creation can be missed because
of environmental issues in the cluster. Therefore, they need to be idempotent.


Other things to know
Unlike deployments and services in Kubernetes, you can't change the same Job configuration
file and reapply it at once. When you make changes in the Job configuration file, you must
delete the previous Job from the cluster before you apply it.

Generally, creating a Job creates a single pod and performs the given task, as in the example
above. But by using completions and parallelism, you can initiate several pods, one after the
other.


Use your Jobs
You can use Kubernetes Jobs and CronJobs to manage your containerized applications. Jobs
are important in Kubernetes application deployment patterns where you need a
communication mechanism along with interactions between pods and the platforms. This may
include cases where an application needs a "controller" or a "watcher" to complete tasks or
needs to be scheduled to run periodically.




Creative Commons Attribution Share-alike 4.0                                                    23
A beginner's guide to Kubernetes
container orchestration

By Jiaqi Liu

Last fall, I took on a new role with a team that relies on Kubernetes (K8s) as part of its core
infrastructure. While I have worked with a variety of container orchestrators in my time, the job
change sent me back to the basics. Here is my take on the fundamentals you should be
familiar with if you're working with Kubernetes.

I consider Kubernetes to have clear advantages when you're working with open source
software. As an open source platform, it is cloud-agnostic, and it makes sense to build other
open source software on top of it. It also has a dedicated following with over 40,000
contributors, and because a lot of developers are already familiar with Kubernetes, it's easier
for users to integrate open source solutions built on top of K8s.


Breaking down Kubernetes into building blocks
The simplest way to break down Kubernetes is by looking at the core concepts of container
orchestrators. There are containers, which serve as foundational building blocks of work, and
then there are the components built on top of each other to tie the system together.

Components come in two core types:

    1. Workload managers: A way to host and run the containers
    2. Cluster managers: Global ways to make decisions on behalf of the cluster

In Kubernetes lingo, these roles are fulfilled by the worker nodes and the control plane that
manages the work (Kubernetes components).




Creative Commons Attribution Share-alike 4.0                                                      24
Managing the workload
Kubernetes worker nodes have a nested layer of components. At the base layer is the
container itself.




Technically, containers run in pods, which are the atomic object type within a Kubernetes
cluster. Here's how they relate:

    • Pod: A pod defines the logical unit of the application; it can contain one or more
       containers and each pod is deployed onto a node.
    • Node: This is the virtual machine serving as the worker in the cluster; pods run on the
       nodes.
    • Cluster: This consists of worker nodes and is managed by the control plane.

Each node runs an agent known as the kublet for running containers in a pod and a kube-
proxy for managing network rules.

Managing the cluster
The worker nodes manage the containers, and the Kubernetes control plane makes global
decisions about the cluster.




Creative Commons Attribution Share-alike 4.0                                                25
The control plane consists of several essential components:

    • Memory store (etcd): This is the backend store for all cluster data. While it's possible
      to run a Kubernetes cluster with a different backing store, etcd, an open source
      distributed key-value store, is the default.
    • Scheduler (kube-scheduler): The scheduler is responsible for assigning newly
      created pods to the appropriate nodes.
    • API frontend (kube-apiserver): This is the gateway from which the developer can
      interact with Kubernetes—to deploy services, fetch metrics, check logs, etc.
    • Controller manager (kube-controller-manager): This watches the cluster and
      makes necessary changes in order to keep the cluster in the desired state—such as
      scaling up nodes, maintaining the correct number of pods per replication controller,
      and creating new namespaces.

The control plane makes decisions to ensure regular operation of the cluster and abstracts
away these decisions so that the developer doesn't have to worry about them. Its
functionality is highly complex, and users of the system need to have awareness of the logical
constraints of the control plane without getting too bogged down on the details.


Using controllers and templates
The components of the cluster dictate how the cluster manages itself—but how do developers
or (human) operators tell the cluster how to run the software? This is where controllers and
templates come in.




Creative Commons Attribution Share-alike 4.0                                                   26
Controllers orchestrate the pods, and K8s has different types of controllers for different use
cases. But the key ones are Jobs, for one-off jobs that run to completion, and ReplicaSets, for
running a specified set of identical pods that provide a service.

Like everything else in Kubernetes, these concepts form the building blocks of more complex
systems that allow developers to run resilient services. Instead of using ReplicaSets directly,
you're encouraged to use Deployments instead. Deployments manage ReplicaSets on behalf
of the user and allow for rolling updates. Kubernetes Deployments ensure that only some
pods are down while they're being updated, thereby allowing for zero-downtime deploys.
Likewise, CronJobs manage Jobs and are used for running scheduled and repeated
processes. The many layers of K8s allow for better customization, but CronJobs and
Deployments suffice for most use cases.

Once you know which controller to pick to run your service, you'll need to configure it with
templating.

Anatomy of the template
The Kubernetes template is a YAML file that defines the parameters by which the containers
run. Much like any kind of configuration as code, it has its own specific format and
requirements that can be a lot to learn. Thankfully, the information you need to provide is the
same as if you were running your code against any container orchestrator:

    • Tell it what to name the application
    • Tell it where to look for the image of the container (often called the container registry)
    • Tell it how many instances to run (in the terminology above, the number of
      ReplicaSets)




Creative Commons Attribution Share-alike 4.0                                                      27
Flexibility in configuration is one of the many advantages of Kubernetes. With the different
resources and templates, you can also provide the cluster information about:

    • Environment variables
    • Location of secrets
    • Any data volumes that should be mounted for use by the containers
    • How much CPU and memory each container or pod is allowed to use
    • The specific command the container should run

And the list goes on.


Bringing it all together

Combining templates from different resources allows the user to interoperate the
components within Kubernetes and customize them for their own needs.



Creative Commons Attribution Share-alike 4.0                                                   28
In a bigger ecosystem, developers leverage Jobs, Services, and Deployments with
ConfigMaps and Secrets that combine to make an application—all of which need to be
carefully orchestrated during deployment.

Managing these coordinated steps can be done manually or with one of the common
package-management options. While it's definitely possible to roll your own deployment
against the Kubernetes API, it's often a good idea to package your configuration—especially if
you're shipping open source software that might be deployed and managed by someone not
directly on your team.

The package manager of choice for Kubernetes is Helm. It doesn't take a lot to get started
with Helm, and it allows you to package your own software for easy installation on a
Kubernetes cluster.


Smooth sailing!
The many layers and extensions sitting on top of containers can make container orchestrators
difficult to understand. But it's actually all very elegant once you've broken down the pieces
and see how they interact. Much like a real orchestra, you develop an appreciation for each
individual instrument and watch the harmony come together.

Knowing the fundamentals allows you to recognize and apply patterns and pivot from one
container orchestrator to another.




Creative Commons Attribution Share-alike 4.0                                                     29
A beginner's guide to load
balancing

By Seth Kenlon

When the personal computer was young, a household was likely to have one (or fewer)
computers in it. Children played games on it during the day, and parents did accounting or
programming or roamed through a BBS in the evening. Imagine a one-computer household
today, though, and you can predict the conflict it would create. Everyone would want to use
the computer at the same time, and there wouldn't be enough keyboard and mouse to go
around.

This is, more or less, the same scenario that's been happening to the IT industry as computers
have become more and more ubiquitous. Demand for services and servers has increased to
the point that they could grind to a halt from overuse. Fortunately, we now have the concept
of load balancing to help us handle the demand.


What is load balancing?
Load balancing is a generic term referring to anything you do to ensure the resources you
manage are distributed efficiently. For a web server's systems administrator, load balancing
usually means ensuring that the web server software (such as Nginx) is configured with
enough worker nodes to handle a spike in incoming visitors. In other words, should a site
suddenly become very popular and its visitor count quadruple in a matter of minutes, the
software running the server must be able to respond to each visitor without any of them
noticing service degradation. For simple sites, this is as simple as a one-line configuration
option, but for complex sites with dynamic content and several database queries for each
user, it can be a serious problem.




Creative Commons Attribution Share-alike 4.0                                                    30
This problem is supposed to have been solved with cloud computing, but it's not impossible
for a web app to fail to scale out when it experiences an unexpected surge.

The important thing to keep in mind when it comes to load balancing is that distributing
resources efficiently doesn't necessarily mean distributing them evenly. Not all tasks require
all available resources at all times. A smart load-balancing strategy provides resources to
users and tasks only when those resources are needed. This is often the application
developer's domain rather than the IT infrastructure's responsibility. Asynchronous
applications are vital to ensuring that a user who walks away from the computer for a coffee
break isn't occupying valuable resources on the server.


How does load balancing work?
Load balancing avoids bottlenecks by distributing a workload across multiple computational
nodes. Those nodes may be physical servers in a data center, containers in a cloud,
strategically placed servers enlisted for edge computing, separate Java Virtual Machines
(JVMs) in a complex application framework, or daemons running on a single Linux server.

The idea is to divide a large problem into small tasks and assign each task to a dedicated
computer. For a website that requires its users to log in, for instance, the website might be
hosted on Server A, while the login page and all the authentication lookups that go along with
it are hosted on Server B. This way, the process of a new user logging into an account doesn't
steal resources from other users actively using the site.

Load balancing the cloud
Cloud computing uses containers, so there aren't usually separate physical servers to handle
distinct tasks (actually, there are many separate servers, but they're clustered together to act
as one computational "brain"). Instead, a "pod" is created from several containers. When one
pod starts to run out of resources due to its user or task load, an identical pod is generated.
Pods share storage and network resources, and each pod is assigned to a compute node as
it's created. Pods can be created or destroyed on demand as the load requires so that users
experience consistent quality of service regardless of how many users there are.

Edge computing
Edge computing takes the physical world into account when load balancing. The cloud is
naturally a distributed system, but in practice, a cloud's nodes are usually concentrated in a
few data centers. The further a user is from the data center running the cloud, the more


Creative Commons Attribution Share-alike 4.0                                                      31
physical barriers they must overcome for optimal service. Even with fiber connections and
proper load balancing, the response time of a server located 3,000 miles away is likely greater
than the response time of something just 300 miles away.

Edge computing brings compute nodes to the "edge" of the cloud in an attempt to bridge the
geographic divide, forming a sort of satellite network for the cloud, so it also plays a part in a
good load-balancing effort.


What is a load-balancing algorithm?
There are many strategies for load balancing, and they range in complexity depending on
what technology is involved and what the requirements demand. Load balancing doesn't have
to be complicated, and it's important, even when using specialized software like Kubernetes or
Keepalived, to start load balancing from inception.

Don't rely on containers to balance the load when you could design your application to take
simple precautions on its own. If you design your application to be modular and ephemeral
from the start, then you'll benefit from the load balancing opportunities made available by
clever network design, container orchestration, and whatever tomorrow's technology brings.

Some popular algorithms that can guide your efforts as an application developer or network
engineer include:

    • Assign tasks to servers sequentially (this is often called round-robin).
    • Assign tasks to the server that's currently the least busy.
    • Assign tasks to the server with the best response time.
    • Assign tasks randomly.

These principles can be combined or weighted to favor, for instance, the most powerful server
in a group when assigning particularly complex tasks. Orchestration is commonly used so that
an administrator doesn't have to drum up the perfect algorithm or strategy for load balancing,
although sometimes it's up to the admin to choose which combination of load balancing
schemes to use.


Expect the unexpected
Load balancing isn't really about ensuring that all your resources are used evenly across your
network. Load balancing is all about guaranteeing a reliable user experience even when the
unexpected happens. Good infrastructure can withstand a computer crash, application


Creative Commons Attribution Share-alike 4.0                                                     32
overload, onslaught of network traffic, and user errors. Think about how your service can be
resilient and design load balancing accordingly from the ground up.




Creative Commons Attribution Share-alike 4.0                                                   33
A guide to Kubernetes
architecture

By Nived Velayudhan

You use Kubernetes to orchestrate containers. It's an easy description to say, but
understanding what that actually means and how you accomplish it is another matter entirely.
If you're running or managing a Kubernetes cluster, then you know that Kubernetes consists of
one computer that gets designated as the control plane, and lots of other computers that get
designated as worker nodes. Each of these has a complex but robust stack making
orchestration possible, and getting familiar with each component helps understand how it all
works.




Creative Commons Attribution Share-alike 4.0                                               34
                                  (Nived Velayudhan, CC BY-SA 4.0)



Control plane components
You install Kubernetes on a machine called the control plane. It's the one running the
Kubernetes daemon, and it's the one you communicate with when starting containers and
pods. The following sections describe the control plane components.

Etcd
Etcd is a fast, distributed, and consistent key-value store used as a backing store for
persistently storing Kubernetes object data such as pods, replication controllers, secrets, and
services. Etcd is the only place where Kubernetes stores cluster state and metadata. The only


Creative Commons Attribution Share-alike 4.0                                                 35
component that talks to etcd directly is the Kubernetes API server. All other components read
and write data to etcd indirectly through the API server.

Etcd also implements a watch feature, which provides an event-based interface for
asynchronously monitoring changes to keys. Once you change a key, its watchers get notified.
The API server component heavily relies on this to get notified and move the current state of
etcd towards the desired state.

Why should the number of etcd instances be an odd number?

You would typically have three, five, or seven etcd instances running in a high-availability (HA)
environment, but why? Because etcd is a distributed data store. It is possible to scale it
horizontally but also you need to ensure that the data in each instance is consistent, and for
this, your system needs to reach a consensus on what the state is. Etcd uses the RAFT
consensus algorithm for this.

The algorithm requires a majority (or quorum) for the cluster to progress to the next state. If
you have only two ectd instances and either of them fails, the etcd cluster can't transition to a
new state because no majority exists. If you have three ectd instances, one instance can fail
but still have a majority of instances available to reach a quorum.

API server
The API server is the only component in Kubernetes that directly interacts with etcd. All other
components in Kubernetes must go through the API server to work with the cluster state,
including the clients (kubectl). The API server has the following functions:

    • Provides a consistent way of storing objects in etcd.
    • Performs validation of those objects so clients can't store improperly configured
      objects (which could happen if they write directly to the etcd datastore).
    • Provides a RESTful API to create, update, modify, or delete a resource.
    • Provides optimistic concurrency locking, so other clients never override changes to an
      object in the event of concurrent updates.
    • Performs authentication and authorization of a request that the client sends. It uses
      the plugins to extract the client's username, user ID, groups the user belongs to, and
      determine whether the authenticated user can perform the requested action on the
      requested resource.
    • Responsible for admission control if the request is trying to create, modify, or delete a
      resource. For example, AlwaysPullImages, DefaultStorageClass, and ResourceQuota.


Creative Commons Attribution Share-alike 4.0                                                     36
    • Implements a watch mechanism (similar to etcd) for clients to watch for changes. This
      allows components such as the Scheduler and Controller Manager to interact with the
      API Server in a loosely coupled manner.

Controller Manager
In Kubernetes, controllers are control loops that watch the state of your cluster, then make or
request changes where needed. Each controller tries to move the current cluster state closer
to the desired state. The controller tracks at least one Kubernetes resource type, and these
objects have a spec field that represents the desired state.

Controller examples:

    • Replication Manager (a controller for ReplicationController resources)
    • ReplicaSet, DaemonSet, and Job controllers
    • Deployment controller
    • StatefulSet controller
    • Node controller
    • Service controller
    • Endpoints controller
    • Namespace controller
    • PersistentVolume controller

Controllers use the watch mechanism to get notified of changes. They watch the API server
for changes to resources and perform operations for each change, whether it's a creation of a
new object or an update or deletion of an existing object. Most of the time, these operations
include creating other resources or updating the watched resources themselves. Still, because
using watches doesn't guarantee the controller won't miss an event, they also perform a re-
list operation periodically to ensure they haven't missed anything.

The Controller Manager also performs lifecycle functions such as namespace creation and
lifecycle, event garbage collection, terminated-pod garbage collection, cascading-deletion
garbage collection, and node garbage collection. See Cloud Controller Manager for more
information.

Scheduler
The Scheduler is a control plane process that assigns pods to nodes. It watches for newly
created pods that have no nodes assigned. For every pod that the Scheduler discovers, the
Scheduler becomes responsible for finding the best node for that pod to run on.

Creative Commons Attribution Share-alike 4.0                                                   37
Nodes that meet the scheduling requirements for a pod get called feasible nodes. If none of
the nodes are suitable, the pod remains unscheduled until the Scheduler can place it. Once it
finds a feasible node, it runs a set of functions to score the nodes, and the node with the
highest score gets selected. It then notifies the API server about the selected node. They call
this process binding.

The selection of nodes is a two-step process:

    1. Filtering the list of all nodes to obtain a list of acceptable nodes to which you can
      schedule the pod (for example, the PodFitsResources filter checks whether a
      candidate node has enough available resources to meet a pod's specific resource
      requests).
    2. Scoring the list of nodes obtained from the first step and ranking them to choose the
      best node. If multiple nodes have the highest score, a round-robin process ensures the
      pods get deployed across all of them evenly.

Factors to consider for scheduling decisions include:

    • Does the pod request hardware/software resources? Is the node reporting a memory
      or a disk pressure condition?
    • Does the node have a label that matches the node selector in the pod specification?
    • If the pod requests binding to a specific host port, is that port available?
    • Does the pod tolerate the taints of the node?
    • Does the pod specify node affinity or anti-affinity rules?

The Scheduler doesn't instruct the selected node to run the pod. All the Scheduler does is
update the pod definition through the API server. The API server then notifies the kubelet
that the pod got scheduled through the watch mechanism. Then the kubelet service on the
target node sees that the pod got scheduled to its node, it creates and runs the pod's
containers.




Worker node components
Worker nodes run the kubelet agent, which permits them to get recruited by the control plane
to process jobs. Similar to the control plane, the worker node uses several different
components to make this possible. The following sections describe the worker node
components.


Creative Commons Attribution Share-alike 4.0                                                   38
Kubelet
Kubelet is an agent that runs on each node in the cluster and is responsible for everything
running on a worker node. It ensures that the containers run in the pod.

The main functions of kubelet service are:

    • Register the node it's running on by creating a node resource in the API server.
    • Continuously monitor the API server for pods that got scheduled to the node.
    • Start the pod's containers by using the configured container runtime.
    • Continuously monitor running containers and report their status, events, and resource
      consumption to the API server.
    • Run the container liveness probes, restart containers when the probes fail and
      terminate containers when their pod gets deleted from the API server (notifying the
      server about the pod termination).

Service proxy
The service proxy (kube-proxy) runs on each node and ensures that one pod can talk to
another pod, one node can talk to another node, and one container can talk to another
container. It is responsible for watching the API server for changes on services and pod
definitions to maintain that the entire network configuration is up to date. When a service gets
backed by more than one pod, the proxy performs load balancing across those pods.

The kube-proxy got its name because it began as an actual proxy server that used to accept
connections and proxy them to the pods. The current implementation uses iptables rules to
redirect packets to a randomly selected backend pod without passing them through an actual
proxy server.

A high-level view of how it works:

    • When you create a service, a virtual IP address gets assigned immediately.
    • The API server notifies the kube-proxy agents running on worker nodes that a new
      service exists.
    • Each kube-proxy makes the service addressable by setting up iptables rules, ensuring
      each service IP/port pair gets intercepted and the destination address gets modified to
      one of the pods that back the service.
    • Watches the API server for changes to services or its endpoint objects.




Creative Commons Attribution Share-alike 4.0                                                  39
Container runtime
There are two categories of container runtimes:

    • Lower-level container runtimes: These focus on running containers and setting up
      the namespace and cgroups for containers.
    • Higher-level container runtimes (container engine): These focus on formats,
      unpacking, management, sharing of images, and providing APIs for developers.

Container runtime takes care of:

    • Pulls the required container image from an image registry if it's not available locally.
    • Extracts the image onto a copy-on-write filesystem and all the container layers overlay
      to create a merged filesystem.
    • Prepares a container mount point.
    • Sets the metadata from the container image like overriding CMD, ENTRYPOINT from
      user inputs, and sets up SECCOMP rules, ensuring the container runs as expected.
    • Alters the kernel to assign isolation like process, networking, and filesystem to this
      container.
    • Alerts the kernel to assign some resource limits like CPU or memory limits.
    • Pass system call (syscall) to the kernel to start the container.
    • Ensures that the SElinux/AppArmor setup is proper.


Working together
System-level components work together to ensure that each part of a Kubernetes cluster can
realize its purpose and perform its functions. It can sometimes be overwhelming (when you're
deep into editing a YAML file) to understand how your requests get communicated within
your cluster. Now that you have a map of how the pieces fit together, you can better
understand what's happening inside Kubernetes, which helps you diagnose problems,
maintain a healthy cluster, and optimize your own workflow.




Creative Commons Attribution Share-alike 4.0                                                     40
Getting started with OKD on your
Linux desktop

By: Ricardo Gerardi

OKD is the open source upstream community edition of Red Hat's OpenShift container
platform. OKD is a container management and orchestration platform based on OCI
containers and Kubernetes.

OKD is a complete solution to manage, deploy, and operate containerized applications that
includes an easy-to-use web interface, automated build tools, routing capabilities, and
monitoring and logging aggregation features. Of course, it also has all the features provided
by Kubernetes natively.

OKD provides several deployment options aimed at different requirements with single or
multiple master nodes, high-availability capabilities, logging, monitoring, and more. You can
create OKD clusters as small or as large as you need.

In addition to these deployment options, OKD provides a way to create a local, all-in-one
cluster on your own machine using the oc command-line tool. This is a great option if you
want to try OKD locally without committing the resources to create a larger multi-node
cluster, or if you want to have a local cluster on your machine as part of your workflow or
development process. In this case, you can create and deploy the applications locally using
the same APIs and interfaces required to deploy the application on a larger scale. This process
ensures a seamless integration that prevents issues with applications that work in the
developer's environment but not in production.

This tutorial shows you how to create an OKD cluster using oc cluster up in a Linux box.




Creative Commons Attribution Share-alike 4.0                                                    41
1. Install Docker
The oc cluster up command creates a local OKD cluster on your machine using Docker
containers. In order to use this command, you need Podman or Docker installed on your
machine. If either Podman or Docker is not installed on your system, install one by using your
distribution's package manager. For example, on Fedora, CentOS, or RHEL:

$ sudo dnf install podman


Or use Docker:

$ sudo dnf install docker




2. Configure Docker insecure registry
When using Docker, you need to configure it to allow the communication with an insecure
registry on address 172.30.0.0/16. This insecure registry will be deployed with your local OKD
cluster later.

On CentOS or RHEL, edit the file /etc/docker/daemon.json by adding these lines:

{
"insecure-registries": ["172.30.0.0/16"]
}


On Fedora, edit the file /etc/containers/registries.conf by adding these lines:

[registries.insecure]
registries = ['172.30.0.0/16']




3. Start Docker
Docker operates through a daemon, so you must start Docker, create a system group named
docker and assign this group to your user so you can run Docker commands with your own
user, without requiring root or sudo access. This allows you to create your OKD cluster using
your own user. If you're using Podman, this step isn't required because Podman doesn't use a
daemon.

For example, these are the commands to create the group and assign it to my local user,
ricardo:


Creative Commons Attribution Share-alike 4.0                                                    42
$ sudo groupadd docker
$ sudo usermod -a -G docker ricardo


You need to log out and log back in to see the new group association. After logging back in,
run the id command and ensure you're a member of the docker group:

$ id
uid=1000(ricardo) gid=1000(ricardo) groups=1000(ricardo),10(wheel),1001(docker)
context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023


Now start and enable the Docker daemon like this:

$ sudo systemctl start docker
$ sudo systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service
to /usr/lib/systemd/system/docker.service.


Verify that Docker is running:

$ docker version
Client:
Version:             1.13.1
API version:         1.26
Package version:     docker-1.13.1-75.git8633870.el7.centos.x86_64
Go version:          go1.9.4
Git commit:          8633870/1.13.1
Built:               Fri Sep 28 19:45:08 2018
OS/Arch:             linux/amd64
[...]

Ensure that the insecure registry option has been enabled by running docker info and
looking for these lines:

$ docker info
... Skipping long output ...
Insecure Registries:
 172.30.0.0/16
 127.0.0.0/8




4. Open firewall ports
Whether you're using Podman or Docker, you must next open firewall ports to ensure your
OKD containers can communicate with the master API. By default, some distributions have
the firewall enabled, which blocks required connectivity from the OKD containers to the

Creative Commons Attribution Share-alike 4.0                                                   43
master API. If your system has the firewall enabled, you need to add rules to allow
communication on ports 8443/tcp for the master API and 53/udp for DNS resolution on the
Docker bridge subnet.

For CentOS, RHEL, and Fedora, you can use the firewall-cmd command-line tool to add the
rules. For other distributions, you can use the provided firewall manager, such as UFW or
iptables.

Before adding the firewall rules, obtain the Docker bridge network subnet's address, like this:

$ docker network inspect bridge | grep Subnet
  "Subnet": "172.17.0.0/16",


Enable the firewall rules using this subnet. For CentOS, RHEL, and Fedora, use firewall-cmd
to add a new zone:

$ sudo firewall-cmd --permanent --new-zone okdlocal
success


Include the subnet address you obtained before as a source to the new zone:

$ sudo firewall-cmd --permanent --zone okdlocal --add-source 172.17.0.0/16
success


Next, add the required rules to the okdlocal zone:

$ sudo firewall-cmd --permanent --zone okdlocal --add-port 8443/tcp
success
$ sudo firewall-cmd --permanent --zone okdlocal --add-port 53/udp
success
$ sudo firewall-cmd --permanent --zone okdlocal --add-port 8053/udp
success


Finally, reload the firewall to enable the new rules:

$ sudo firewall-cmd --reload
success




Creative Commons Attribution Share-alike 4.0                                                  44
Ensure that the new zone and rules are in place:

 $ sudo firewall-cmd --zone okdlocal --list-sources
 172.17.0.0/16
 $ sudo firewall-cmd --zone okdlocal --list-ports
 8443/tcp 53/udp 8053/udp


Your system is ready to start the cluster. It's time to download the OKD client tools.


5. Download the OKD client tools
To deploy a local OKD cluster using oc, you need to download the OKD client tools package.
For some distributions, like CentOS and Fedora, this package can be downloaded as an RPM
from the official repositories. Please note that these packages may follow the distribution
update cycle and usually are not the most recent version available.

For this tutorial, download the OKD client package directly from the official GitHub repository
so you can get the most recent version available. At the time of writing, this was OKD v3.11.

Go to the OKD downloads page to get the link to the OKD tools for Linux, then download it
with wget:

 $ cd ~/Downloads/
 $ wget https://github.com/openshift/origin/releases/download/v3.11.0/openshift-
 origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz


Uncompress the downloaded package:

 $ tar -xzvf openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz


Finally, to make it easier to use the oc command systemwide, move it to a directory included
in your $PATH variable. A good location is /usr/local/bin:

 $ sudo cp openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit/oc
 /usr/local/bin/


One of the nicest features of the oc command is that it's a static single binary. You don't need
to install it to use it.




Creative Commons Attribution Share-alike 4.0                                                    45
Check that the oc command is working:

$ oc version
oc v3.11.0+0cbc58b
kubernetes v1.11.0+d4cacc0
features: Basic-Auth GSSAPI Kerberos SPNEGO




6. Start your OKD cluster
Once you have all the prerequisites in place, start your local OKD cluster by running this
command:

$ oc cluster up


This command downloads all required images from Docker Hub, and starts the containers.
The first time you run it, it takes a few minutes to complete. When it's finished, you see:

... Skipping long output ...
OpenShift server started.
The server is accessible via web console at:
    https://127.0.0.1:8443
You are logged in as:
    User:     developer
    Password: <any value>
To login as administrator:
    oc login -u system:admin




Creative Commons Attribution Share-alike 4.0                                                  46
Access the OKD web console by using the browser and navigating to https://127.0.0.1:8443




From the command line, you can check if the cluster is running by entering this command:

$ oc cluster status
Web console URL: https://127.0.0.1:8443/console/
Config is at host directory
Volumes are at host directory
Persistent volumes are at host directory
/home/ricardo/openshift.local.clusterup/openshift.local.pv
Data will be discarded when cluster is destroyed


You can also verify your cluster is working by logging in as the system:admin user and
checking available nodes using the oc command-line tool:

$ oc login -u system:admin
Logged into "https://127.0.0.1:8443" as "system:admin" using existing
credentials.
You have access to the following projects and can switch between them with 'oc
project <projectname>':
    default
    kube-dns
    kube-proxy
    kube-public


Creative Commons Attribution Share-alike 4.0                                               47
     kube-system
  * myproject
     openshift
     openshift-apiserver
     openshift-controller-manager
     openshift-core-operators
     openshift-infra
     openshift-node
     openshift-service-cert-signer
     openshift-web-console
Using project "myproject".
$ oc get nodes
NAME         STATUS    ROLES      AGE               VERSION
localhost    Ready     <none>     52m               v1.11.0+d4cacc0


Since this is a local, all-in-one cluster, you see only localhost in the nodes list.


7. Smoke-test your cluster
Now that your local OKD cluster is running, create a test app to smoke-test it. Use OKD to
build and start the sample application so you can ensure the different components are
working.

Start by logging in as the developer user:

$ oc login -u developer
Logged into "https://127.0.0.1:8443" as "developer" using existing credentials.
You have one project on this server: "myproject"
Using project "myproject".


You're automatically assigned to a new, empty project named myproject. Create a sample
PHP application based on an existing GitHub repository, like this:

$ oc new-app php:5.6~https://github.com/rgerardi/ocp-smoke-test.git
--> Found image 92ed8b3 (5 months old) in image stream "openshift/php" under tag
"5.6" for "php:5.6"
    Apache 2.4 with PHP 5.6
    -----------------------
    PHP 5.6 available as container is a base platform for building and running
various PHP 5.6 applications and frameworks. PHP is an HTML-embedded scripting
language. [...]
    Tags: builder, php, php56, rh-php56
    * A source build using source code from https://github.com/rgerardi/ocp-
smoke-test.git will be created




Creative Commons Attribution Share-alike 4.0                                                 48
       * The resulting image will be pushed to image stream tag "ocp-smoke-
test:latest"
       * Use 'start-build' to trigger a new build
    * This image will be deployed in deployment config "ocp-smoke-test"
    * Ports 8080/tcp, 8443/tcp will be load balanced by service "ocp-smoke-test"
       * Other containers can access this service through the hostname "ocp-smoke-
test"
--> Creating resources ...
    imagestream.image.openshift.io "ocp-smoke-test" created
    buildconfig.build.openshift.io "ocp-smoke-test" created
    deploymentconfig.apps.openshift.io "ocp-smoke-test" created
    service "ocp-smoke-test" created
--> Success
    Build scheduled, use 'oc logs -f bc/ocp-smoke-test' to track its progress.
    Application is not exposed. You can expose services to the outside world by
xecuting one or more of the commands below:
      'oc expose svc/ocp-smoke-test'
    Run 'oc status' to view your app.


OKD starts the build process, which clones the provided GitHub repository, compiles the
application (if required), and creates the necessary images. You can follow the build process
by tailing its log with this command:

$ oc logs -f bc/ocp-smoke-test
Cloning "https://github.com/rgerardi/ocp-smoke-test.git" ...
        Commit: 391a475713d01ab0afab700bab8a3d7549c5cc27 (Create index.php)
        Author: Ricardo Gerardi <ricardo.gerardi@gmail.com>
        Date:   Tue Oct 2 13:47:25 2018 -0400
Using
172.30.1.1:5000/openshift/php@sha256:f3c95020fa870fcefa7d1440d07a2b947834b87bdaf0
00588e84ef4a599c7546 as the s2i builder image
---> Installing application source...
=> sourcing 20-copy-config.sh ...
---> 04:53:28     Processing additional arbitrary httpd configuration provided by
s2i ...
=> sourcing 00-documentroot.conf ...
=> sourcing 50-mpm-tuning.conf ...
=> sourcing 40-ssl-certs.sh ...
Pushing image 172.30.1.1:5000/myproject/ocp-smoke-test:latest ...
Pushed 1/10 layers, 10% complete
Push successful


After the build process completes, OKD starts the application automatically by running a new
pod based on the created image. You can see this new pod with this command:

$ oc get pods



Creative Commons Attribution Share-alike 4.0                                                49
NAME                          READY       STATUS        RESTARTS     AGE
ocp-smoke-test-1-build        0/1         Completed     0            1m
ocp-smoke-test-1-d8h76        1/1         Running       0            7s


You can see two pods are created; the first one (with the status Completed) is the pod used
to build the application. The second one (with the status Running) is the application itself.

In addition, OKD creates a service for this application. Verify it by using this command:

$ oc get service
NAME             TYPE             CLUSTER-IP          EXTERNAL-IP     PORT(S)
ocp-smoke-test   ClusterIP        172.30.232.241      <none>          8080/TCP,8443/TCP


Finally, expose this service externally using OKD routes so you can access the application
from a local browser:

$ oc expose svc ocp-smoke-test
route.route.openshift.io/ocp-smoke-test exposed
$ oc get route
NAME      HOST/PORT   PATH      SERVICES        PORT       TERMINATION    WILDCARD
ocp-smo.. ocp-smoke-..ct.127.0.0.1.nip.io       ocp-smoke-test   8080-tcp    None


Verify that your new application is running by navigating to http://ocp-smoke-test-
myproject.127.0.0.1.nip.io in a web browser:




Creative Commons Attribution Share-alike 4.0                                                    50
OKD sample web application

You can also see the status of your application by logging into the OKD web console:




Creative Commons Attribution Share-alike 4.0                                           51
Learn more
You can find more information about OKD on the official site, which includes a link to the OKD
documentation.



If this is your first time working with OKD/OpenShift, you can learn the basics of the platform,
including how to build and deploy containerized applications, through the Interactive Learning
Portal. Another good resource is the official OpenShift YouTube channel.




Creative Commons Attribution Share-alike 4.0                                                  52