.. _kubernetes:
Kubernetes\*
############
This tutorial describes how to install, configure, and start the `Kubernetes
container orchestration system`_ on |CL-ATTR|.
A Kubernetes cluster can be setup on |CL| using the |CL| cloud-native-setup
scripts to automate the process or can be setup through a manual step-by-step
process. This tutorial covers both scenarios.
.. contents::
:local:
:depth: 1
Background
***********
|CL| has builtin integrations to make setting up Kubernetes using a variety of
`container runtimes
`_.
For more background information see:
* `What is Kubernetes?`_
* `What is a Container Network Interface (CNI)?`_
* `What is a Container Runtime Interface (CRI)?`_
* `What is CRI+O?`_
* `What is containerd?`_
* `What is Docker?`_
* `What is Kata Containers\*?`_
Prerequisites
*************
This tutorial assumes you have already installed |CL|. For detailed
instructions on installing |CL| on a bare metal system, follow the :ref:`bare
metal installation tutorial`.
#. Review and make sure the `requirements for kubeadm
`_
are satisfied for the host system.
#. Before you continue, update your |CL| installation with the following
command:
.. code-block:: bash
sudo swupd update
Learn about the benefits of having an up-to-date system for cloud
orchestration on the :ref:`swupd-guide` page.
#. Kubernetes, a set of supported :abbr:`CRI (Container Runtime Interface)`
runtimes, :abbr:`CNI (Container Network Interface)` and `cloud-native-setup
scripts`_ are included in the `cloud-native-basic`_ bundle. Install the
cloud-native-basic bundle to get these components:
.. code-block:: bash
sudo swupd bundle-add cloud-native-basic
Set up Kubernetes automatically
*******************************
|CL| provides `cloud-native-setup scripts`_ to automate system setup and
Kubernetes cluster initialization which allows you to get a cluster up and
running quickly.
.. note::
By default, the scripts will update |CL| to the latest version, set up the
system as a Kubernetes master-node with **canal for container networking**
and **crio for container runtime**, and taint the master node to allow
workloads to run on it. Kata is installed as an optional alternative
runtime. The script can be configured to use other CNI's and CRI's by
following the directions on the `README
`_.
See `What is a Container Network Interface (CNI)?`_ and `What is a
Container Runtime Interface (CRI)?`_ for more information.
.. important::
If network proxy settings are required for Internet connectivity, configure
them now because the scripts will propagate proxy configuration based on
the running configuration. It is especially important to set the
:command:`no_proxy` variable appropriately for Kubernetes.
The script will also modify the :file:`/etc/environment` and
:file:`/etc/profile.d/proxy.sh` files, if they exist, with the proxy
environment variables in the running shell when the script is executed.
See the `Setting proxy servers for Kubernetes`_ section for details.
#. Run the :file:`system-setup.sh` script to configure the |CL| system
settings.
.. code-block:: bash
sudo /usr/share/clr-k8s-examples/setup_system.sh
#. Stop docker and containerd to avoid conflicting CRIs being detected. The
scripts use CRIO for the CRI.
.. code-block:: bash
sudo systemctl stop docker
sudo systemctl stop containerd
#. Install git as it's a dependency of the :file:`create_stack.sh`.
.. code-block:: bash
sudo swupd bundle-add git
#. Run the :file:`create_stack.sh` script to initialize the Kubernetes node
and setup a container network plugin.
.. code-block:: bash
sudo /usr/share/clr-k8s-examples/create_stack.sh minimal
#. Follow the output on the screen and continue onto the section on `using
your cluster <#use-your-cluster>`_.
Uninstalling
============
#. If you need to delete the Kubernetes cluster or want to start from scratch
run the :file:`reset_stack.sh` script.
.. warning::
This will stop components in the stack including Kubernetes, all CNI and
CRIs **and will delete** all containers and networks.
.. code-block:: bash
sudo /usr/share/clr-k8s-examples/reset_stack.sh
Set up Kubernetes manually
**************************
Configure host system
=====================
This tutorial uses the basic default Kubernetes configuration to get started.
You can customize your Kubernetes configuration according to your specific
deployment and security needs.
The Kubernetes administration tool, :command:`kubeadm`, performs some
"`preflight checks`_" when initializing and starting a cluster. The steps
below are necessary to ensure those preflight checks pass successfully.
#. Enable IP forwarding:
- Create the file :file:`/etc/sysctl.d/60-k8s.conf` to set the
:command:`net.ipv4.ip_forward` parameter
.. code-block:: bash
sudo mkdir -p /etc/sysctl.d/
sudo tee /etc/sysctl.d/99-kubernetes-cri.conf > /dev/null </dev/null
sudo swapoff -a
.. note::
Kubernetes is designed to work without swap. Performance degradation of other workloads can occur
with swap disabled on systems with constrained memory resources.
#. Add the the system's hostname to the :file:`/etc/hosts` file. Kubernetes
will read this file to locate the master host.
.. code-block:: bash
echo "127.0.0.1 localhost `hostname`" | sudo tee --append /etc/hosts
#. Enable the kubelet agent service to start at boot automatically:
.. code-block:: bash
sudo systemctl enable kubelet.service
.. important::
If network proxy settings are required for Internet connectivity, configure
them now because the scripts will propagate proxy configuration based on
the running configuration. It is especially important to set the
:command:`no_proxy` variable for Kubernetes. See the `Setting proxy servers
for Kubernetes`_ section for details.
Initialize the master node
**************************
In Kubernetes, a master node is part of the `Kubernetes Control Plane
`_.
Initializing a new Kubernetes cluster involves crafting a :command:`kubeadm
init` command. Adding parameters to this command can control the fundamental
operating components of the cluster. This means it is important to understand
and choose network and runtime options before running a :command:`kubeadm
init` command.
Choose a pod network add-on
===========================
See `What is a Container Network Interface (CNI)?`_ for information on what
pod network add-ons and CNIs.
It is important to decide which CNI will be used early because some pod
network add-ons require configuration during cluster initialization. Check
whether or not your add-on requires special flags when you initialize the
master control plane.
If your chosen network add-on requires appending to the :command:`kubeadm
init` command, make note of it before continuing. For example, if you choose
the *flannel* pod network add-on, then in later steps you must add the
following to the :command:`kubeadm init` command:
.. code-block:: console
--pod-network-cidr 10.244.0.0/16
.. important::
The version of CNI plugins installed needs to be compatible with the
version of Kubernetes that is installed otherwise the cluster may fail.
Check the Kubernetes version with :command:`kubeadm version -o short` and
refer to the documentation of the CNI plugins to obtain a compatible
version.
Choose a container runtime
==========================
See `What is a Container Runtime Interface (CRI)?`_ for more information on
what a CRI is.
|CL| supports Kubernetes with the various runtimes
below with or without `Kata Containers`_:
* `CRI+O`_
* `containerd`_
* `Docker`_
The container runtime that you choose will dictate the steps necessary to
initialize the master cluster with :command:`kubeadm init`.
CRI+O
-----
For information on CRI+O as a Kubernetes CRI, see `What is
CRI+O?`_. To use CRI+O as the Kubernetes CRI:
#. Start the CRI-O service and enable it to run at boot automatically:
.. code-block:: bash
sudo systemctl enable --now crio.service
When the crio service starts for the first time, it will create a
configuration file for crio at :file:`/etc/crio/crio.conf`.
#. Run the kubeadm command to initialize the master node with the
:command:`--cri-socket` parameter:
.. important::
You may need to add additional parameters to the command below,
depending the pod network addon in use.
In this example, the :command:`--pod-network-cidr 10.244.0.0/16`
parameter is to use *flannel* as the pod networking. See `Choose a pod
network add-on`_ for more information.
.. code-block:: bash
sudo kubeadm init \
--cri-socket=unix:///run/crio/crio.sock \
--pod-network-cidr 10.244.0.0/16
#. (Optional) By default, CRI+O will use runc as the default
runtime. CRI+O can optionally provide Kata Containers as a runtime. See
the `Add the Kata runtime to Kubernetes`_ section for details.
With CRI+O, the `Kata Containers`_ can be set as the runtime with a
per-pod *RuntimeClass* annotation.
.. note::
If you are using CRI-O + Kata Containers as the runtime and choose the
*flannel* for pod networking (see `Choose a pod network add-on`_), the
:file:`/etc/crio/crio.conf` file needs to include the value below. On
|CL| this is done automatically.
.. code-block:: console
[crio.runtime]
manage_network_ns_lifecycle = true
#. Once the cluster initialization is complete, continue reading about how to
`Use your cluster`_.
containerd
----------
For information on containerd as as Kubernetes CRI, see `What is
containerd?`_. To use containerd as the Kubernetes CRI:
#. Start the containerd service and enable it to run at boot automatically:
.. code-block:: bash
sudo systemctl enable --now containerd.service
#. Configure kubelet to use containerd. and reload the service.
.. code-block:: bash
sudo mkdir -p /etc/systemd/system/kubelet.service.d/
cat << EOF | sudo tee /etc/systemd/system/kubelet.service.d/0-containerd.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF
#. Configure kubelet to use systemd as the cgroup driver. and reload the
service.
.. code-block:: bash
sudo mkdir -p /etc/systemd/system/kubelet.service.d/
cat << EOF | sudo tee /etc/systemd/system/kubelet.service.d/10-cgroup-driver.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--cgroup-driver=systemd"
EOF
#. Reload the systemd manager configuration.
.. code:: bash
sudo systemctl daemon-reload
#. Run the kubeadm command to initialize the master node with the
:command:`--cri-socket` parameter:
.. important::
You may need to add additional parameters to the command below,
depending the pod network addon in use.
In this example, the :command:`--pod-network-cidr 10.244.0.0/16`
parameter is to use *flannel* as the pod networking. See `Choose a pod
network add-on`_ for more information.
.. code-block:: bash
sudo kubeadm init \
--cri-socket=/run/containerd/containerd.sock
--pod-network-cidr 10.244.0.0/16
#. (Optional) By default, containerd will use runc as the default
runtime. containerd can optionally provide Kata Containers as a runtime.
See the `Add the Kata runtime to Kubernetes`_ section for details.
With containerd, the `Kata Containers`_ can be set as the runtime with a
per-pod *RuntimeClass* annotation.
#. Once the cluster initialization is complete, continue reading about how to
`Use your cluster`_.
Docker
------
For information on Docker, see `What is Docker?`_. To use Docker as the
Kubernetes container runtime:
#. Make sure Docker is installed:
.. code:: bash
sudo swupd bundle-add containers-basic
#. Start the Docker service and enable it to start automatically at boot:
.. code::
sudo systemctl enable --now docker.service
#. Configure kubelet to use the |CL| directory for cni-plugins and reload the
service.
.. code-block:: bash
sudo mkdir -p /etc/systemd/system/kubelet.service.d/
cat << EOF | sudo tee /etc/systemd/system/kubelet.service.d/0-cni.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--cni-bin-dir=/usr/libexec/cni"
EOF
.. code:: bash
sudo systemctl daemon-reload
#. Run the kubeadm command to initialize the master node:
.. important::
You may need to add additional parameters to the command below,
depending the pod network addon in use.
In this example, the :command:`--pod-network-cidr 10.244.0.0/16`
parameter is to use *flannel* as the pod networking. See `Choose a pod
network add-on`_ for more information.
.. code:: bash
sudo kubeadm init \
--pod-network-cidr 10.244.0.0/16
#. Once the cluster initialization is complete, continue reading about how to
`Use your cluster`_.
Add the Kata runtime to Kubernetes
-----------------------------------
For information on Kata as a container runtime, see `What is Kata Containers\*?`_.
Using Kata Containers is optional.
You can use *kata-deploy* to install all the necessary parts of Kata
Containers after you have a Kubernetes cluster running with one of the CRI's
using the default runc runtime. Follow the steps in the Kubernetes quick start
section of the `kata-containers GitHub README
`_
to install Kata.
Use your cluster
****************
Once your master control plane is successfully initialized, follow the
instructions presented about how to use your cluster and its *IP*, *token*,
and *hash* values are displayed. It is important that you record this
information because it is required to join additional nodes to the cluster.
A successful initialization looks like this:
.. code-block:: console
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
...
You can now join any number of machines by running the following on each node
as root:
kubeadm join : --token --discovery-token-ca-cert-hash sha256:
With the first node of the cluster setup, you can continue expanding the
cluster with additional nodes and start deploying containerized applications.
For further information on using Kubernetes, see `Related topics`_.
.. note::
By default, the master node does not run any pods for security reasons. To
setup a single-node cluster and allow the master node to also run pods, the
master node will need to be untained. See the Kubernetes documentation on
`control plane node isolation
`_.
Troubleshooting
***************
Package configuration customization
===================================
|CL| is a stateless system that looks for user-defined package configuration
files in the :file:`/etc/` directory to be used as default. If
user-defined files are not found, |CL| uses the distribution-provided
configuration files for each package.
If you customize any of the default package configuration files, you **must**
store the customized files in the :file:`/etc/` directory. If you edit any of
the distribution-provided default files, your changes will be lost in the next
system update as the default files will be overwritten with the updated files.
Learn more about :ref:`stateless` in |CL|.
Logs
====
* Check the kubelet service logs :command:`sudo journalctl -u kubelet`
Setting proxy servers for Kubernetes
====================================
If you receive any of the messages below, check outbound Internet access. You
may be behind a proxy server.
* Images cannot be pulled.
* Connection refused error.
* Connection timed-out or Access Refused errors.
* The warnings when :command:`kubeadm init` is run.
.. code-block:: console
[WARNING HTTPProxy]: Connection to "https://" uses proxy "". If that is not intended, adjust your proxy settings
[WARNING HTTPProxyCIDR]: connection to "10.96.0.0/12" uses proxy "". This may lead to malfunctional cluster setup. Make sure that Pod and Services IP ranges specified correctly as exceptions in proxy configuration
[WARNING HTTPProxyCIDR]: connection to "10.244.0.0/16" uses proxy "". This may lead to malfunctional cluster setup. Make sure that Pod and Services IP ranges specified correctly as exceptions in proxy configuration
If you use an outbound proxy server, you must configure proxy settings
appropriately for all components in the stack including :command:`kubectl` and
container runtime services.
Configure the :ref:`proxy settings `, using the standard *HTTP_PROXY*,
*HTTPS_PROXY*, and *NO_PROXY* environment variables. The *NO_PROXY* values are
especially important for Kubernetes to ensure private IP traffic does not try
to go out the proxy.
#. Set your environment proxy variables. Ensure that your local IP address is
**explicitly included** in the environment variable *NO_PROXY*. Setting
*localhost* is not sufficient!
.. code-block:: bash
export http_proxy=http://proxy.example.com:80
export https_proxy=http://proxy.example.com:443
export no_proxy=.svc,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,`hostname`,localhost
.. important::
:command:`kubeadm` commands specifically use these shell variables for proxy
configuration. Ensure they are set your running terminal before running
:command:`kubeadm` commands.
#. Run the following command to add systemd drop-in configurations for each
service to include proxy settings:
.. code-block:: bash
services=(kubelet docker crio containerd)
for s in "${services[@]}"; do
sudo mkdir -p "/etc/systemd/system/${s}.service.d/"
cat << EOF | sudo tee "/etc/systemd/system/${s}.service.d/proxy.conf"
[Service]
Environment="HTTP_PROXY=${http_proxy}"
Environment="HTTPS_PROXY=${https_proxy}"
Environment="SOCKS_PROXY=${socks_proxy}"
Environment="NO_PROXY=${no_proxy}"
EOF
done
#. Reload the systemd manager configuration.
.. code-block:: bash
sudo systemctl daemon-reload
If you had a previously failed initialization due to a proxy issue, restart
the process with the :command:`kubeadm reset` command.
DNS issues
==========
* not found in message.
Your DNS server may not be appropriately configured. Try adding an entry
to the :file:`/etc/hosts` file with your host's IP and Name.
Use the commands :command:`hostname` and :command:`hostname -I` to
retrieve them.
For example:
.. code:: bash
10.200.50.20 myhost
* coredns pods are stuck in container creating state and logs show entries
similar to one of the following:
.. code:: console
Warning FailedCreatePodSandBox 5m7s kubelet, kata3 Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get network JSON for pod sandbox k8s_coredns->-5gpj2_kube-system_): cannot convert version ["" "0.1.0" "0.2.0"] to 0.4.0
In this case the :file:`/etc/cni/net.d/10-flannel.conf` or another CNI file
is using an incompatible version. Delete the file and restart the stack.
.. code:: console
Warning FailedCreatePodSandBox 117s (x197 over 45m) kubelet, kata3 (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = failed to create pod network sandbox k8s_coredns->-npsm5_kube-system_: error getting ClusterInformation: Get https://[10.96.0.1]:443/apis/crd.projectcalico.org/v1/clusterinformations/default: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
In this case, there may be multiple CNI configuration files in the
:file:`/etc/cni/net.d` folder. Delete all the files in this directory and
restart the stack.
.. code:: console
Warning FailedScheduling 55s (x3 over 2m12s) default-scheduler 0/1
nodes are available: 1 node(s) had taints that the pod didn't tolerate.
In this case, there may be multiple CNI configuration files in the
:file:`/etc/cni/net.d` folder. Delete all the files in this directory, apply
a CNI plugin, and restart the stack.
Reference
*********
What is Kubernetes?
===================
Kubernetes (K8s) is an open source system for automating deployment, scaling,
and management of containerized applications. It groups containers that make
up an application into logical units for easy management and discovery.
Kubernetes supports using a variety of `container runtimes
`_.
What is a Container Network Interface (CNI)?
============================================
In Kubernetes, a `pod
`_ is a group of one
or more containers and is the smallest deployable unit of computing in a
Kubernetes cluster. Pods have shared storage/network internally but
communication between pods requires additional configuration. If you want your
pods to be able to communicate with each other you must choose and install a
`pod network add-on`_.
Some pod network add-ons enable advanced functionality with physical networks
or cloud provider networks.
What is a Container Runtime Interface (CRI)?
============================================
Container runtimes are the underlying fabric that pod workloads execute inside
of. Different container runtimes offer different balances between features,
performance, and security.
Kubernetes allows integration various container runtimes via a container
runtime interface (CRI).
What is CRI+O?
--------------
`CRI+O `_ is a lightweight alternative to using Docker as
the runtime for kubernetes. It allows Kubernetes to use any OCI-compliant
runtime as the container runtime for running pods, such as runc and
Kata Containers as the container runtimes.
CRI+O allows setting a different runtime per-pod.
What is containerd?
-------------------
`containerd `_ is the runtime that the Docker engine
is built on top of.
Kubernetes can use containerd directly instead of going through the Docker
engine for increased robustness and performance. See the `blog post on
kubernetes containerd integration
`_
for more details.
containerd allows setting a different runtime per-pod.
What is Docker?
---------------
`Docker `_ is an engine for running software packaged
as functionally complete units, called containers, using the same operating
system kernel.
The default built-in runtime provided by Kubernetes is using the system Docker
installation via Dockershim and as a result is one of the simplest to use. One
limitation of using Dockershim is that all pods on the Kubernetes node will
inherit and use the default runtime that Docker is set to use. To be able to
specify a container runtime per-Kerbernetes service, use CRI+O or containerd.
What is Kata Containers\*?
==========================
`Kata Containers`_ is an alternative OCI compatible runtime that secures
container workloads in a lightweight virtual machine. It provides stronger
workloads isolation using hardware virtualization technology as a second layer
of defense for untrusted workloads or multi-tenant scenarios.
The Kata Containers (kata-runtime) adheres to :abbr:`OCI (Open Container
Initiative*)` guidelines and works seamlessly with Kubernetes through Docker,
containerd, or CRI+O.
Related topics
==============
* `Understanding basic Kubernetes architecture`_
* Installing a `pod network add-on`_
* `Joining your nodes`_
* `Deploying an application to your cluster`_
* See our document on :ref:`Kubernetes best practices `
.. _Kubernetes container orchestration system: https://kubernetes.io/
.. _Kata Containers: https://katacontainers.io/
.. _cloud-native-basic: https://github.com/clearlinux/clr-bundles/blob/master/bundles/cloud-native-basic
.. _preflight checks: https://kubernetes.io/docs/reference/setup-tools/kubeadm/implementation-details/#preflight-checks
.. _Understanding basic Kubernetes architecture: https://kubernetes.io/docs/user-journeys/users/application-developer/foundational/#section-3
.. _Deploying an application to your cluster: https://kubernetes.io/docs/user-journeys/users/application-developer/foundational/#section-2
.. _pod network add-on: https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#pod-network
.. _Joining your nodes: https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#join-nodes
.. _cloud-native-setup scripts: https://github.com/clearlinux/cloud-native-setup/tree/master/clr-k8s-examples
.. _control-plane node: https://kubernetes.io/docs/concepts/#kubernetes-control-plane
.. _RuntimeClass handler: https://kubernetes.io/docs/concepts/containers/runtime-class/