diff --git a/content/en/docs/tutorials/_index.md b/content/en/docs/tutorials/_index.md index ec0d420421..7196986412 100644 --- a/content/en/docs/tutorials/_index.md +++ b/content/en/docs/tutorials/_index.md @@ -55,6 +55,11 @@ Before walking through each tutorial, you may want to bookmark the * [Apply Pod Security Standards at Namespace level](/docs/tutorials/security/ns-level-pss/) * [Restrict a Container's Access to Resources with AppArmor](/docs/tutorials/security/apparmor/) * [Seccomp](/docs/tutorials/security/seccomp/) + +## Cluster Management + +* [Running Kubelet in Standalone Mode](/docs/tutorials/cluster-management/kubelet-standalone/) + ## {{% heading "whatsnext" %}} If you would like to write a tutorial, see diff --git a/content/en/docs/tutorials/cluster-management/_index.md b/content/en/docs/tutorials/cluster-management/_index.md new file mode 100644 index 0000000000..4b104d5940 --- /dev/null +++ b/content/en/docs/tutorials/cluster-management/_index.md @@ -0,0 +1,4 @@ +--- +title: "Cluster Management" +weight: 60 +--- diff --git a/content/en/docs/tutorials/cluster-management/kubelet-standalone.md b/content/en/docs/tutorials/cluster-management/kubelet-standalone.md new file mode 100644 index 0000000000..a169353512 --- /dev/null +++ b/content/en/docs/tutorials/cluster-management/kubelet-standalone.md @@ -0,0 +1,519 @@ +--- +title: Running Kubelet in Standalone Mode +content_type: tutorial +weight: 10 +--- + + + +This tutorial shows you how to run a standalone Kubelet instance. + +You may have different motivations for running a standalone kubelet. +This tutorial is aimed at introducing you to Kubernetes, even if you don't have +much experience with it. You can follow this tutorial and learn about node setup, +basic (static) Pods, and how Kubernetes manages containers. + +Once you have followed this tutorial, you could try using a cluster that has a +{{< glossary_tooltip text="control plane" term_id="control-plane" >}} to manage pods +and nodes, and other types of objects. For example, +[Hello, minikube](/docs/tutorials/hello-minikube/). + +You can also run the kubelet in standalone mode to suit production use cases, such as +to run the control plane for a highly available, resiliently deployed cluster. This +tutorial does not cover the details you need for running a resilient control plane. + +## {{% heading "objectives" %}} + +* Install `cri-o`, and `kubelet` on a Linux system and run them as `systemd` services. +* Launch a Pod running `nginx` that listens to requests on TCP port 80 on the Pod's IP address. +* Learn how the different components of the solution interact among themselves. + +{{< caution >}} +The Kubelet configuration used for this tutorial is insecure by design and should +_not_ be used in a production environment. +{{< /caution >}} + +## {{% heading "prerequisites" %}} + +* Admin (`root`) access to a Linux system that uses `systemd` and `iptables` + (or nftables with `iptables` emulation). +* Access to the Internet to download the components needed for the tutorial, such as: +* A {{< glossary_tooltip text="container runtime" term_id="container-runtime" >}} + that implements the Kubernetes {{< glossary_tooltip term_id="cri" text="(CRI)">}}. +* Network plugins (these are often known as + {{< glossary_tooltip text="Container Networking Interface (CNI)" term_id="cni" >}}) +* Required CLI tools: `curl`, `tar`, `jq`. + + + +## Prepare the system + +### Swap configuration + +The default behavior of kubelet is to fail to start if swap memory is detected on a node. +This means that swap should either be disabled or tolerated by kubelet. + +{{< note >}} +If you configure the kubelet to tolerate swap, the kubelet still configures Pods (and the +containers in those Pods) not to use swap space. To find out how Pods can actually +use the available swap, you can read more about +[swap memory management](/docs/concepts/architecture/nodes/#swap-memory) on Linux nodes. +{{< /note >}} + +If you have swap memory enabled, either disable it or add `failSwapOn: false` to the +kubelet configuration file. + +To check if swap is enabled: + +```shell +sudo swapon --show +``` + +If there is no output from the command, then swap memory is already disabled. + +To disable swap temporarily: + +```shell +sudo swapoff -a +``` + +To make this change persistent across reboots: + +Make sure swap is disabled in either `/etc/fstab` or `systemd.swap`, depending how it was +configured on your system. + +### Enable IPv4 packet forwarding + +To check if IPv4 packet forwarding is enabled: + +```shell +cat /proc/sys/net/ipv4/ip_forward +``` + +If the output is `1`, it is already enabled. If the output is `0`, then follow next steps. + +To enable IPv4 packet forwarding, create a configuration file that sets the +`net.ipv4.ip_forward` parameter to `1`: + +```shell +sudo tee /etc/sysctl.d/k8s.conf < crio-install +``` + +Run the installer script: + +```shell +sudo bash crio-install +``` + +Enable and start the `crio` service: + +```shell +sudo systemctl daemon-reload +sudo systemctl enable --now crio.service +``` + +Quick test: + +```shell +sudo systemctl is-active crio.service +``` + +The output is similar to: + +``` +active +``` + +Detailed service check: + +```shell +sudo journalctl -f -u crio.service +``` + +### Install network plugins + +The `cri-o` installer installs and configures the `cni-plugins` package. You can +verify the installation running the following command: + + +```shell +/opt/cni/bin/bridge --version +``` + +The output is similar to: + +``` +CNI bridge plugin v1.5.1 +CNI protocol versions supported: 0.1.0, 0.2.0, 0.3.0, 0.3.1, 0.4.0, 1.0.0 +``` + +To check the default configuration: + +```shell +cat /etc/cni/net.d/11-crio-ipv4-bridge.conflist +``` + +The output is similar to: + +```json +{ + "cniVersion": "1.0.0", + "name": "crio", + "plugins": [ + { + "type": "bridge", + "bridge": "cni0", + "isGateway": true, + "ipMasq": true, + "hairpinMode": true, + "ipam": { + "type": "host-local", + "routes": [ + { "dst": "0.0.0.0/0" } + ], + "ranges": [ + [{ "subnet": "10.85.0.0/16" }] + ] + } + } + ] +} +``` + +{{< note >}} +Make sure that the default `subnet` range (`10.85.0.0/16`) does not overlap with +one of your active networks. If there is an overlap, you can edit the file and change it +accordingly. Restart the service after the change. +{{< /note >}} + +### Download and set up the kubelet + +Download the [latest stable release](/releases/download/) of the Kubelet. + +{{< tabs name="download_kubelet" >}} +{{< tab name="x86-64" codelang="bash" >}} +curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubelet" +{{< /tab >}} +{{< tab name="ARM64" codelang="bash" >}} +curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubelet" +{{< /tab >}} +{{< /tabs >}} + +Configure: + +```shell +sudo mkdir -p /etc/kubernetes/manifests +``` + +```shell +sudo tee /etc/kubernetes/kubelet.yaml <}} +Because you are not setting up a production cluster, you are using plain HTTP +(`readOnlyPort: 10255`) for unauthenticated queries to the kubelet's API. + +The _authentication webhook_ is disabled and _authorization mode_ is set to `AlwaysAllow` +for the purpose of this tutorial. You can learn more about +[authorization modes](/docs/reference/access-authn-authz/authorization/#authorization-modules) +and [webhook authentication](/docs/reference/access-authn-authz/webhook/) to properly +configure kubelet in standalone mode in your environment. + +See [Ports and Protocols](/docs/reference/networking/ports-and-protocols/) to +understand which ports Kubernetes components use. +{{< /note >}} + + +Install: + +```shell +chmod +x kubelet +sudo cp kubelet /usr/bin/ +``` + +Create a `systemd` service unit file: + +```shell +sudo tee /etc/systemd/system/kubelet.service < static-web.yaml +apiVersion: v1 +kind: Pod +metadata: + name: static-web +spec: + containers: + - name: web + image: nginx + ports: + - name: web + containerPort: 80 + protocol: TCP +EOF +``` + +Copy the `static-web.yaml` manifest file to the `/etc/kubernetes/manifests` directory. + +```shell +sudo cp static-web.yaml /etc/kubernetes/manifests/ +``` + +### Find out information about the Kubelet and the Pod {#find-out-information} + +The Pod networking plugin creates a network bridge (`cni0`) and a pair of `veth` interfaces +for each Pod (one of the pair is inside the newly made Pod, and the other is at the host level). + +Query the Kubelet's API endpoint at `http://localhost:10255/pods`: + +```shell +curl http://localhost:10255/pods | jq '.' +``` + +To obtain the IP address of the `static-web` Pod: + +```shell +curl http://localhost:10255/pods | jq '.items[].status.podIP' +``` + +The output is similar to: + +``` +"10.85.0.4" +``` + +Connect to the `nginx` server Pod on `http://:` (port 80 is the default), in this case: + +```shell +curl http://10.85.0.4 +``` + +The output is similar to: + +```html + + + +Welcome to nginx! +... +``` + +## Where to look for more details + +If you need to diagnose a problem getting this tutorial to work, you can look +within the following directories for monitoring and troubleshooting: + +``` +/var/lib/cni +/var/lib/containers +/var/lib/kubelet + +/var/log/containers +/var/log/pods +``` + +## Clean up + +### Kubelet + +```shell +sudo systemctl disable --now kubelet.service +sudo systemctl daemon-reload +sudo rm /etc/systemd/system/kubelet.service +sudo rm /usr/bin/kubelet +sudo rm -rf /etc/kubernetes +sudo rm -rf /var/lib/kubelet +sudo rm -rf /var/log/containers +sudo rm -rf /var/log/pods +``` + +### Container Runtime + +```shell +sudo systemctl disable --now crio.service +sudo systemctl daemon-reload +sudo rm -rf /usr/local/bin +sudo rm -rf /usr/local/lib +sudo rm -rf /usr/local/share +sudo rm -rf /usr/libexec/crio +sudo rm -rf /etc/crio +sudo rm -rf /etc/containers +``` + +### Network Plugins + +```shell +sudo rm -rf /opt/cni +sudo rm -rf /etc/cni +sudo rm -rf /var/lib/cni +``` + +## Conclusion + +This page covered the basic aspects of deploying a kubelet in standalone mode. +You are now ready to deploy Pods and test additional functionality. + +Notice that in standalone mode the Kubelet does *not* support fetching Pod +configurations from the control plane (because there is no control plane connection). + +You also cannot use a {{< glossary_tooltip text="ConfigMap" term_id="configmap" >}} or a +{{< glossary_tooltip text="Secret" term_id="secret" >}} to configure the containers +in a static Pod. + +## {{% heading "whatsnext" %}} + +* Follow [Hello, minikube](/docs/tutorials/hello-minikube/) to learn about running Kubernetes + _with_ a control plane. The minikube tool helps you set up a practice cluster on your own computer. +* Learn more about [Network Plugins](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) +* Learn more about [Container Runtimes](/docs/setup/production-environment/container-runtimes/) +* Learn more about [kubelet](/docs/reference/command-line-tools-reference/kubelet/) +* Learn more about [static Pods](/docs/tasks/configure-pod-container/static-pod/)