From c87c4b8649b8dea5bb7a1f1bb77bb913ef2a49e0 Mon Sep 17 00:00:00 2001 From: Marcelo Giles Date: Thu, 26 Sep 2024 01:40:57 -0700 Subject: [PATCH 1/2] Add Tutorial Running Kubelet in Standalone Mode Add lessoncontent tag Add changes requested in comments/feedback Add svcs checks and cleanup details. Fix typos Simplify curl test commands Revert curl test commands syntax change. Fix kubelet api addr Minor edits, fixes Remove list items, minor fixes Add changes requested in feedback. Add arm64 arch urls and commands Add changes requested in feedback. Add sudo to commands Move kubelet-standalone to new cluster-management section Add changes requested in feedback. Minor fixes Switch pod ip addr to localhost Add swap section and fix systemctl daemon-reload Add swap note and fix paragraph Substitute containerd with crio. Modify instructions Add changes requested in feedback/comments. Other minor fixes Add security warnings to kubelet config file Add changes requested in feedback/comments Add more changes requested in feedback/comments Fix kubelet api port Replace containerd.service -> crio.service Add suggested changes in feedback and minor fixes Add set up cri-o title header --- content/en/docs/tutorials/_index.md | 5 + .../tutorials/cluster-management/_index.md | 4 + .../cluster-management/kubelet-standalone.md | 512 ++++++++++++++++++ 3 files changed, 521 insertions(+) create mode 100644 content/en/docs/tutorials/cluster-management/_index.md create mode 100644 content/en/docs/tutorials/cluster-management/kubelet-standalone.md 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..8c62979bab --- /dev/null +++ b/content/en/docs/tutorials/cluster-management/kubelet-standalone.md @@ -0,0 +1,512 @@ +--- +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. +{{< /note >}} + +See [Ports and Protocols](/docs/reference/networking/ports-and-protocols/) to +understand which ports Kubernetes components use. + +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/) From f9851cdd11de2c5eaff81bd70ebdc565a7d53bf3 Mon Sep 17 00:00:00 2001 From: Marcelo Giles Date: Tue, 15 Oct 2024 21:25:09 -0700 Subject: [PATCH 2/2] Expand kubelet config explanation note --- .../cluster-management/kubelet-standalone.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/content/en/docs/tutorials/cluster-management/kubelet-standalone.md b/content/en/docs/tutorials/cluster-management/kubelet-standalone.md index 8c62979bab..a169353512 100644 --- a/content/en/docs/tutorials/cluster-management/kubelet-standalone.md +++ b/content/en/docs/tutorials/cluster-management/kubelet-standalone.md @@ -279,10 +279,17 @@ EOF {{< note >}} Because you are not setting up a production cluster, you are using plain HTTP (`readOnlyPort: 10255`) for unauthenticated queries to the kubelet's API. -{{< /note >}} + +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: @@ -308,8 +315,8 @@ WantedBy=multi-user.target EOF ``` -We intentionally omitted the command line argument `--kubeconfig` in the service -configuration file. This argument sets the path to a +The command line argument `--kubeconfig` has been intentionally omitted in the +service configuration file. This argument sets the path to a [kubeconfig](/docs/concepts/configuration/organize-cluster-access-kubeconfig/) file that specifies how to connect to the API server, enabling API server mode. Omitting it, enables standalone mode.