From 28e18f914c8cb6ddc954b499045b6d63605213ae Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 30 Jun 2020 19:50:25 +0100 Subject: [PATCH 01/58] Use the installCRDs option for cert-manager --- .../v2.x/en/installation/k8s-install/helm-rancher/_index.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md index 74aa80b7789..3d1e76fc86a 100644 --- a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md @@ -88,9 +88,6 @@ This step is only required to use certificates issued by Rancher's generated CA These instructions are adapted from the [official cert-manager documentation](https://cert-manager.io/docs/installation/kubernetes/#installing-with-helm). ``` -# Install the CustomResourceDefinition resources separately -kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.15.0/cert-manager.crds.yaml - # **Important:** # If you are running Kubernetes v1.15 or below, you # will need to add the `--validate=false` flag to your @@ -114,7 +111,8 @@ helm repo update helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ - --version v0.15.0 + --version v0.15.0 \ + --set installCRDs=true ``` Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the cert-manager namespace for running pods: From e61a737ac30d40a3f69cf1597692ae98594ebf87 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 30 Jun 2020 20:06:59 +0100 Subject: [PATCH 02/58] Update docs for cert manager to latest version --- .../air-gap/install-rancher/_index.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md index af59e6eacf5..dec2bf92dfe 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md @@ -85,22 +85,19 @@ By default, Rancher generates a CA and uses cert-manager to issue the certificat 1. Fetch the latest cert-manager chart available from the [Helm chart repository](https://hub.helm.sh/charts/jetstack/cert-manager). ```plain - helm fetch jetstack/cert-manager --version v0.12.0 + helm fetch jetstack/cert-manager --version v0.15.1 ``` 1. Render the cert manager template with the options you would like to use to install the chart. Remember to set the `image.repository` option to pull the image from your private registry. This will create a `cert-manager` directory with the Kubernetes manifest files. ```plain - helm template cert-manager ./cert-manager-v0.12.0.tgz --output-dir . \ + helm template cert-manager ./cert-manager-v0.15.1.tgz --output-dir . \ --namespace cert-manager \ --set image.repository=/quay.io/jetstack/cert-manager-controller \ --set webhook.image.repository=/quay.io/jetstack/cert-manager-webhook \ --set cainjector.image.repository=/quay.io/jetstack/cert-manager-cainjector + --set installCRDs=true ``` -1. Download the required CRD file for cert-manager - ```plain - curl -L -o cert-manager/cert-manager-crd.yaml https://raw.githubusercontent.com/jetstack/cert-manager/release-0.12/deploy/manifests/00-crds.yaml - ``` 1. Render the Rancher template, declaring your chosen options. Use the reference table below to replace each placeholder. Rancher needs to be configured to use the private registry in order to provision any Rancher launched Kubernetes clusters or Rancher tools. @@ -183,18 +180,14 @@ If you are using self-signed certificates, install cert-manager: kubectl create namespace cert-manager ``` -1. Create the cert-manager CustomResourceDefinitions (CRDs). +1. Launch cert-manager. ```plain -kubectl apply -f cert-manager/cert-manager-crd.yaml +kubectl apply -R -f ./cert-manager ``` > **Note:** > If you are running Kubernetes v1.15 or below, you will need to add the `--validate=false` flag to your `kubectl apply` command above, or else you will receive a validation error relating to the `x-kubernetes-preserve-unknown-fields` field in cert-manager’s CustomResourceDefinition resources. This is a benign error and occurs due to the way kubectl performs resource validation. -1. Launch cert-manager. -```plain -kubectl apply -R -f ./cert-manager -``` {{% /accordion %}} From 07396216427c210f3fc84f1f794651c7418563e9 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 30 Jun 2020 20:08:00 +0100 Subject: [PATCH 03/58] Update image version --- .../air-gap/populate-private-registry/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md index 6cef213e1ae..285181f6ec0 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md @@ -59,7 +59,7 @@ In a Kubernetes Install, if you elect to use the Rancher default self-signed TLS ```plain helm repo add jetstack https://charts.jetstack.io helm repo update - helm fetch jetstack/cert-manager --version v0.12.0 + helm fetch jetstack/cert-manager --version v0.15.1 helm template ./cert-manager-.tgz | grep -oP '(?<=image: ").*(?=")' >> ./rancher-images.txt ``` From e6fe8a24ee7bad6d9252bba0f14ee73e935e3921 Mon Sep 17 00:00:00 2001 From: Tejeev Date: Tue, 28 Jul 2020 14:58:57 +0100 Subject: [PATCH 04/58] synchronised and updated overlay test RKE and Rancher had different versions of the test. I synced them and changed them so that they utilize Murali's swiss-army-knife which allows much more freedom for troubleshooting. --- .../v2.x/en/troubleshooting/networking/_index.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/content/rancher/v2.x/en/troubleshooting/networking/_index.md b/content/rancher/v2.x/en/troubleshooting/networking/_index.md index 7259b61a3e0..23e6e6bed02 100644 --- a/content/rancher/v2.x/en/troubleshooting/networking/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/networking/_index.md @@ -15,7 +15,7 @@ Double check if all the [required ports]({{}}/rancher/v2.x/en/cluster-p The pod can be scheduled to any of the hosts you used for your cluster, but that means that the NGINX ingress controller needs to be able to route the request from `NODE_1` to `NODE_2`. This happens over the overlay network. If the overlay network is not functioning, you will experience intermittent TCP/HTTP connection failures due to the NGINX ingress controller not being able to route to the pod. -To test the overlay network, you can launch the following `DaemonSet` definition. This will run a `busybox` container on every host, which we will use to run a `ping` test between containers on all hosts. +To test the overlay network, you can launch the following `DaemonSet` definition. This will run a `swiss-army-knife` container on every host (image was developed by Rancher engineers), which we will use to run a `ping` test between containers on all hosts. 1. Save the following file as `ds-overlaytest.yml` @@ -34,11 +34,16 @@ To test the overlay network, you can launch the following `DaemonSet` definition name: overlaytest spec: tolerations: - - operator: Exists + - effect: NoExecute + key: "node-role.kubernetes.io/etcd" + value: "true" + - effect: NoSchedule + key: "node-role.kubernetes.io/controlplane" + value: "true" containers: - - image: busybox:1.28 + - image: leodotcloud/swiss-army-knife imagePullPolicy: Always - name: busybox + name: swiss-army-knife command: ["sh", "-c", "tail -f /dev/null"] terminationMessagePath: /dev/termination-log ``` From 6d966738cf9359aa049113e85739d0d720d748d4 Mon Sep 17 00:00:00 2001 From: Tejeev Date: Tue, 28 Jul 2020 15:35:28 +0100 Subject: [PATCH 05/58] Update content/rancher/v2.x/en/troubleshooting/networking/_index.md Co-authored-by: Murali Paluru --- content/rancher/v2.x/en/troubleshooting/networking/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/troubleshooting/networking/_index.md b/content/rancher/v2.x/en/troubleshooting/networking/_index.md index 23e6e6bed02..dd14ebd0a49 100644 --- a/content/rancher/v2.x/en/troubleshooting/networking/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/networking/_index.md @@ -31,7 +31,7 @@ To test the overlay network, you can launch the following `DaemonSet` definition template: metadata: labels: - name: overlaytest + name: ds-overlaytest spec: tolerations: - effect: NoExecute From 07b8d7073da842ec93bdb2d0d3d3c13f09db37fd Mon Sep 17 00:00:00 2001 From: Tejeev Date: Tue, 28 Jul 2020 15:35:44 +0100 Subject: [PATCH 06/58] Update content/rancher/v2.x/en/troubleshooting/networking/_index.md Co-authored-by: Murali Paluru --- content/rancher/v2.x/en/troubleshooting/networking/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/troubleshooting/networking/_index.md b/content/rancher/v2.x/en/troubleshooting/networking/_index.md index dd14ebd0a49..fc2fb59144f 100644 --- a/content/rancher/v2.x/en/troubleshooting/networking/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/networking/_index.md @@ -43,7 +43,7 @@ To test the overlay network, you can launch the following `DaemonSet` definition containers: - image: leodotcloud/swiss-army-knife imagePullPolicy: Always - name: swiss-army-knife + name: overlaytest command: ["sh", "-c", "tail -f /dev/null"] terminationMessagePath: /dev/termination-log ``` From 050b03b36582e73cddeec12a7d9e3dc3129b427b Mon Sep 17 00:00:00 2001 From: Tejeev Date: Tue, 28 Jul 2020 16:02:38 +0100 Subject: [PATCH 07/58] Fixed the command to run with new name and added debug --- .../en/troubleshooting/networking/_index.md | 78 ++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/content/rancher/v2.x/en/troubleshooting/networking/_index.md b/content/rancher/v2.x/en/troubleshooting/networking/_index.md index fc2fb59144f..0115725e433 100644 --- a/content/rancher/v2.x/en/troubleshooting/networking/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/networking/_index.md @@ -10,7 +10,6 @@ Make sure you configured the correct kubeconfig (for example, `export KUBECONFIG ### Double check if all the required ports are opened in your (host) firewall Double check if all the [required ports]({{}}/rancher/v2.x/en/cluster-provisioning/node-requirements/#networking-requirements/) are opened in your (host) firewall. The overlay network uses UDP in comparison to all other required ports which are TCP. - ### Check if overlay network is functioning correctly The pod can be scheduled to any of the hosts you used for your cluster, but that means that the NGINX ingress controller needs to be able to route the request from `NODE_1` to `NODE_2`. This happens over the overlay network. If the overlay network is not functioning, you will experience intermittent TCP/HTTP connection failures due to the NGINX ingress controller not being able to route to the pod. @@ -53,7 +52,79 @@ To test the overlay network, you can launch the following `DaemonSet` definition 4. Run the following command, from the same location, to let each container on every host ping each other (it's a single line bash command). ``` - echo "=> Start network overlay test"; kubectl get pods -l name=overlaytest -o jsonpath='{range .items[*]}{@.metadata.name}{" "}{@.spec.nodeName}{"\n"}{end}' | while read spod shost; do kubectl get pods -l name=overlaytest -o jsonpath='{range .items[*]}{@.status.podIP}{" "}{@.spec.nodeName}{"\n"}{end}' | while read tip thost; do kubectl --request-timeout='10s' exec $spod -- /bin/sh -c "ping -c2 $tip > /dev/null 2>&1"; RC=$?; if [ $RC -ne 0 ]; then echo $shost cannot reach $thost; fi; done; done; echo "=> End network overlay test" + ### Check if overlay network is functioning correctly + +The pod can be scheduled to any of the hosts you used for your cluster, but that means that the NGINX ingress controller needs to be able to route the request from `NODE_1` to `NODE_2`. This happens over the overlay network. If the overlay network is not functioning, you will experience intermittent TCP/HTTP connection failures due to the NGINX ingress controller not being able to route to the pod. + +To test the overlay network, you can launch the following `DaemonSet` definition. This will run a `swiss-army-knife` container on every host (image was developed by Rancher engineers), which we will use to run a `ping` test between containers on all hosts. + +1. Save the following file as `ds-overlaytest.yml` + + ``` + apiVersion: apps/v1 + kind: DaemonSet + metadata: + name: overlaytest + spec: + selector: + matchLabels: + name: overlaytest + template: + metadata: + labels: + name: ds-overlaytest + spec: + tolerations: + - effect: NoExecute + key: "node-role.kubernetes.io/etcd" + value: "true" + - effect: NoSchedule + key: "node-role.kubernetes.io/controlplane" + value: "true" + containers: + - image: leodotcloud/swiss-army-knife + imagePullPolicy: Always + name: overlaytest + command: ["sh", "-c", "tail -f /dev/null"] + terminationMessagePath: /dev/termination-log + ``` + +2. Launch it using `kubectl create -f ds-overlaytest.yml` +3. Wait until `kubectl rollout status ds/overlaytest -w` returns: `daemon set "overlaytest" successfully rolled out`. +4. Run the following command, from the same location, to let each container on every host ping each other (it's a single line bash command). + + ``` + echo "=> Start network overlay test"; kubectl get pods -l name=ds-overlaytest -o jsonpath='{range .items[*]}{@.metadata.name}{" "}{@.spec.nodeName}{"\n"}{end}' | while read spod shost; do kubectl get pods -l name=ds-overlaytest -o jsonpath='{range .items[*]}{@.status.podIP}{" "}{@.spec.nodeName}{"\n"}{end}' | while read tip thost; do kubectl --request-timeout='10s' exec $spod -- /bin/sh -c "ping -c2 $tip > /dev/null 2>&1"; RC=$?; if [ $RC -ne 0 ]; then echo $shost cannot reach $thost; fi; done; done; echo "=> End network overlay test" + ``` + +5. When this command has finished running, the output indicating everything is correct is: + + ``` + => Start network overlay test + Pinging from pod overlaytest-4cpx5 on host NODE1 + to pod ip 10.42.1.29 on host NODE1 + to pod ip 10.42.2.19 on host NODE2 + to pod ip 10.42.4.12 on host NODE3 + Pinging from pod overlaytest-vms6w on host NODE2 + to pod ip 10.42.1.29 on host NODE1 + to pod ip 10.42.2.19 on host NODE2 + to pod ip 10.42.4.12 on host NODE3 + => End network overlay test + ``` + +If you see error in the output, that means that the [required ports]({{}}/rancher/v2.x/en/cluster-provisioning/node-requirements/#networking-requirements/) for overlay networking are not opened between the hosts indicated. + +If a path fails the overlay test, you will see errors like the following: + +``` +command terminated with exit code 1 +NODE2 cannot reach NODE1 +command terminated with exit code 1 +NODE3 cannot reach NODE1 +``` + +Cleanup the DaemonSet by running `kubectl delete ds/overlaytest`. + ``` 5. When this command has finished running, the output indicating everything is correct is: @@ -80,7 +151,8 @@ NODE1 cannot reach NODE3 => End network overlay test ``` -Cleanup the busybox DaemonSet by running `kubectl delete ds/overlaytest`. +Cleanup the DaemonSet by running `kubectl delete ds/overlaytest`. + ### Check if MTU is correctly configured on hosts and on peering/tunnel appliances/devices From 43f4eadad3d25b53823d5b2b9d34f301ebdc8118 Mon Sep 17 00:00:00 2001 From: Tejeev Date: Tue, 28 Jul 2020 16:05:43 +0100 Subject: [PATCH 08/58] Update _index.md --- content/rancher/v2.x/en/troubleshooting/networking/_index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/content/rancher/v2.x/en/troubleshooting/networking/_index.md b/content/rancher/v2.x/en/troubleshooting/networking/_index.md index 0115725e433..76dd5b7cd71 100644 --- a/content/rancher/v2.x/en/troubleshooting/networking/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/networking/_index.md @@ -119,8 +119,6 @@ If a path fails the overlay test, you will see errors like the following: ``` command terminated with exit code 1 NODE2 cannot reach NODE1 -command terminated with exit code 1 -NODE3 cannot reach NODE1 ``` Cleanup the DaemonSet by running `kubectl delete ds/overlaytest`. From 7fa88f691a17620113d39b72b87c3d91c452c862 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 22 Sep 2020 09:37:52 +0100 Subject: [PATCH 09/58] Update version. Remove CRD Flag --- .../v2.x/en/installation/k8s-install/helm-rancher/_index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md index 3d1e76fc86a..8ea026ca56f 100644 --- a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md @@ -88,6 +88,9 @@ This step is only required to use certificates issued by Rancher's generated CA These instructions are adapted from the [official cert-manager documentation](https://cert-manager.io/docs/installation/kubernetes/#installing-with-helm). ``` +# Install the CustomResourceDefinition resources separately +kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.crds.yaml + # **Important:** # If you are running Kubernetes v1.15 or below, you # will need to add the `--validate=false` flag to your @@ -111,8 +114,7 @@ helm repo update helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ - --version v0.15.0 \ - --set installCRDs=true + --version v1.0.1 ``` Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the cert-manager namespace for running pods: From 39686bbae17ff430e75ca6cb8d0823ef620db250 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 22 Sep 2020 09:38:22 +0100 Subject: [PATCH 10/58] Whitespace --- .../v2.x/en/installation/k8s-install/helm-rancher/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md index 8ea026ca56f..f6bcec0c245 100644 --- a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md @@ -88,8 +88,8 @@ This step is only required to use certificates issued by Rancher's generated CA These instructions are adapted from the [official cert-manager documentation](https://cert-manager.io/docs/installation/kubernetes/#installing-with-helm). ``` -# Install the CustomResourceDefinition resources separately -kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.crds.yaml +# Install the CustomResourceDefinition resources separately +kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.crds.yaml # **Important:** # If you are running Kubernetes v1.15 or below, you From 568a5377d8e808617576d1e1b53a4487d199fc86 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 22 Sep 2020 09:41:04 +0100 Subject: [PATCH 11/58] Version 1.0.1. Revert CRD flag --- .../air-gap/install-rancher/_index.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md index dec2bf92dfe..c95159ca386 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md @@ -85,17 +85,21 @@ By default, Rancher generates a CA and uses cert-manager to issue the certificat 1. Fetch the latest cert-manager chart available from the [Helm chart repository](https://hub.helm.sh/charts/jetstack/cert-manager). ```plain - helm fetch jetstack/cert-manager --version v0.15.1 + helm fetch jetstack/cert-manager --version v1.0.1 ``` 1. Render the cert manager template with the options you would like to use to install the chart. Remember to set the `image.repository` option to pull the image from your private registry. This will create a `cert-manager` directory with the Kubernetes manifest files. ```plain - helm template cert-manager ./cert-manager-v0.15.1.tgz --output-dir . \ + helm template cert-manager ./cert-manager-v1.0.1.tgz --output-dir . \ --namespace cert-manager \ --set image.repository=/quay.io/jetstack/cert-manager-controller \ --set webhook.image.repository=/quay.io/jetstack/cert-manager-webhook \ --set cainjector.image.repository=/quay.io/jetstack/cert-manager-cainjector - --set installCRDs=true + ``` + +1. Download the required CRD file for cert-manager + ```plain + curl -L -o cert-manager/cert-manager-crd.yaml https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.crds.yaml ``` 1. Render the Rancher template, declaring your chosen options. Use the reference table below to replace each placeholder. Rancher needs to be configured to use the private registry in order to provision any Rancher launched Kubernetes clusters or Rancher tools. From 20cdeb1b73a67221fe6575c7dbff1935d4dd50fe Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 22 Sep 2020 09:44:30 +0100 Subject: [PATCH 12/58] Revert back CRD settings --- .../air-gap/install-rancher/_index.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md index c95159ca386..3c77f17f536 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md @@ -184,14 +184,18 @@ If you are using self-signed certificates, install cert-manager: kubectl create namespace cert-manager ``` -1. Launch cert-manager. +1. Create the cert-manager CustomResourceDefinitions (CRDs). ```plain -kubectl apply -R -f ./cert-manager +kubectl apply -f cert-manager/cert-manager-crd.yaml ``` > **Note:** > If you are running Kubernetes v1.15 or below, you will need to add the `--validate=false` flag to your `kubectl apply` command above, or else you will receive a validation error relating to the `x-kubernetes-preserve-unknown-fields` field in cert-manager’s CustomResourceDefinition resources. This is a benign error and occurs due to the way kubectl performs resource validation. +1. Launch cert-manager. +```plain +kubectl apply -R -f ./cert-manager +``` {{% /accordion %}} From 588ec4334e54083174a4247644055208dfb26742 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Tue, 22 Sep 2020 09:45:45 +0100 Subject: [PATCH 13/58] Fix version to 1.0.1 --- .../air-gap/populate-private-registry/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md index 285181f6ec0..8032be68c40 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md @@ -59,7 +59,7 @@ In a Kubernetes Install, if you elect to use the Rancher default self-signed TLS ```plain helm repo add jetstack https://charts.jetstack.io helm repo update - helm fetch jetstack/cert-manager --version v0.15.1 + helm fetch jetstack/cert-manager --version v1.0.1 helm template ./cert-manager-.tgz | grep -oP '(?<=image: ").*(?=")' >> ./rancher-images.txt ``` From 718ccc0c655ded802113632ed78a42dd4532a298 Mon Sep 17 00:00:00 2001 From: Bryson <15582+bryson@users.noreply.github.com> Date: Tue, 27 Oct 2020 16:31:19 -0700 Subject: [PATCH 14/58] Update _index.md Update cert-manager commands with new github paths, matching the current cert-manager docs. https://cert-manager.io/docs/installation/uninstall/kubernetes/#uninstalling-with-helm --- .../resources/encryption/upgrading-cert-manager/_index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/rancher/v2.x/en/installation/resources/encryption/upgrading-cert-manager/_index.md b/content/rancher/v2.x/en/installation/resources/encryption/upgrading-cert-manager/_index.md index 5468c772d67..0fe87b4103c 100644 --- a/content/rancher/v2.x/en/installation/resources/encryption/upgrading-cert-manager/_index.md +++ b/content/rancher/v2.x/en/installation/resources/encryption/upgrading-cert-manager/_index.md @@ -53,16 +53,16 @@ In order to upgrade cert-manager, follow these instructions: helm uninstall cert-manager ``` - Delete the CustomResourceDefinition using the link to the version vX.Y you installed + Delete the CustomResourceDefinition using the link to the version vX.Y.Z you installed ```plain - kubectl delete -f https://raw.githubusercontent.com/jetstack/cert-manager/release-X.Y/deploy/manifests/00-crds.yaml + kubectl delete -f https://github.com/jetstack/cert-manager/releases/download/vX.Y.Z/cert-manager.crds.yaml ``` 1. Install the CustomResourceDefinition resources separately ```plain - kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.12/deploy/manifests/00-crds.yaml + kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/vX.Y.Z/cert-manager.crds.yaml ``` > **Note:** From eea77e8f832b1569a95f29ff19eed1191c2f0e7d Mon Sep 17 00:00:00 2001 From: Court Date: Fri, 30 Oct 2020 06:57:09 -0500 Subject: [PATCH 15/58] Update _index.md Oracle Linux is no longer referred to as OEL. It's simply OL now. https://en.wikipedia.org/wiki/Oracle_Linux --- content/rke/latest/en/os/_index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/rke/latest/en/os/_index.md b/content/rke/latest/en/os/_index.md index 9c09b13e0b8..ecfa281b7ee 100644 --- a/content/rke/latest/en/os/_index.md +++ b/content/rke/latest/en/os/_index.md @@ -8,7 +8,7 @@ weight: 5 - [Operating System](#operating-system) - [General Linux Requirements](#general-linux-requirements) - - [Red Hat Enterprise Linux (RHEL) / Oracle Enterprise Linux (OEL) / CentOS](#red-hat-enterprise-linux-rhel-oracle-enterprise-linux-oel-centos) + - [Red Hat Enterprise Linux (RHEL) / Oracle Linux (OL) / CentOS](#red-hat-enterprise-linux-rhel-oracle-enterprise-linux-oel-centos) - [Using upstream Docker](#using-upstream-docker) - [Using RHEL/CentOS packaged Docker](#using-rhel-centos-packaged-docker) @@ -98,9 +98,9 @@ xt_tcpudp | net.bridge.bridge-nf-call-iptables=1 ``` -### Red Hat Enterprise Linux (RHEL) / Oracle Enterprise Linux (OEL) / CentOS +### Red Hat Enterprise Linux (RHEL) / Oracle Linux (OL) / CentOS -If using Red Hat Enterprise Linux, Oracle Enterprise Linux or CentOS, you cannot use the `root` user as [SSH user]({{}}/rke/latest/en/config-options/nodes/#ssh-user) due to [Bugzilla 1527565](https://bugzilla.redhat.com/show_bug.cgi?id=1527565). Please follow the instructions below how to setup Docker correctly, based on the way you installed Docker on the node. +If using Red Hat Enterprise Linux, Oracle Linux or CentOS, you cannot use the `root` user as [SSH user]({{}}/rke/latest/en/config-options/nodes/#ssh-user) due to [Bugzilla 1527565](https://bugzilla.redhat.com/show_bug.cgi?id=1527565). Please follow the instructions below how to setup Docker correctly, based on the way you installed Docker on the node. #### Using upstream Docker If you are using upstream Docker, the package name is `docker-ce` or `docker-ee`. You can check the installed package by executing: From a8b10a52925c84988f959c44b1c305bd5de35f10 Mon Sep 17 00:00:00 2001 From: Bastian Hofmann Date: Fri, 30 Oct 2020 16:22:28 +0100 Subject: [PATCH 16/58] Add guide how to migrate dashboards and alerts from monitoring v1 to v2 Signed-off-by: Bastian Hofmann --- .../migration/alert_2.4_to_2.5_source.png | Bin 0 -> 56577 bytes .../v2.5/migrating/_index.md | 65 +++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 assets/img/rancher/monitoring/migration/alert_2.4_to_2.5_source.png diff --git a/assets/img/rancher/monitoring/migration/alert_2.4_to_2.5_source.png b/assets/img/rancher/monitoring/migration/alert_2.4_to_2.5_source.png new file mode 100644 index 0000000000000000000000000000000000000000..131fdb76a025d02e95071c704a3a2dfc4d6fdac9 GIT binary patch literal 56577 zcmeFZcT`hd(>DxA5fMR=-VsEk_g)lf(gdW0ju3k2y%!q_(m}ckfSM&B+>;3Ed*80}>u+~X7XU^=IJu|!gW}ieo(NZD3Mt2Pd2ZvNm^^q

gu3XdMp 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 + +you have to create a PrometheusRule configuration like this in any namespace + +```yaml +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: custom-rules + namespace: default +spec: + groups: + - name: custom.rules + rules: + - alert: Custom Expression Alert + expr: prometheus_query > 5 + for: 5m + labels: + severity: critical + annotations: + summary: "The result of prometheus_query has been larger than 5 for 5m. Current value {{ $value }}" +``` + +For more details on how to configure PrometheusRules in Monitoring V2 see [this page]({{}}/rancher/v2.x/en/monitoring-alerting/v2.5/configuration). From cffa8eb5738e1ed0ff34a2973929f2ee6613ff9e Mon Sep 17 00:00:00 2001 From: Bastian Hofmann Date: Mon, 2 Nov 2020 11:39:14 +0100 Subject: [PATCH 17/58] Add guide how to migrate dashboards and alerts from monitoring v1 to v2 Clarify V1 uninstallation and Grafana dashboard import. Signed-off-by: Bastian Hofmann --- .../v2.x/en/monitoring-alerting/v2.5/migrating/_index.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/migrating/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/migrating/_index.md index 0a7510ed150..1351aef81f5 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.5/migrating/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/migrating/_index.md @@ -5,7 +5,7 @@ aliases: - /rancher/v2.x/en/monitoring-alerting/migrating --- -If you previously enabled Monitoring, Alerting, or Notifiers in Rancher prior to v2.5, there is no automatic upgrade path for switching to the new monitoring/alerting solution. You will need to disable monitoring/alerting/notifiers in the same way it was disabled in Rancher v2.4 before deploying the new monitoring solution via Cluster Explorer. +If you previously enabled Monitoring, Alerting, or Notifiers in Rancher prior to v2.5, there is no automatic upgrade path for switching to the new monitoring/alerting solution. Before deploying the new monitoring solution via Cluster Explore, you will need to disable and remove all existing custom alerts, notifiers and monitoring installations for the whole cluster and in all projects. ### Monitoring Prior to Rancher v2.5 @@ -48,7 +48,8 @@ You can migrate any dashboard added to Grafana in Monitoring V1 to Monitoring V2 In the JSON Model, change all `datasource` fields from `RANCHER_MONITORING` to `Prometheus`. You can easily do this by replacing all occurrences of `"datasource": "RANCHER_MONITORING"` with `"datasource": "Prometheus"`. -Now you can either [import](https://grafana.com/docs/grafana/latest/dashboards/export-import/) this JSON Model into the Monitoring V2 Grafana UI, or you can provide this with a ConfigMap: +If Grafana is backed by a persistent volume, you can now [import](https://grafana.com/docs/grafana/latest/dashboards/export-import/) this JSON Model into the Monitoring V2 Grafana UI. +It is recommended though to provide the dashboard to Grafana with a ConfigMap: ```yaml apiVersion: v1 @@ -65,6 +66,8 @@ data: } ``` +Once this ConfigMap is created, the dashboard will automatically be added to Grafana. + #### Migrating Alerts It is only possible to directly migrate expression-based alerts to Monitoring V2. Fortunately, the event-based alerts that could be set up to alert on system component, node or workload events, are already covered out-of-the-box by the alerts that are part of Monitoring V2. So it is not necessary to migrate them. From 241066ade0d1800af1bd9781d0783973bfc2b01f Mon Sep 17 00:00:00 2001 From: cluse Date: Tue, 3 Nov 2020 11:51:11 -0700 Subject: [PATCH 18/58] Say minimum required version to use K3s config.yaml --- content/k3s/latest/en/installation/install-options/_index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/k3s/latest/en/installation/install-options/_index.md b/content/k3s/latest/en/installation/install-options/_index.md index cffd0b436d5..efab7e77072 100644 --- a/content/k3s/latest/en/installation/install-options/_index.md +++ b/content/k3s/latest/en/installation/install-options/_index.md @@ -79,6 +79,8 @@ For details on configuring the K3s agent, refer to the [agent configuration refe ### Configuration File +_Available as of v1.19.1+k3s1_ + In addition to configuring K3s with environment variables and CLI arguments, K3s can also use a config file. By default, values present in a YAML file located at `/etc/rancher/k3s/config.yaml` will be used on install. From fd0d2e090bdec5759b1368e2ea11ebd1cbc498da Mon Sep 17 00:00:00 2001 From: Eamon Bauman Date: Tue, 3 Nov 2020 14:11:43 -0600 Subject: [PATCH 19/58] added docs for logging migration --- .../logging/migration/rancher_logging.png | Bin 0 -> 28466 bytes .../v2.x/en/logging/v2.5/migrating/_index.md | 191 ++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 assets/img/rancher/logging/migration/rancher_logging.png create mode 100644 content/rancher/v2.x/en/logging/v2.5/migrating/_index.md diff --git a/assets/img/rancher/logging/migration/rancher_logging.png b/assets/img/rancher/logging/migration/rancher_logging.png new file mode 100644 index 0000000000000000000000000000000000000000..1815c4ab7fdcd43d156d979694b0388a2dc35d21 GIT binary patch literal 28466 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�L8y;^RP9k!~4+ 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 Note: The pre-v2.5 user interface is now referred to as the _Cluster Manager_. The v2.5+ dashboard is referred to as the _Cluster Explorer_. + +## Installation + +To install logging in Rancher v2.5+, use the following steps: + +1. Open the Rancher dashboard. This can be done by clicking the _Cluster Explorer_ button within the cluster context, or from the global page in the _Cluster Manager_. + +2. Once within the _Cluster Explorer_, navigate to _Apps & Marketplace_ from the dropdown in the upper-left corner of the dashboard. + +3. Once in the _Apps & Marketplace_ section, locate the "rancher-logging" chart. It is available as part of the "Rancher" repository, installed by default in Rancher v2.5+: + + ![rancher logging chart image](../.../../../../../../../../assets/img/rancher/logging/migration/rancher_logging.png) + +4. Scroll to the bottom of the page and click _Install_. + +## Terminology & Familiarity + +In v2.5, logging configuration is centralized under a _Logging_ menu option available in the _Cluster Explorer_. It is from this menu option that logging for both cluster and namespace is configured. + +> Note: Logging is installed on a per-cluster basis. You will need to navigate between clusters to configure logging for each cluster. + +There are four key concepts to understand for v2.5+ logging: + +1. Outputs + + _Outputs_ are a configuration resource that determine a destination for collected logs. This is where settings for aggregators such as ElasticSearch, Kafka, etc. are stored. _Outputs_ are namespaced resources. + +2. Flows + + _Flows_ are a configuration resource that determine collection, filtering, and destination rules for logs. It is within a flow that one will configure what logs to collect, how to mutate or filter them, and which outputs to send the logs to. _Flows_ are namespaced resources, and can connect either to an _Output_ in the same namespace, or a _ClusterOutput_. + +3. ClusterOutputs + + _ClusterOutputs_ serve the same functionality as _Outputs_, except they are a cluster-scoped resource. _ClusterOutputs_ are necessary when collecting logs cluster-wide, or if you wish to provide an output to all namespaces in your cluster. + +4. ClusterFlows + + _ClusterFlows_ serve the same function as _Flows_, but at the cluster level. They are used to configure log collection for an entire cluster, instead of on a per-namespace level. _ClusterFlows_ are also where mutations and filters are defined, same as _Flows_ (in functionality). + +# Cluster Logging + +To configure cluster-wide logging for v2.5+ logging, one needs to setup a _ClusterFlow_. This object defines the source of logs, any transformations or filters to be applied, and finally the output(s) for the logs. + +> Important: _ClusterFlows_ must be defined within the `cattle-logging-system` namespace. _ClusterFlows_ will not work if defined in any other namespace. + +In legacy logging, in order to collect logs from across the entire cluster, one only needed to enable cluster-level logging and define the desired output. This basic approach remains in v2.5+ logging. To replicate legacy cluster-level logging, follow these steps: + +1. Define a _ClusterOutput_ according to the instructions found under [Output Configuration](#output-configuration) +2. Create a _ClusterFlow_, ensuring that it is set to be created in the `cattle-logging-system` namespace + 1. Remove all _Include_ and _Exclude_ rules from the flow definition. This ensures that all logs are gathered. + 2. You do not need to configure any filters if you do not wish - default behavior does not require their creation + 3. Define your cluster output(s) + +This will result in logs from all sources in the cluster (all pods, and all system components) being collected and sent to the output(s) you defined in the _ClusterFlow_. + +# Project Logging + +Logging in v2.5+ is not project-aware. This means that in order to collect logs from pods running in project namespaces, you will need to define _Flows_ for those namespaces. + +To collect logs from a specific namespace, follow these steps: + +1. Define an _Output_ or _ClusterOutput_ according to the instructions found under [Output Configuration](#output-configuration) +2. Create a _Flow_, ensuring that it is set to be created in the namespace in which you want to gather logs. + 1. If you wish to define _Include_ or _Exclude_ rules, you may do so. Otherwise, removal of all rules will result in all pods in the target namespace having their logs collected. + 2. You do not need to configure any filters if you do not wish - default behavior does not require their creation + 3. Define your output(s) - these can be either _ClusterOutput_ or _Output_ objects. + +This will result in logs from all sources in the namespace (pods) being collected and sent to the output(s) you defined in your _Flow_. + +> To collect logs from a project, repeat the above steps for every namespace within the project. Alternatively, you can label your project workloads with a common label (e.g. `project=my-project`) and use a _ClusterFlow_ to collect logs from all pods matching this label. + +# Output Configuration +In legacy logging, there are five logging destinations to choose from: Elasticsearch, Splunk, Kafka, Fluentd, and Syslog. With the exception of Syslog, all of these destinations are available in logging v2.5+. + + +## Elasticsearch + +| Legacy Logging | v2.5+ Logging | Notes | +|-----------------------------------------------|-----------------------------------|-----------------------------------------------------------| +| Endpoint | Target -> Host | Make sure to specify Scheme (https/http), as well as Port | +| X-Pack Security -> Username | Access -> User | | +| X-Pack Security -> Password | Access -> Password | Password must now be stored in a secret | +| SSL Configuration -> Client Private Key | SSL -> Client Key | Key must now be stored in a secret | +| SSL Configuration -> Client Certificate | SSL -> Client Cert | Certificate must now be stored in a secret | +| SSL Configuration -> Client Key Password | SSL -> Client Key Pass | Password must now be stored in a secret | +| SSL Configuration -> Enabled SSL Verification | SSL -> Certificate Authority File | Certificate must now be stored in a secret | + + +In legacy logging, indices were automatically created according to the format in the "Index Patterns" section. In v2.5 logging, default behavior has been changed to logging to a single index. You can still configure index pattern functionality on the output object by editing as YAML and inputting the following values: + +``` +... +spec: + elasticsearch: + ... + logstash_format: true + logstash_prefix: + logstash_dateformat: "%Y-%m-%d" +``` + +Replace `` with the prefix for the indices that will be created. In legacy logging, this defaulted to the name of the cluster. + +## Splunk + +| Legacy Logging | v2.5+ Logging | Notes | +|------------------------------------------|----------------------------------------|----------------------------------------------------------------------------------------| +| HEC Configuration -> Endpoint | Target -> Host | Protocol (https/http) and port must be defined separately from the host | +| HEC Configuration -> Token | Access -> Token | Token must now be stored as a secret | +| HEC Configuration -> Index | Edit as YAML -> `index` | `index` field must be added as YAML key under `spec.splunkHec` | +| HEC Configuration -> Source | Edit as YAML -> `source` | `source` field must be added as YAML key under `spec.splunkHec` | +| SSL Configuration -> Client Private Key | Edit as YAML -> `client_key` | `client_key` field must be added as YAML key under `spec.splunkHec`. See (1) | +| SSL Configuration -> Client Certificate | Edit as YAML -> `client_cert` | `client_cert` field must be added as YAML key under `spec.splunkHec`. See (1) | +| SSL Configuration -> Client Key Password | _Not Supported_ | Specifying a password for the client private key is not currently supported. | +| SSL Configuration -> SSL Verify | Edit as YAML -> `ca_file` or `ca_path` | `ca_file` or `ca_path` field must be added as YAML key under `spec.splunkHec`. See (2) | + +_(1) `client_key` and `client_cert` values must be paths to the key and cert files, respectively. These files must be mounted into the `rancher-logging-fluentd` pod in order to be used._ + +_(2) Users can configure either `ca_file` (a path to a PEM-encoded CA certificate) or `ca_path` (a path to a directory containing CA certificates in PEM format). These files must be mounted into the `rancher-logging-fluentd` pod in order to be used._ + +## Kafka + +| Legacy Logging | v2.5+ Logging | Notes | +|-----------------------------------------|----------------------------|------------------------------------------------------| +| Kafka Configuration -> Endpoint Type | - | Zookeeper is no longer supported as an endpoint type | +| Kafka Configuration -> Endpoint | Target -> Brokers | Comma-separated list of brokers (host:port) | +| Kafka Configuration -> Topic | Target -> Default Topic | | +| SSL Configuration -> Client Private Key | SSL -> SSL Client Cert | Certificate must be stored as a secret | +| SSL Configuration -> Client Certificate | SSL -> SSL Client Cert Key | Key must be stored as a secret | +| SSL Configuration -> CA Certificate PEM | SSL -> SSL CA Cert | Certificate must be stored as a secret | +| SASL Configuration -> Username | Access -> Username | Username must be stored in a secret | +| SASL Configuration -> Password | Access -> Password | Password must be stored in a secret | +| SASL Configuration -> Scram Mechanism | Access -> Scram Mechanism | Input mechanism as string, e.g. "sha256" or "sha512" | + +## Fluentd + +As of v2.5.2, it is only possible to add a single Fluentd server using the "Edit as Form" option. To add multiple servers, edit the output as YAML and input multiple servers. + +| Legacy Logging | v2.5+ Logging | Notes | +|------------------------------------------|-----------------------------------------------------|----------------------------------------------------------------------| +| Fluentd Configuration -> Endpoint | Target -> Host, Port | Input the host and port separately | +| Fluentd Configuration -> Shared Key | Access -> Shared Key | Shared key must be stored as a secret | +| Fluentd Configuration -> Username | Access -> Username | Username must be stored as a secret | +| Fluentd Configuration -> Password | Access -> Password | Password must be stored as a secret | +| Fluentd Configuration -> Hostname | Edit as YAML -> `host` | `host` field set as YAML key under `spec.forward.servers[n]` | +| Fluentd Configuration -> Weight | Edit as YAML -> `weight` | `weight` field set as YAML key under `spec.forward.servers[n]` | +| SSL Configuration -> Use TLS | - | Do not need to explicitly enable. Define client cert fields instead. | +| SSL Configuration -> Client Private Key | Edit as YAML -> `tls_private_key_path` | Field set as YAML key under `spec.forward`. See (1) | +| SSL Configuration -> Client Certificate | Edit as YAML -> `tls_client_cert_path` | Field set as YAML key under `spec.forward`. See (1) | +| SSL Configuration -> Client Key Password | Edit as YAML -> `tls_client_private_key_passphrase` | Field set as YAML key under `spec.forward`. See (1) | +| SSL Configuration -> SSL Verify | Edit as YAML -> `tls_insecure_mode` | Field set as YAML key under `spec.forward`. Default: `false` | +| SSL Configuration -> CA Certificate PEM | Edit as YAML -> `tls_cert_path` | Field set as YAML key under `spec.forward`. See (1) | +| Enable Gzip Compression | - | No longer supported in v2.5+ logging | + +_(1) These values are to be specified as paths to files. Those files must be mounted into the `rancher-logging-fluentd` pod in order to be used._ + +## Syslog + +As of v2.5.2, syslog is not currently supported as an output using v2.5+ logging. + +## Custom Log Fields + +In order to add custom log fields, you will need to add the following YAML to your flow configuration: + +``` +... +spec: + filters: + - record_modifier: + records: + - foo: "bar" +``` + +(replace `foo: "bar"` with custom log fields you wish to add) + +# System Logging + +In legacy logging, collecting logs from system components was accomplished by checking a box labeled "Include System Log" when setting up cluster logging. In v2.5+ logging, system logs are gathered in one of two ways: + +1. Gather all cluster logs, not specifying any match or exclusion rules. This results in all container logs from the cluster being collected, which includes system logs. +2. Specifically target system logs by adding match rules for system components. Specific match rules depend on the component being collected. \ No newline at end of file From b6334e863bfc9949b5831ca8a36cd982864f8425 Mon Sep 17 00:00:00 2001 From: Caleb Bron Date: Tue, 3 Nov 2020 13:56:52 -0700 Subject: [PATCH 20/58] Clarify node agents in 2.5 Also changing title of page to Registered as thats how it is referred to moving forward. --- .../v2.x/en/troubleshooting/imported-clusters/_index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/troubleshooting/imported-clusters/_index.md b/content/rancher/v2.x/en/troubleshooting/imported-clusters/_index.md index b7a6e6b28eb..87aba226c73 100644 --- a/content/rancher/v2.x/en/troubleshooting/imported-clusters/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/imported-clusters/_index.md @@ -1,5 +1,5 @@ --- -title: Imported clusters +title: Registered clusters weight: 105 --- @@ -15,6 +15,8 @@ If the cattle-cluster-agent cannot connect to the configured `server-url`, the c #### cattle-node-agent +> Note: Starting in Rancher 2.5 cattle-node-agents are only present in clusters created in Rancher with RKE. + Check if the cattle-node-agent pods are present on each node, have status **Running** and don't have a high count of Restarts: ``` From efcf0ed85b0078d61f6fa6aac3a1f3e7896b6733 Mon Sep 17 00:00:00 2001 From: Eamon Bauman Date: Mon, 9 Nov 2020 13:25:43 -0600 Subject: [PATCH 21/58] removed install instructions, assets. linked to existing --- .../logging/migration/rancher_logging.png | Bin 28466 -> 0 bytes .../v2.x/en/logging/v2.5/migrating/_index.md | 12 +----------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 assets/img/rancher/logging/migration/rancher_logging.png diff --git a/assets/img/rancher/logging/migration/rancher_logging.png b/assets/img/rancher/logging/migration/rancher_logging.png deleted file mode 100644 index 1815c4ab7fdcd43d156d979694b0388a2dc35d21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28466 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�L8y;^RP9k!~4+ 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/rancher/v2.x/en/logging/v2.5/#enabling-logging-for-rancher-managed-clusters). ## Terminology & Familiarity From 15a208dcc065f676799860a451507168a4babb0f Mon Sep 17 00:00:00 2001 From: cluse Date: Mon, 9 Nov 2020 15:07:43 -0700 Subject: [PATCH 22/58] Update section about K3s support for SELinux --- content/k3s/latest/en/advanced/_index.md | 40 ++++++++++++++---------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/content/k3s/latest/en/advanced/_index.md b/content/k3s/latest/en/advanced/_index.md index 178e58c4e38..7edd6c620dc 100644 --- a/content/k3s/latest/en/advanced/_index.md +++ b/content/k3s/latest/en/advanced/_index.md @@ -19,7 +19,7 @@ This section contains advanced information describing the different ways you can - [Additional preparation for Alpine Linux setup](#additional-preparation-for-alpine-linux-setup) - [Running K3d (K3s in Docker) and docker-compose](#running-k3d-k3s-in-docker-and-docker-compose) - [Enabling legacy iptables on Raspbian Buster](#enabling-legacy-iptables-on-raspbian-buster) -- [Experimental SELinux Support](#experimental-selinux-support) +- [SELinux Support](#selinux-support) # Certificate Rotation @@ -304,15 +304,20 @@ sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy sudo reboot ``` -# Experimental SELinux Support +# SELinux Support -As of release v1.17.4+k3s1, experimental support for SELinux has been added to K3s's embedded containerd. If you are installing K3s on a system where SELinux is enabled by default (such as CentOS), you must ensure the proper SELinux policies have been installed. +_Supported as of v1.19.4+k3s1. Experimental as of v1.17.4+k3s1._ + +If you are installing K3s on a system where SELinux is enabled by default (such as CentOS), you must ensure the proper SELinux policies have been installed. + +### Automatic Installation + +_Available as of v1.19.3+k3s2_ + +The [install script]({{}}/k3s/latest/en/installation/install-options/#installation-script-options) will automatically install the SELinux RPM from the Rancher RPM repository if on a compatible system if not performing an air-gapped install. Automatic installation can be skipped by setting `INSTALL_K3S_SKIP_SELINUX_RPM=true`. + +### Manual Installation -{{% tabs %}} -{{% tab "automatic installation" %}} -As of release v1.19.3+k3s2, the [install script]({{}}/k3s/latest/en/installation/install-options/#installation-script-options) will automatically install the SELinux RPM from the Rancher RPM repository if on a compatible system if not performing an air-gapped install. Automatic installation can be skipped by setting `INSTALL_K3S_SKIP_SELINUX_RPM=true`. -{{% /tab %}} -{{% tab "manual installation" %}} The necessary policies can be installed with the following commands: ``` yum install -y container-selinux selinux-policy-base @@ -321,17 +326,14 @@ yum install -y https://rpm.rancher.io/k3s/latest/common/centos/7/noarch/k3s-seli To force the install script to log a warning rather than fail, you can set the following environment variable: `INSTALL_K3S_SELINUX_WARN=true`. -{{% /tab %}} -{{% /tabs %}} +### Enabling and Disabling SELinux Enforcement -The way that SELinux enforcement is enabled or disabled depends on the K3s version. Prior to v1.19.x, SELinux enablement for the builtin containerd was automatic but could be disabled by passing `--disable-selinux`. With v1.19.x and beyond, enabling SELinux must be affirmatively configured via the `--selinux` flag or config file entry. Servers and agents that specify both the `--selinux` and (deprecated) `--disable-selinux` flags will fail to start. - -Using a custom `--data-dir` under SELinux is not supported. To customize it, you would most likely need to write your own custom policy. For guidance, you could refer to the [containers/container-selinux](https://github.com/containers/container-selinux) repository, which contains the SELinux policy files for Container Runtimes, and the [rancher/k3s-selinux](https://github.com/rancher/k3s-selinux) repository, which contains the SELinux policy for K3s . +The way that SELinux enforcement is enabled or disabled depends on the K3s version. {{% tabs %}} {{% tab "K3s v1.19.1+k3s1" %}} -To leverage experimental SELinux, specify the `--selinux` flag when starting K3s servers and agents. +To leverage SELinux, specify the `--selinux` flag when starting K3s servers and agents. This option can also be specified in the K3s [configuration file:]({{}}/k3s/latest/en/installation/install-options/#configuration-file) @@ -341,12 +343,16 @@ selinux: true The `--disable-selinux` option should not be used. It is deprecated and will be either ignored or will be unrecognized, resulting in an error, in future minor releases. +Using a custom `--data-dir` under SELinux is not supported. To customize it, you would most likely need to write your own custom policy. For guidance, you could refer to the [containers/container-selinux](https://github.com/containers/container-selinux) repository, which contains the SELinux policy files for Container Runtimes, and the [rancher/k3s-selinux](https://github.com/rancher/k3s-selinux) repository, which contains the SELinux policy for K3s . + {{%/tab%}} {{% tab "K3s prior to v1.19.1+k3s1" %}} -You can turn off SELinux enforcement in the embedded containerd by launching K3s with the `--disable-selinux` flag. +SELinux is automatically enabled for the built-in containerd. + +To turn off SELinux enforcement in the embedded containerd, launch K3s with the `--disable-selinux` flag. + +Using a custom `--data-dir` under SELinux is not supported. To customize it, you would most likely need to write your own custom policy. For guidance, you could refer to the [containers/container-selinux](https://github.com/containers/container-selinux) repository, which contains the SELinux policy files for Container Runtimes, and the [rancher/k3s-selinux](https://github.com/rancher/k3s-selinux) repository, which contains the SELinux policy for K3s . {{%/tab%}} {{% /tabs %}} - -Note that support for SELinux in containerd is still under development. Progress can be tracked in [this pull request](https://github.com/containerd/cri/pull/1246). From 8c9fd3440be47de682fa9aa8fcdd9138c99d6279 Mon Sep 17 00:00:00 2001 From: Bastian Hofmann Date: Tue, 10 Nov 2020 16:25:34 +0100 Subject: [PATCH 23/58] Adapt default value for noProxy helm chart variable New value was introduced in 2.5 with https://github.com/rancher/rancher/commit/7feec1fb9713df4903a056c5375926a613a5d85d Signed-off-by: Bastian Hofmann --- .../behind-proxy/install-rancher/_index.md | 2 +- .../single-node-docker/proxy/_index.md | 4 +++- .../v2.x/en/installation/resources/chart-options/_index.md | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/install-rancher/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/install-rancher/_index.md index 86d64a487f3..532abe59d5d 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/install-rancher/_index.md @@ -34,7 +34,7 @@ helm upgrade --install cert-manager jetstack/cert-manager \ --namespace cert-manager --version v0.15.2 \ --set http_proxy=http://${proxy_host} \ --set https_proxy=http://${proxy_host} \ - --set no_proxy=127.0.0.0/8\\,10.0.0.0/8\\,172.16.0.0/12\\,192.168.0.0/16 + --set no_proxy=127.0.0.0/8\\,10.0.0.0/8\\,172.16.0.0/12\\,192.168.0.0/16\\,.svc\\,.cluster.local ``` Now you should wait until cert-manager is finished starting up: diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/proxy/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/proxy/_index.md index 100acc4f282..e097a3dae40 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/proxy/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/proxy/_index.md @@ -26,6 +26,8 @@ Passing environment variables to the Rancher container can be done using `-e KEY - `127.0.0.1` - `0.0.0.0` - `10.0.0.0/8` +- `.svc` +- `.cluster.local` The example below is based on a proxy server accessible at `http://192.168.0.1:3128`, and excluding usage the proxy when accessing network range `192.168.10.0/24` and every hostname under the domain `example.com`. @@ -34,7 +36,7 @@ docker run -d --restart=unless-stopped \ -p 80:80 -p 443:443 \ -e HTTP_PROXY="http://192.168.10.1:3128" \ -e HTTPS_PROXY="http://192.168.10.1:3128" \ - -e NO_PROXY="localhost,127.0.0.1,0.0.0.0,10.0.0.0/8,192.168.10.0/24,example.com" \ + -e NO_PROXY="localhost,127.0.0.1,0.0.0.0,10.0.0.0/8,192.168.10.0/24,.svc,.cluster.local,example.com" \ --privileged \ rancher/rancher:latest ``` diff --git a/content/rancher/v2.x/en/installation/resources/chart-options/_index.md b/content/rancher/v2.x/en/installation/resources/chart-options/_index.md index ce976deb1b7..41c18e66db6 100644 --- a/content/rancher/v2.x/en/installation/resources/chart-options/_index.md +++ b/content/rancher/v2.x/en/installation/resources/chart-options/_index.md @@ -54,7 +54,7 @@ aliases: | `ingress.configurationSnippet` | "" | `string` - Add additional Nginx configuration. Can be used for proxy configuration. _Note: Available as of v2.0.15, v2.1.10 and v2.2.4_ | | `letsEncrypt.ingress.class` | "" | `string` - optional ingress class for the cert-manager acmesolver ingress that responds to the Let's Encrypt ACME challenges | | `proxy` | "" | `string` - HTTP[S] proxy server for Rancher | -| `noProxy` | "127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" | `string` - comma separated list of hostnames or ip address not to use the proxy | +| `noProxy` | "127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.cluster.local" | `string` - comma separated list of hostnames or ip address not to use the proxy | | `resources` | {} | `map` - rancher pod resource requests & limits | | `rancherImage` | "rancher/rancher" | `string` - rancher image source | | `rancherImageTag` | same as chart version | `string` - rancher/rancher image tag | @@ -134,11 +134,11 @@ Example on setting a static proxy header with `ingress.configurationSnippet`. Th Rancher requires internet access for some functionality (helm charts). Use `proxy` to set your proxy server. -Add your IP exceptions to the `noProxy` list. Make sure you add the Service cluster IP range (default: 10.43.0.1/16) and any worker cluster `controlplane` nodes. Rancher supports CIDR notation ranges in this list. +Add your IP exceptions to the `noProxy` list. Make sure you add the Pod cluster IP range (default: `10.42.0.0/16`), Service cluster IP range (default: `10.43.0.0/16`), the internal cluster domains (default: `.svc,.cluster.local`) and any worker cluster `controlplane` nodes. Rancher supports CIDR notation ranges in this list. ```plain --set proxy="http://:@:/" ---set noProxy="127.0.0.0/8\,10.0.0.0/8\,172.16.0.0/12\,192.168.0.0/16" +--set noProxy="127.0.0.0/8\,10.0.0.0/8\,172.16.0.0/12\,192.168.0.0/16,.svc,.cluster.local" ``` ### Additional Trusted CAs From 8242a26b33e5191eedb9635349f20d390fb12aad Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Tue, 10 Nov 2020 10:13:00 -0700 Subject: [PATCH 24/58] Change cert-manager version from v1.0.1 to v1.0.4 --- .../v2.x/en/installation/k8s-install/helm-rancher/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md index f6bcec0c245..3fa99ac72d8 100644 --- a/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/k8s-install/helm-rancher/_index.md @@ -89,7 +89,7 @@ These instructions are adapted from the [official cert-manager documentation](ht ``` # Install the CustomResourceDefinition resources separately -kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.crds.yaml +kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.4/cert-manager.crds.yaml # **Important:** # If you are running Kubernetes v1.15 or below, you @@ -114,7 +114,7 @@ helm repo update helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ - --version v1.0.1 + --version v1.0.4 ``` Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the cert-manager namespace for running pods: From ec87dc9dcb794f1454d6ad8d629a2ea4a2662b9f Mon Sep 17 00:00:00 2001 From: cluse Date: Tue, 10 Nov 2020 10:37:06 -0700 Subject: [PATCH 25/58] Change cert-manager version to v1.0.4 --- .../air-gap/install-rancher/_index.md | 6 +++--- .../air-gap/populate-private-registry/_index.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md index 148ef712370..c27acbcca55 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/install-rancher/_index.md @@ -85,12 +85,12 @@ By default, Rancher generates a CA and uses cert-manager to issue the certificat 1. Fetch the latest cert-manager chart available from the [Helm chart repository](https://hub.helm.sh/charts/jetstack/cert-manager). ```plain - helm fetch jetstack/cert-manager --version v1.0.1 + helm fetch jetstack/cert-manager --version v1.0.4 ``` 1. Render the cert manager template with the options you would like to use to install the chart. Remember to set the `image.repository` option to pull the image from your private registry. This will create a `cert-manager` directory with the Kubernetes manifest files. ```plain - helm template cert-manager ./cert-manager-v1.0.1.tgz --output-dir . \ + helm template cert-manager ./cert-manager-v1.0.4.tgz --output-dir . \ --namespace cert-manager \ --set image.repository=/quay.io/jetstack/cert-manager-controller \ --set webhook.image.repository=/quay.io/jetstack/cert-manager-webhook \ @@ -99,7 +99,7 @@ By default, Rancher generates a CA and uses cert-manager to issue the certificat 1. Download the required CRD file for cert-manager ```plain - curl -L -o cert-manager/cert-manager-crd.yaml https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.crds.yaml + curl -L -o cert-manager/cert-manager-crd.yaml https://github.com/jetstack/cert-manager/releases/download/v1.0.4/cert-manager.crds.yaml ``` 1. Render the Rancher template, declaring your chosen options. Use the reference table below to replace each placeholder. Rancher needs to be configured to use the private registry in order to provision any Rancher launched Kubernetes clusters or Rancher tools. diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md index 8bc0f92e73a..6c0b68fceea 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/air-gap/populate-private-registry/_index.md @@ -63,7 +63,7 @@ In a Kubernetes Install, if you elect to use the Rancher default self-signed TLS ```plain helm repo add jetstack https://charts.jetstack.io helm repo update - helm fetch jetstack/cert-manager --version v1.0.1 + helm fetch jetstack/cert-manager --version v1.0.4 helm template ./cert-manager-.tgz | grep -oP '(?<=image: ").*(?=")' >> ./rancher-images.txt ``` From c1d4cdfa024f2491a2cc53ede4d67e09524032eb Mon Sep 17 00:00:00 2001 From: Jose Corral Date: Wed, 11 Nov 2020 06:43:52 +0100 Subject: [PATCH 26/58] Remove Longhorn no longer needed storageclass info --- content/k3s/latest/en/storage/_index.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/content/k3s/latest/en/storage/_index.md b/content/k3s/latest/en/storage/_index.md index 790cbd04e38..760bd893fff 100644 --- a/content/k3s/latest/en/storage/_index.md +++ b/content/k3s/latest/en/storage/_index.md @@ -89,12 +89,6 @@ kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/master/depl Longhorn will be installed in the namespace `longhorn-system`. -Before we create a PVC, we will create a storage class for Longhorn with this yaml: - -``` -kubectl create -f https://raw.githubusercontent.com/longhorn/longhorn/master/examples/storageclass.yaml -``` - Apply the yaml to create the PVC and pod: ``` From 1f67d3268d1cea36487a3141d55abc759280efea Mon Sep 17 00:00:00 2001 From: Bastian Hofmann Date: Thu, 12 Nov 2020 13:50:27 +0100 Subject: [PATCH 27/58] Add documentation for the new entity ID field in the keycloak configuration The field was introduced with https://github.com/rancher/rancher/pull/29555 in 2.5.2 Signed-off-by: Bastian Hofmann --- .../authentication/keycloak/_index.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/content/rancher/v2.x/en/admin-settings/authentication/keycloak/_index.md b/content/rancher/v2.x/en/admin-settings/authentication/keycloak/_index.md index e5859ff84b1..0425173433e 100644 --- a/content/rancher/v2.x/en/admin-settings/authentication/keycloak/_index.md +++ b/content/rancher/v2.x/en/admin-settings/authentication/keycloak/_index.md @@ -17,7 +17,7 @@ If your organization uses Keycloak Identity Provider (IdP) for user authenticati `Sign Documents` | `ON` 1 `Sign Assertions` | `ON` 1 All other `ON/OFF` Settings | `OFF` - `Client ID` | `https://yourRancherHostURL/v1-saml/keycloak/saml/metadata`2 + `Client ID` | Either `https://yourRancherHostURL/v1-saml/keycloak/saml/metadata` or the value configured in the `Entry ID Field` of the Rancher Keycloak configuration2 `Client Name` | (e.g. `rancher`) `Client Protocol` | `SAML` `Valid Redirect URI` | `https://yourRancherHostURL/v1-saml/keycloak/saml/acs` @@ -65,15 +65,16 @@ If your organization uses Keycloak Identity Provider (IdP) for user authenticati 1. Complete the **Configure Keycloak Account** form. - | Field | Description | - | ------------------------- | -------------------------------------------------------------------------------------- | - | Display Name Field | The attribute that contains the display name of users.

Example: `givenName` | - | User Name Field | The attribute that contains the user name/given name.

Example: `email` | - | UID Field | An attribute that is unique to every user.

Example: `email` | - | Groups Field | Make entries for managing group memberships.

Example: `member` | - | Rancher API Host | The URL for your Rancher Server. | - | Private Key / Certificate | A key/certificate pair to create a secure shell between Rancher and your IdP. | - | IDP-metadata | The `metadata.xml` file that you exported from your IdP server. | + | Field | Description | + | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | + | Display Name Field | The attribute that contains the display name of users.

Example: `givenName` | + | User Name Field | The attribute that contains the user name/given name.

Example: `email` | + | UID Field | An attribute that is unique to every user.

Example: `email` | + | Groups Field | Make entries for managing group memberships.

Example: `member` | + | Entity ID Field | The ID that needs to be configured as a client ID in the Keycloak client.

Default: `https://yourRancherHostURL/v1-saml/keycloak/saml/metadata` | + | Rancher API Host | The URL for your Rancher Server. | + | Private Key / Certificate | A key/certificate pair to create a secure shell between Rancher and your IdP. | + | IDP-metadata | The `metadata.xml` file that you exported from your IdP server. | >**Tip:** You can generate a key/certificate pair using an openssl command. For example: > From 8534996de485866d1656483e9f242a6fd21e28e7 Mon Sep 17 00:00:00 2001 From: Bastian Hofmann Date: Thu, 12 Nov 2020 18:44:34 +0100 Subject: [PATCH 28/58] Extend monitoring v1 to v2 migration guide * Add more default information how to remove monitoring v1 * Add documentation how to migrate a v1 alert through the new PrometheusRule UI * Add a note how to migrate v1 notifiers Signed-off-by: Bastian Hofmann --- .../migration/alert_2.4_to_2.5_target.png | Bin 0 -> 183664 bytes .../v2.5/migrating/_index.md | 23 +++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 assets/img/rancher/monitoring/migration/alert_2.4_to_2.5_target.png diff --git a/assets/img/rancher/monitoring/migration/alert_2.4_to_2.5_target.png b/assets/img/rancher/monitoring/migration/alert_2.4_to_2.5_target.png new file mode 100644 index 0000000000000000000000000000000000000000..d452c4afedea547caabee180da968ca6bfa3357f GIT binary patch literal 183664 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 g5G?j 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 Project -> Tools -> Monitoring +* Ensure that all project-monitoring apps in all projects have been removed and are not recreated after a few minutes +* Disable the cluster monitoring installation under Cluster -> Tools -> Monitoring +* Ensure that the cluster-monitoring app and the monitoring-operator app in the System project have been removed and are not recreated after a few minutes + #### Migrating Grafana Dashboards You can migrate any dashboard added to Grafana in Monitoring V1 to Monitoring V2. In Monitoring V1 you can export an existing dashboard like this: @@ -49,7 +58,7 @@ You can migrate any dashboard added to Grafana in Monitoring V1 to Monitoring V2 In the JSON Model, change all `datasource` fields from `RANCHER_MONITORING` to `Prometheus`. You can easily do this by replacing all occurrences of `"datasource": "RANCHER_MONITORING"` with `"datasource": "Prometheus"`. If Grafana is backed by a persistent volume, you can now [import](https://grafana.com/docs/grafana/latest/dashboards/export-import/) this JSON Model into the Monitoring V2 Grafana UI. -It is recommended though to provide the dashboard to Grafana with a ConfigMap: +It is recommended to provide the dashboard to Grafana with a ConfigMap in the `cattle-dashboards` namespace that has the label `grafana_dashboard: "1"`: ```yaml apiVersion: v1 @@ -76,7 +85,7 @@ To migrate the following expression alert {{< img "/img/rancher/monitoring/migration/alert_2.4_to_2.5_source.png" "">}} -you have to create a PrometheusRule configuration like this in any namespace +you have to either create a PrometheusRule configuration like this in any namespace ```yaml apiVersion: monitoring.coreos.com/v1 @@ -97,4 +106,12 @@ spec: summary: "The result of prometheus_query has been larger than 5 for 5m. Current value {{ $value }}" ``` -For more details on how to configure PrometheusRules in Monitoring V2 see [this page]({{}}/rancher/v2.x/en/monitoring-alerting/v2.5/configuration). +or add the Prometheus Rule through the Cluster Explorer + +{{< img "/img/rancher/monitoring/migration/alert_2.4_to_2.5_target.png" "">}} + +For more details on how to configure PrometheusRules in Monitoring V2 see [Monitoring Configuration]({{}}/rancher/v2.x/en/monitoring-alerting/v2.5/configuration#prometheusrules). + +#### Migrating notifiers + +There is no direct equivalent for how notifiers work in Monitoring V1. Instead you have to replicate the desired setup with [Routes and Receivers]({{}}/rancher/v2.x/en/monitoring-alerting/v2.5/configuration#alertmanager-config) in Monitoring V2. From 61eccf8dd1624c27b52e7b7abdc3dc2a1a5ea54a Mon Sep 17 00:00:00 2001 From: cluse Date: Thu, 12 Nov 2020 14:59:25 -0700 Subject: [PATCH 29/58] Update OS requirements section in K3s docs --- .../installation-requirements/_index.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/content/k3s/latest/en/installation/installation-requirements/_index.md b/content/k3s/latest/en/installation/installation-requirements/_index.md index c8c330d6d7d..f5b64b19f53 100644 --- a/content/k3s/latest/en/installation/installation-requirements/_index.md +++ b/content/k3s/latest/en/installation/installation-requirements/_index.md @@ -17,17 +17,14 @@ If all your nodes have the same hostname, use the `--with-node-id` option to app ## Operating Systems -K3s should run on just about any flavor of Linux. +K3s is expected to work on most modern Linux systems. -K3s is officially supported and tested on the following operating systems and their subsequent non-major releases: +Some OSs have specific requirements: -* Ubuntu 16.04 (amd64) -* Ubuntu 18.04 (amd64) -* Raspbian Buster* +- If you are using **Raspbian Buster**, follow [these steps]({{}}/k3s/latest/en/advanced/#enabling-legacy-iptables-on-raspbian-buster) to switch to legacy iptables. +- If you are using **Alpine Linux**, follow [these steps]({{}}/k3s/latest/en/advanced/#additional-preparation-for-alpine-linux-setup) for additional setup. -\* If you are using **Raspbian Buster**, follow [these steps]({{}}/k3s/latest/en/advanced/#enabling-legacy-iptables-on-raspbian-buster) to switch to legacy iptables. - -If you are using **Alpine Linux**, follow [these steps]({{}}/k3s/latest/en/advanced/#additional-preparation-for-alpine-linux-setup) for additional setup. +For more information on which OSs were tested with Rancher managed K3s clusters, refer to the [Rancher support and maintenance terms.](https://rancher.com/support-maintenance-terms/) ## Hardware From 8f172317a0907bc651176986da63248c4896480b Mon Sep 17 00:00:00 2001 From: cluse Date: Thu, 12 Nov 2020 15:24:44 -0700 Subject: [PATCH 30/58] Redefine 'repeat wait time' in alerting section --- .../v2.0.x-v2.4.x/cluster-alerts/_index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-alerts/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-alerts/_index.md index 7ab29bf56df..81fbcc45dd5 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-alerts/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-alerts/_index.md @@ -90,7 +90,7 @@ This alert type monitor for events that affect one of the Kubernetes master comp - **Group Wait Time**: How long to wait to buffer alerts of the same group before sending initially, default to 30 seconds. - **Group Interval Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 30 seconds. - - **Repeat Wait Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 1 hour. + - **Repeat Wait Time**: How long to wait before re-sending a given alert that has already been sent, default to 1 hour. {{% /accordion %}} {{% accordion id="resource-event" label="Resource Event Alerts" %}} @@ -125,7 +125,7 @@ This alert type monitors for specific events that are thrown from a resource typ - **Group Wait Time**: How long to wait to buffer alerts of the same group before sending initially, default to 30 seconds. - **Group Interval Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 30 seconds. - - **Repeat Wait Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 1 hour. + - **Repeat Wait Time**: How long to wait before re-sending a given alert that has already been sent, default to 1 hour. {{% /accordion %}} {{% accordion id="node" label="Node Alerts" %}} @@ -152,7 +152,7 @@ This alert type monitors for events that occur on a specific node. - **Group Wait Time**: How long to wait to buffer alerts of the same group before sending initially, default to 30 seconds. - **Group Interval Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 30 seconds. - - **Repeat Wait Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 1 hour. + - **Repeat Wait Time**: How long to wait before re-sending a given alert that has already been sent, default to 1 hour. {{% /accordion %}} {{% accordion id="node-selector" label="Node Selector Alerts" %}} @@ -179,7 +179,7 @@ This alert type monitors for events that occur on any node on marked with a labe - **Group Wait Time**: How long to wait to buffer alerts of the same group before sending initially, default to 30 seconds. - **Group Interval Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 30 seconds. - - **Repeat Wait Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 1 hour. + - **Repeat Wait Time**: How long to wait before re-sending a given alert that has already been sent, default to 1 hour. {{% /accordion %}} {{% accordion id="cluster-expression" label="Metric Expression Alerts" %}} @@ -224,7 +224,7 @@ This alert type monitors for the overload from Prometheus expression querying, i - **Group Wait Time**: How long to wait to buffer alerts of the same group before sending initially, default to 30 seconds. - **Group Interval Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 30 seconds. - - **Repeat Wait Time**: How long to wait before sending an alert that has been added to a group which contains already fired alerts, default to 1 hour. + - **Repeat Wait Time**: How long to wait before re-sending a given alert that has already been sent, default to 1 hour. {{% /accordion %}} From ae3eebd011e86f2f646918a6b2652e4e1f806ac6 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Thu, 12 Nov 2020 16:29:13 -0700 Subject: [PATCH 31/58] Fix internal link --- content/rke/latest/en/os/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rke/latest/en/os/_index.md b/content/rke/latest/en/os/_index.md index ecfa281b7ee..7a60fce88ff 100644 --- a/content/rke/latest/en/os/_index.md +++ b/content/rke/latest/en/os/_index.md @@ -8,7 +8,7 @@ weight: 5 - [Operating System](#operating-system) - [General Linux Requirements](#general-linux-requirements) - - [Red Hat Enterprise Linux (RHEL) / Oracle Linux (OL) / CentOS](#red-hat-enterprise-linux-rhel-oracle-enterprise-linux-oel-centos) + - [Red Hat Enterprise Linux (RHEL) / Oracle Linux (OL) / CentOS](#red-hat-enterprise-linux-rhel-oracle-enterprise-linux-ol-centos) - [Using upstream Docker](#using-upstream-docker) - [Using RHEL/CentOS packaged Docker](#using-rhel-centos-packaged-docker) From 30497d5ba16c19843f266b937c96a0cc7e0e2280 Mon Sep 17 00:00:00 2001 From: cluse Date: Thu, 12 Nov 2020 19:15:18 -0700 Subject: [PATCH 32/58] Add --privileged flag to install command previously in shortcode --- .../single-node-docker/advanced/_index.md | 14 +++++++++++++- .../single-node-install-external-lb/_index.md | 14 +++++++++++++- layouts/shortcodes/persistentdata.html | 17 ----------------- 3 files changed, 26 insertions(+), 19 deletions(-) delete mode 100644 layouts/shortcodes/persistentdata.html diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/advanced/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/advanced/_index.md index 8eefb2db503..b8cf98496f0 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/advanced/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/single-node-docker/advanced/_index.md @@ -83,7 +83,19 @@ If you are visiting this page to complete an air gap installation, you must prep ### Persistent Data -{{< persistentdata >}} +Rancher uses etcd as a datastore. When Rancher is installed with Docker, the embedded etcd is being used. The persistent data is at the following path in the container: `/var/lib/rancher`. + +You can bind mount a host volume to this location to preserve data on the host it is running on: + +``` +docker run -d --restart=unless-stopped \ + -p 80:80 -p 443:443 \ + -v /opt/rancher:/var/lib/rancher \ + --privileged \ + rancher/rancher:latest +``` + +As of Rancher v2.5, privileged access is [required.](../#privileged-access-for-rancher-v2-5) ### Running `rancher/rancher` and `rancher/rancher-agent` on the Same Node diff --git a/content/rancher/v2.x/en/installation/resources/advanced/single-node-install-external-lb/_index.md b/content/rancher/v2.x/en/installation/resources/advanced/single-node-install-external-lb/_index.md index c2f9b6ea1dd..eeabd44485b 100644 --- a/content/rancher/v2.x/en/installation/resources/advanced/single-node-install-external-lb/_index.md +++ b/content/rancher/v2.x/en/installation/resources/advanced/single-node-install-external-lb/_index.md @@ -197,7 +197,19 @@ If you are visiting this page to complete an [Air Gap Installation]({{} ### Persistent Data -{{< persistentdata >}} +Rancher uses etcd as a datastore. When Rancher is installed with Docker, the embedded etcd is being used. The persistent data is at the following path in the container: `/var/lib/rancher`. + +You can bind mount a host volume to this location to preserve data on the host it is running on: + +``` +docker run -d --restart=unless-stopped \ + -p 80:80 -p 443:443 \ + -v /opt/rancher:/var/lib/rancher \ + --privileged \ + rancher/rancher:latest +``` + +As of Rancher v2.5, privileged access is [required.](../#privileged-access-for-rancher-v2-5) This layer 7 NGINX configuration is tested on NGINX version 1.13 (mainline) and 1.14 (stable). diff --git a/layouts/shortcodes/persistentdata.html b/layouts/shortcodes/persistentdata.html deleted file mode 100644 index f816e7fff37..00000000000 --- a/layouts/shortcodes/persistentdata.html +++ /dev/null @@ -1,17 +0,0 @@ -

From e19ee79d9636ce80aabcdcf202bb29705443c086 Mon Sep 17 00:00:00 2001 From: Tejeev Date: Tue, 17 Nov 2020 18:24:10 +0000 Subject: [PATCH 33/58] Overlay test updated Standardized names and etc. Used `operator: Exists` toleration from the rancher overlay test rather than the no schedule and execute from the RKE. Added some verbosity --- .../en/troubleshooting/networking/_index.md | 142 +++++------------- 1 file changed, 39 insertions(+), 103 deletions(-) diff --git a/content/rancher/v2.x/en/troubleshooting/networking/_index.md b/content/rancher/v2.x/en/troubleshooting/networking/_index.md index 76dd5b7cd71..d476c1695ee 100644 --- a/content/rancher/v2.x/en/troubleshooting/networking/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/networking/_index.md @@ -14,9 +14,9 @@ Double check if all the [required ports]({{}}/rancher/v2.x/en/cluster-p The pod can be scheduled to any of the hosts you used for your cluster, but that means that the NGINX ingress controller needs to be able to route the request from `NODE_1` to `NODE_2`. This happens over the overlay network. If the overlay network is not functioning, you will experience intermittent TCP/HTTP connection failures due to the NGINX ingress controller not being able to route to the pod. -To test the overlay network, you can launch the following `DaemonSet` definition. This will run a `swiss-army-knife` container on every host (image was developed by Rancher engineers), which we will use to run a `ping` test between containers on all hosts. +To test the overlay network, you can launch the following `DaemonSet` definition. This will run a `swiss-army-knife` container on every host (image was developed by Rancher engineers and can be found here: https://github.com/leodotcloud/swiss-army-knife), which we will use to run a `ping` test between containers on all hosts. -1. Save the following file as `ds-overlaytest.yml` +1. Save the following file as `overlaytest.yml` ``` apiVersion: apps/v1 @@ -30,126 +30,62 @@ To test the overlay network, you can launch the following `DaemonSet` definition template: metadata: labels: - name: ds-overlaytest + name: overlaytest spec: tolerations: - - effect: NoExecute - key: "node-role.kubernetes.io/etcd" - value: "true" - - effect: NoSchedule - key: "node-role.kubernetes.io/controlplane" - value: "true" + - operator: Exists containers: - image: leodotcloud/swiss-army-knife imagePullPolicy: Always name: overlaytest command: ["sh", "-c", "tail -f /dev/null"] terminationMessagePath: /dev/termination-log + ``` -2. Launch it using `kubectl create -f ds-overlaytest.yml` +2. Launch it using `kubectl create -f overlaytest.yml` 3. Wait until `kubectl rollout status ds/overlaytest -w` returns: `daemon set "overlaytest" successfully rolled out`. -4. Run the following command, from the same location, to let each container on every host ping each other (it's a single line bash command). - +4. Run the following script, from the same location. It will have each `overlaytest` container on every host ping each other: ``` - ### Check if overlay network is functioning correctly - -The pod can be scheduled to any of the hosts you used for your cluster, but that means that the NGINX ingress controller needs to be able to route the request from `NODE_1` to `NODE_2`. This happens over the overlay network. If the overlay network is not functioning, you will experience intermittent TCP/HTTP connection failures due to the NGINX ingress controller not being able to route to the pod. - -To test the overlay network, you can launch the following `DaemonSet` definition. This will run a `swiss-army-knife` container on every host (image was developed by Rancher engineers), which we will use to run a `ping` test between containers on all hosts. - -1. Save the following file as `ds-overlaytest.yml` - - ``` - apiVersion: apps/v1 - kind: DaemonSet - metadata: - name: overlaytest - spec: - selector: - matchLabels: - name: overlaytest - template: - metadata: - labels: - name: ds-overlaytest - spec: - tolerations: - - effect: NoExecute - key: "node-role.kubernetes.io/etcd" - value: "true" - - effect: NoSchedule - key: "node-role.kubernetes.io/controlplane" - value: "true" - containers: - - image: leodotcloud/swiss-army-knife - imagePullPolicy: Always - name: overlaytest - command: ["sh", "-c", "tail -f /dev/null"] - terminationMessagePath: /dev/termination-log + #!/bin/bash + echo "=> Start network overlay test" + kubectl get pods -l name=overlaytest -o jsonpath='{range .items[*]}{@.metadata.name}{" "}{@.spec.nodeName}{"\n"}{end}' | + while read spod shost + do kubectl get pods -l name=overlaytest -o jsonpath='{range .items[*]}{@.status.podIP}{" "}{@.spec.nodeName}{"\n"}{end}' | + while read tip thost + do kubectl --request-timeout='10s' exec $spod -c overlaytest -- /bin/sh -c "ping -c2 $tip > /dev/null 2>&1" + RC=$? + if [ $RC -ne 0 ] + then echo FAIL: $spod on $shost cannot reach pod IP $tip on $thost + else echo $shost can reach $thost + fi + done + done + echo "=> End network overlay test" ``` -2. Launch it using `kubectl create -f ds-overlaytest.yml` -3. Wait until `kubectl rollout status ds/overlaytest -w` returns: `daemon set "overlaytest" successfully rolled out`. -4. Run the following command, from the same location, to let each container on every host ping each other (it's a single line bash command). - - ``` - echo "=> Start network overlay test"; kubectl get pods -l name=ds-overlaytest -o jsonpath='{range .items[*]}{@.metadata.name}{" "}{@.spec.nodeName}{"\n"}{end}' | while read spod shost; do kubectl get pods -l name=ds-overlaytest -o jsonpath='{range .items[*]}{@.status.podIP}{" "}{@.spec.nodeName}{"\n"}{end}' | while read tip thost; do kubectl --request-timeout='10s' exec $spod -- /bin/sh -c "ping -c2 $tip > /dev/null 2>&1"; RC=$?; if [ $RC -ne 0 ]; then echo $shost cannot reach $thost; fi; done; done; echo "=> End network overlay test" - ``` - -5. When this command has finished running, the output indicating everything is correct is: +5. When this command has finished running, it will output the state of each route: ``` => Start network overlay test - Pinging from pod overlaytest-4cpx5 on host NODE1 - to pod ip 10.42.1.29 on host NODE1 - to pod ip 10.42.2.19 on host NODE2 - to pod ip 10.42.4.12 on host NODE3 - Pinging from pod overlaytest-vms6w on host NODE2 - to pod ip 10.42.1.29 on host NODE1 - to pod ip 10.42.2.19 on host NODE2 - to pod ip 10.42.4.12 on host NODE3 + Error from server (NotFound): pods "wk2" not found + FAIL: overlaytest-5bglp on wk2 cannot reach pod IP 10.42.7.3 on wk2 + Error from server (NotFound): pods "wk2" not found + FAIL: overlaytest-5bglp on wk2 cannot reach pod IP 10.42.0.5 on cp1 + Error from server (NotFound): pods "wk2" not found + FAIL: overlaytest-5bglp on wk2 cannot reach pod IP 10.42.2.12 on wk1 + command terminated with exit code 1 + FAIL: overlaytest-v4qkl on cp1 cannot reach pod IP 10.42.7.3 on wk2 + cp1 can reach cp1 + cp1 can reach wk1 + command terminated with exit code 1 + FAIL: overlaytest-xpxwp on wk1 cannot reach pod IP 10.42.7.3 on wk2 + wk1 can reach cp1 + wk1 can reach wk1 => End network overlay test ``` - -If you see error in the output, that means that the [required ports]({{}}/rancher/v2.x/en/cluster-provisioning/node-requirements/#networking-requirements/) for overlay networking are not opened between the hosts indicated. - -If a path fails the overlay test, you will see errors like the following: - -``` -command terminated with exit code 1 -NODE2 cannot reach NODE1 -``` - -Cleanup the DaemonSet by running `kubectl delete ds/overlaytest`. - - ``` - -5. When this command has finished running, the output indicating everything is correct is: - - ``` - => Start network overlay test - => End network overlay test - ``` - -If you see error in the output, that means that the [required ports]({{}}/rancher/v2.x/en/cluster-provisioning/node-requirements/#networking-requirements/) for overlay networking are not opened between the hosts indicated. - -Example error output of a situation where NODE1 had the UDP ports blocked. - -``` -=> Start network overlay test -command terminated with exit code 1 -NODE2 cannot reach NODE1 -command terminated with exit code 1 -NODE3 cannot reach NODE1 -command terminated with exit code 1 -NODE1 cannot reach NODE2 -command terminated with exit code 1 -NODE1 cannot reach NODE3 -=> End network overlay test -``` - -Cleanup the DaemonSet by running `kubectl delete ds/overlaytest`. + If you see error in the output, there is some issue with the route between the pods on the two hosts. In the above output the node `wk2` has no connectivity over the overlay network. This could be because the [required ports]({{}}/rancher/v2.x/en/cluster-provisioning/node-requirements/#networking-requirements/) for overlay networking are not opened for `wk2`. +6. You can now clean up the DaemonSet by running `kubectl delete ds/overlaytest`. ### Check if MTU is correctly configured on hosts and on peering/tunnel appliances/devices From b34d8d9f300d5f456b95ca831387190aa18b840d Mon Sep 17 00:00:00 2001 From: cluse Date: Mon, 16 Nov 2020 18:21:28 -0700 Subject: [PATCH 34/58] Say only one domain name can be used for DHCP option sets with Windows --- .../rke-clusters/windows-clusters/_index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md index 62b280d5f4c..5ff394c2ed2 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md @@ -68,6 +68,9 @@ For **Host Gateway (L2bridge)** networking, it's best to use the same Layer 2 ne For **VXLAN (Overlay)** networking, the [KB4489899](https://support.microsoft.com/en-us/help/4489899) hotfix must be installed. Most cloud-hosted VMs already have this hotfix. +If you are configuring DHCP options sets for an AWS virtual private cloud, note that in the `domain-name` option field, only one domain name can be specified. According to the DHCP options [documentation:](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_DHCP_Options.html) + +> Some Linux operating systems accept multiple domain names separated by spaces. However, other Linux operating systems and Windows treat the value as a single domain, which results in unexpected behavior. If your DHCP options set is associated with a VPC that has instances with multiple operating systems, specify only one domain name. ### Architecture Requirements The Kubernetes cluster management nodes (`etcd` and `controlplane`) must be run on Linux nodes. From 30d7f0b6e8e7f2d0f8651ca3a7f0acc232dd06c0 Mon Sep 17 00:00:00 2001 From: cluse Date: Tue, 17 Nov 2020 16:41:37 -0700 Subject: [PATCH 35/58] Remove extra copies of Rancher v2.4 benchmark/hardening guides --- .../v2.x/en/security/benchmark-2.4/_index.md | 2266 ----------------- .../v2.x/en/security/hardening-2.4/_index.md | 720 ------ 2 files changed, 2986 deletions(-) delete mode 100644 content/rancher/v2.x/en/security/benchmark-2.4/_index.md delete mode 100644 content/rancher/v2.x/en/security/hardening-2.4/_index.md diff --git a/content/rancher/v2.x/en/security/benchmark-2.4/_index.md b/content/rancher/v2.x/en/security/benchmark-2.4/_index.md deleted file mode 100644 index 672fbba7826..00000000000 --- a/content/rancher/v2.x/en/security/benchmark-2.4/_index.md +++ /dev/null @@ -1,2266 +0,0 @@ ---- -title: CIS Benchmark Rancher Self-Assessment Guide - v2.4 -weight: 204 ---- - -### CIS Kubernetes Benchmark v1.5 - Rancher v2.4 with Kubernetes v1.15 - -[Click here to download a PDF version of this document](https://releases.rancher.com/documents/security/2.4/Rancher_Benchmark_Assessment.pdf) - -#### Overview - -This document is a companion to the Rancher v2.4 security hardening guide. The hardening guide provides prescriptive guidance for hardening a production installation of Rancher, and this benchmark guide is meant to help you evaluate the level of security of the hardened cluster against each control in the benchmark. - -This guide corresponds to specific versions of the hardening guide, Rancher, Kubernetes, and the CIS Benchmark: - -Self Assessment Guide Version | Rancher Version | Hardening Guide Version | Kubernetes Version | CIS Benchmark Version ----------------------------|----------|---------|-------|----- -Self Assessment Guide v2.4 | Rancher v2.4 | Hardening Guide v2.4 | Kubernetes v1.15 | Benchmark v1.5 - -Because Rancher and RKE install Kubernetes services as Docker containers, many of the control verification checks in the CIS Kubernetes Benchmark don't apply and will have a result of `Not Applicable`. This guide will walk through the various controls and provide updated example commands to audit compliance in Rancher-created clusters. - -This document is to be used by Rancher operators, security teams, auditors and decision makers. - -For more detail about each audit, including rationales and remediations for failing tests, you can refer to the corresponding section of the CIS Kubernetes Benchmark v1.5. You can download the benchmark after logging in to [CISecurity.org]( https://www.cisecurity.org/benchmark/kubernetes/). - -#### Testing controls methodology - -Rancher and RKE install Kubernetes services via Docker containers. Configuration is defined by arguments passed to the container at the time of initialization, not via configuration files. - -Where control audits differ from the original CIS benchmark, the audit commands specific to Rancher Labs are provided for testing. -When performing the tests, you will need access to the Docker command line on the hosts of all three RKE roles. The commands also make use of the the [jq](https://stedolan.github.io/jq/) and [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (with valid config) tools to and are required in the testing and evaluation of test results. - -> NOTE: only scored tests are covered in this guide. - -### Controls - ---- -## 1 Master Node Security Configuration -### 1.1 Master Node Configuration Files - -#### 1.1.1 Ensure that the API server pod specification file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the API server. All configuration is passed in as arguments at container run time. - -#### 1.1.2 Ensure that the API server pod specification file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the API server. All configuration is passed in as arguments at container run time. - -#### 1.1.3 Ensure that the controller manager pod specification file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. - -#### 1.1.4 Ensure that the controller manager pod specification file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. - -#### 1.1.5 Ensure that the scheduler pod specification file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. - -#### 1.1.6 Ensure that the scheduler pod specification file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. - -#### 1.1.7 Ensure that the etcd pod specification file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for etcd. All configuration is passed in as arguments at container run time. - -#### 1.1.8 Ensure that the etcd pod specification file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for etcd. All configuration is passed in as arguments at container run time. - -#### 1.1.11 Ensure that the etcd data directory permissions are set to `700` or more restrictive (Scored) - -**Result:** PASS - -**Remediation:** -On the etcd server node, get the etcd data directory, passed as an argument `--data-dir`, -from the below command: - -``` bash -ps -ef | grep etcd -``` - -Run the below command (based on the etcd data directory found above). For example, - -``` bash -chmod 700 /var/lib/etcd -``` - -**Audit Script:** 1.1.11.sh - -``` -#!/bin/bash -e - -etcd_bin=${1} - -test_dir=$(ps -ef | grep ${etcd_bin} | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%') - -docker inspect etcd | jq -r '.[].HostConfig.Binds[]' | grep "${test_dir}" | cut -d ":" -f 1 | xargs stat -c %a -``` - -**Audit Execution:** - -``` -./1.1.11.sh etcd -``` - -**Expected result**: - -``` -'700' is equal to '700' -``` - -#### 1.1.12 Ensure that the etcd data directory ownership is set to `etcd:etcd` (Scored) - -**Result:** PASS - -**Remediation:** -On the etcd server node, get the etcd data directory, passed as an argument `--data-dir`, -from the below command: - -``` bash -ps -ef | grep etcd -``` - -Run the below command (based on the etcd data directory found above). -For example, -``` bash -chown etcd:etcd /var/lib/etcd -``` - -**Audit Script:** 1.1.12.sh - -``` -#!/bin/bash -e - -etcd_bin=${1} - -test_dir=$(ps -ef | grep ${etcd_bin} | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%') - -docker inspect etcd | jq -r '.[].HostConfig.Binds[]' | grep "${test_dir}" | cut -d ":" -f 1 | xargs stat -c %U:%G -``` - -**Audit Execution:** - -``` -./1.1.12.sh etcd -``` - -**Expected result**: - -``` -'etcd:etcd' is present -``` - -#### 1.1.13 Ensure that the `admin.conf` file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE does not store the kubernetes default kubeconfig credentials file on the nodes. It’s presented to user where RKE is run. -We recommend that this `kube_config_cluster.yml` file be kept in secure store. - -#### 1.1.14 Ensure that the admin.conf file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE does not store the kubernetes default kubeconfig credentials file on the nodes. It’s presented to user where RKE is run. -We recommend that this `kube_config_cluster.yml` file be kept in secure store. - -#### 1.1.15 Ensure that the `scheduler.conf` file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. - -#### 1.1.16 Ensure that the `scheduler.conf` file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. - -#### 1.1.17 Ensure that the `controller-manager.conf` file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. - -#### 1.1.18 Ensure that the `controller-manager.conf` file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. - -#### 1.1.19 Ensure that the Kubernetes PKI directory and file ownership is set to `root:root` (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the master node. -For example, - -``` bash -chown -R root:root /etc/kubernetes/ssl -``` - -**Audit:** - -``` -stat -c %U:%G /etc/kubernetes/ssl -``` - -**Expected result**: - -``` -'root:root' is present -``` - -#### 1.1.20 Ensure that the Kubernetes PKI certificate file permissions are set to `644` or more restrictive (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the master node. -For example, - -``` bash -chmod -R 644 /etc/kubernetes/ssl -``` - -**Audit Script:** check_files_permissions.sh - -``` -#!/usr/bin/env bash - -# This script is used to ensure the file permissions are set to 644 or -# more restrictive for all files in a given directory or a wildcard -# selection of files -# -# inputs: -# $1 = /full/path/to/directory or /path/to/fileswithpattern -# ex: !(*key).pem -# -# $2 (optional) = permission (ex: 600) -# -# outputs: -# true/false - -# Turn on "extended glob" for use of '!' in wildcard -shopt -s extglob - -# Turn off history to avoid surprises when using '!' -set -H - -USER_INPUT=$1 - -if [[ "${USER_INPUT}" == "" ]]; then - echo "false" - exit -fi - - -if [[ -d ${USER_INPUT} ]]; then - PATTERN="${USER_INPUT}/*" -else - PATTERN="${USER_INPUT}" -fi - -PERMISSION="" -if [[ "$2" != "" ]]; then - PERMISSION=$2 -fi - -FILES_PERMISSIONS=$(stat -c %n\ %a ${PATTERN}) - -while read -r fileInfo; do - p=$(echo ${fileInfo} | cut -d' ' -f2) - - if [[ "${PERMISSION}" != "" ]]; then - if [[ "$p" != "${PERMISSION}" ]]; then - echo "false" - exit - fi - else - if [[ "$p" != "644" && "$p" != "640" && "$p" != "600" ]]; then - echo "false" - exit - fi - fi -done <<< "${FILES_PERMISSIONS}" - - -echo "true" -exit -``` - -**Audit Execution:** - -``` -./check_files_permissions.sh '/etc/kubernetes/ssl/*.pem' -``` - -**Expected result**: - -``` -'true' is present -``` - -#### 1.1.21 Ensure that the Kubernetes PKI key file permissions are set to `600` (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the master node. -For example, - -``` bash -chmod -R 600 /etc/kubernetes/ssl/certs/serverca -``` - -**Audit Script:** 1.1.21.sh - -``` -#!/bin/bash -e -check_dir=${1:-/etc/kubernetes/ssl} - -for file in $(find ${check_dir} -name "*key.pem"); do - file_permission=$(stat -c %a ${file}) - if [[ "${file_permission}" == "600" ]]; then - continue - else - echo "FAIL: ${file} ${file_permission}" - exit 1 - fi -done - -echo "pass" -``` - -**Audit Execution:** - -``` -./1.1.21.sh /etc/kubernetes/ssl -``` - -**Expected result**: - -``` -'pass' is present -``` - -### 1.2 API Server - -#### 1.2.2 Ensure that the `--basic-auth-file` argument is not set (Scored) - -**Result:** PASS - -**Remediation:** -Follow the documentation and configure alternate mechanisms for authentication. Then, -edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and remove the `--basic-auth-file=` parameter. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--basic-auth-file' is not present -``` - -#### 1.2.3 Ensure that the `--token-auth-file` parameter is not set (Scored) - -**Result:** PASS - -**Remediation:** -Follow the documentation and configure alternate mechanisms for authentication. Then, -edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and remove the `--token-auth-file=` parameter. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--token-auth-file' is not present -``` - -#### 1.2.4 Ensure that the `--kubelet-https` argument is set to true (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml -on the master node and remove the `--kubelet-https` parameter. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--kubelet-https' is present OR '--kubelet-https' is not present -``` - -#### 1.2.5 Ensure that the `--kubelet-client-certificate` and `--kubelet-client-key` arguments are set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and set up the TLS connection between the -apiserver and kubelets. Then, edit API server pod specification file -`/etc/kubernetes/manifests/kube-apiserver.yaml` on the master node and set the -kubelet client certificate and key parameters as below. - -``` bash ---kubelet-client-certificate= ---kubelet-client-key= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--kubelet-client-certificate' is present AND '--kubelet-client-key' is present -``` - -#### 1.2.6 Ensure that the `--kubelet-certificate-authority` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and setup the TLS connection between -the apiserver and kubelets. Then, edit the API server pod specification file -`/etc/kubernetes/manifests/kube-apiserver.yaml` on the master node and set the -`--kubelet-certificate-authority` parameter to the path to the cert file for the certificate authority. -`--kubelet-certificate-authority=` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--kubelet-certificate-authority' is present -``` - -#### 1.2.7 Ensure that the `--authorization-mode` argument is not set to `AlwaysAllow` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--authorization-mode` parameter to values other than `AlwaysAllow`. -One such example could be as below. - -``` bash ---authorization-mode=RBAC -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'Node,RBAC' not have 'AlwaysAllow' -``` - -#### 1.2.8 Ensure that the `--authorization-mode` argument includes `Node` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--authorization-mode` parameter to a value that includes `Node`. - -``` bash ---authorization-mode=Node,RBAC -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'Node,RBAC' has 'Node' -``` - -#### 1.2.9 Ensure that the `--authorization-mode` argument includes `RBAC` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--authorization-mode` parameter to a value that includes RBAC, -for example: - -``` bash ---authorization-mode=Node,RBAC -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'Node,RBAC' has 'RBAC' -``` - -#### 1.2.11 Ensure that the admission control plugin `AlwaysAdmit` is not set (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and either remove the `--enable-admission-plugins` parameter, or set it to a -value that does not include `AlwaysAdmit`. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' not have 'AlwaysAdmit' OR '--enable-admission-plugins' is not present -``` - -#### 1.2.14 Ensure that the admission control plugin `ServiceAccount` is set (Scored) - -**Result:** PASS - -**Remediation:** -Follow the documentation and create ServiceAccount objects as per your environment. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and ensure that the `--disable-admission-plugins` parameter is set to a -value that does not include `ServiceAccount`. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' has 'ServiceAccount' OR '--enable-admission-plugins' is not present -``` - -#### 1.2.15 Ensure that the admission control plugin `NamespaceLifecycle` is set (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--disable-admission-plugins` parameter to -ensure it does not include `NamespaceLifecycle`. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--disable-admission-plugins' is present OR '--disable-admission-plugins' is not present -``` - -#### 1.2.16 Ensure that the admission control plugin `PodSecurityPolicy` is set (Scored) - -**Result:** PASS - -**Remediation:** -Follow the documentation and create Pod Security Policy objects as per your environment. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--enable-admission-plugins` parameter to a -value that includes `PodSecurityPolicy`: - -``` bash ---enable-admission-plugins=...,PodSecurityPolicy,... -``` - -Then restart the API Server. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' has 'PodSecurityPolicy' -``` - -#### 1.2.17 Ensure that the admission control plugin `NodeRestriction` is set (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and configure `NodeRestriction` plug-in on kubelets. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--enable-admission-plugins` parameter to a -value that includes `NodeRestriction`. - -``` bash ---enable-admission-plugins=...,NodeRestriction,... -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' has 'NodeRestriction' -``` - -#### 1.2.18 Ensure that the `--insecure-bind-address` argument is not set (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and remove the `--insecure-bind-address` parameter. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--insecure-bind-address' is not present -``` - -#### 1.2.19 Ensure that the `--insecure-port` argument is set to `0` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the below parameter. - -``` bash ---insecure-port=0 -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'0' is equal to '0' -``` - -#### 1.2.20 Ensure that the `--secure-port` argument is not set to `0` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and either remove the `--secure-port` parameter or -set it to a different **(non-zero)** desired port. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -6443 is greater than 0 OR '--secure-port' is not present -``` - -#### 1.2.21 Ensure that the `--profiling` argument is set to `false` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the below parameter. - -``` bash ---profiling=false -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'false' is equal to 'false' -``` - -#### 1.2.22 Ensure that the `--audit-log-path` argument is set (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--audit-log-path` parameter to a suitable path and -file where you would like audit logs to be written, for example: - -``` bash ---audit-log-path=/var/log/apiserver/audit.log -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--audit-log-path' is present -``` - -#### 1.2.23 Ensure that the `--audit-log-maxage` argument is set to `30` or as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--audit-log-maxage` parameter to `30` or as an appropriate number of days: - -``` bash ---audit-log-maxage=30 -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -30 is greater or equal to 30 -``` - -#### 1.2.24 Ensure that the `--audit-log-maxbackup` argument is set to `10` or as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--audit-log-maxbackup` parameter to `10` or to an appropriate -value. - -``` bash ---audit-log-maxbackup=10 -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -10 is greater or equal to 10 -``` - -#### 1.2.25 Ensure that the `--audit-log-maxsize` argument is set to `100` or as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--audit-log-maxsize` parameter to an appropriate size in **MB**. -For example, to set it as `100` **MB**: - -``` bash ---audit-log-maxsize=100 -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -100 is greater or equal to 100 -``` - -#### 1.2.26 Ensure that the `--request-timeout` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -and set the below parameter as appropriate and if needed. -For example, - -``` bash ---request-timeout=300s -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--request-timeout' is not present OR '--request-timeout' is present -``` - -#### 1.2.27 Ensure that the `--service-account-lookup` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the below parameter. - -``` bash ---service-account-lookup=true -``` - -Alternatively, you can delete the `--service-account-lookup` parameter from this file so -that the default takes effect. - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--service-account-lookup' is not present OR 'true' is equal to 'true' -``` - -#### 1.2.28 Ensure that the `--service-account-key-file` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--service-account-key-file` parameter -to the public key file for service accounts: - -``` bash ---service-account-key-file= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--service-account-key-file' is present -``` - -#### 1.2.29 Ensure that the `--etcd-certfile` and `--etcd-keyfile` arguments are set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the **etcd** certificate and **key** file parameters. - -``` bash ---etcd-certfile= ---etcd-keyfile= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--etcd-certfile' is present AND '--etcd-keyfile' is present -``` - -#### 1.2.30 Ensure that the `--tls-cert-file` and `--tls-private-key-file` arguments are set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and set up the TLS connection on the apiserver. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the TLS certificate and private key file parameters. - -``` bash ---tls-cert-file= ---tls-private-key-file= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--tls-cert-file' is present AND '--tls-private-key-file' is present -``` - -#### 1.2.31 Ensure that the `--client-ca-file` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and set up the TLS connection on the apiserver. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the client certificate authority file. - -``` bash ---client-ca-file= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--client-ca-file' is present -``` - -#### 1.2.32 Ensure that the `--etcd-cafile` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the etcd certificate authority file parameter. - -``` bash ---etcd-cafile= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--etcd-cafile' is present -``` - -#### 1.2.33 Ensure that the `--encryption-provider-config` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and configure a EncryptionConfig file. -Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` -on the master node and set the `--encryption-provider-config` parameter to the path of that file: - -``` bash ---encryption-provider-config= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-apiserver | grep -v grep -``` - -**Expected result**: - -``` -'--encryption-provider-config' is present -``` - -#### 1.2.34 Ensure that encryption providers are appropriately configured (Scored) - -**Result:** PASS - -**Remediation:** -Follow the Kubernetes documentation and configure a `EncryptionConfig` file. -In this file, choose **aescbc**, **kms** or **secretbox** as the encryption provider. - -**Audit Script:** 1.2.34.sh - -``` -#!/bin/bash -e - -check_file=${1} - -grep -q -E 'aescbc|kms|secretbox' ${check_file} -if [ $? -eq 0 ]; then - echo "--pass" - exit 0 -else - echo "fail: encryption provider found in ${check_file}" - exit 1 -fi -``` - -**Audit Execution:** - -``` -./1.2.34.sh /etc/kubernetes/ssl/encryption.yaml -``` - -**Expected result**: - -``` -'--pass' is present -``` - -### 1.3 Controller Manager - -#### 1.3.1 Ensure that the `--terminated-pod-gc-threshold` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node and set the `--terminated-pod-gc-threshold` to an appropriate threshold, -for example: - -``` bash ---terminated-pod-gc-threshold=10 -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'--terminated-pod-gc-threshold' is present -``` - -#### 1.3.2 Ensure that the `--profiling` argument is set to false (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node and set the below parameter. - -``` bash ---profiling=false -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'false' is equal to 'false' -``` - -#### 1.3.3 Ensure that the `--use-service-account-credentials` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node to set the below parameter. - -``` bash ---use-service-account-credentials=true -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'true' is not equal to 'false' -``` - -#### 1.3.4 Ensure that the `--service-account-private-key-file` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node and set the `--service-account-private-key-file` parameter -to the private key file for service accounts. - -``` bash ---service-account-private-key-file= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'--service-account-private-key-file' is present -``` - -#### 1.3.5 Ensure that the `--root-ca-file` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node and set the `--root-ca-file` parameter to the certificate bundle file`. - -``` bash ---root-ca-file= -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'--root-ca-file' is present -``` - -#### 1.3.6 Ensure that the `RotateKubeletServerCertificate` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node and set the `--feature-gates` parameter to include `RotateKubeletServerCertificate=true`. - -``` bash ---feature-gates=RotateKubeletServerCertificate=true -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'RotateKubeletServerCertificate=true' is equal to 'RotateKubeletServerCertificate=true' -``` - -#### 1.3.7 Ensure that the `--bind-address argument` is set to `127.0.0.1` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` -on the master node and ensure the correct value for the `--bind-address` parameter. - -**Audit:** - -``` -/bin/ps -ef | grep kube-controller-manager | grep -v grep -``` - -**Expected result**: - -``` -'--bind-address' is present OR '--bind-address' is not present -``` - -### 1.4 Scheduler - -#### 1.4.1 Ensure that the `--profiling` argument is set to `false` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Scheduler pod specification file `/etc/kubernetes/manifests/kube-scheduler.yaml` file -on the master node and set the below parameter. - -``` bash ---profiling=false -``` - -**Audit:** - -``` -/bin/ps -ef | grep kube-scheduler | grep -v grep -``` - -**Expected result**: - -``` -'false' is equal to 'false' -``` - -#### 1.4.2 Ensure that the `--bind-address` argument is set to `127.0.0.1` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the Scheduler pod specification file `/etc/kubernetes/manifests/kube-scheduler.yaml` -on the master node and ensure the correct value for the `--bind-address` parameter. - -**Audit:** - -``` -/bin/ps -ef | grep kube-scheduler | grep -v grep -``` - -**Expected result**: - -``` -'--bind-address' is present OR '--bind-address' is not present -``` - -## 2 Etcd Node Configuration -### 2 Etcd Node Configuration Files - -#### 2.1 Ensure that the `--cert-file` and `--key-file` arguments are set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the etcd service documentation and configure TLS encryption. -Then, edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` -on the master node and set the below parameters. - -``` bash ---cert-file= ---key-file= -``` - -**Audit:** - -``` -/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep -``` - -**Expected result**: - -``` -'--cert-file' is present AND '--key-file' is present -``` - -#### 2.2 Ensure that the `--client-cert-auth` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master -node and set the below parameter. - -``` bash ---client-cert-auth="true" -``` - -**Audit:** - -``` -/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep -``` - -**Expected result**: - -``` -'true' is equal to 'true' -``` - -#### 2.3 Ensure that the `--auto-tls` argument is not set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master -node and either remove the `--auto-tls` parameter or set it to `false`. - -``` bash - --auto-tls=false -``` - -**Audit:** - -``` -/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep -``` - -**Expected result**: - -``` -'--auto-tls' is not present OR '--auto-tls' is not present -``` - -#### 2.4 Ensure that the `--peer-cert-file` and `--peer-key-file` arguments are set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -Follow the etcd service documentation and configure peer TLS encryption as appropriate -for your etcd cluster. Then, edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the -master node and set the below parameters. - -``` bash ---peer-client-file= ---peer-key-file= -``` - -**Audit:** - -``` -/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep -``` - -**Expected result**: - -``` -'--peer-cert-file' is present AND '--peer-key-file' is present -``` - -#### 2.5 Ensure that the `--peer-client-cert-auth` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master -node and set the below parameter. - -``` bash ---peer-client-cert-auth=true -``` - -**Audit:** - -``` -/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep -``` - -**Expected result**: - -``` -'true' is equal to 'true' -``` - -#### 2.6 Ensure that the `--peer-auto-tls` argument is not set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master -node and either remove the `--peer-auto-tls` parameter or set it to `false`. - -``` bash ---peer-auto-tls=false -``` - -**Audit:** - -``` -/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep -``` - -**Expected result**: - -``` -'--peer-auto-tls' is not present OR '--peer-auto-tls' is present -``` - -## 3 Control Plane Configuration -### 3.2 Logging - -#### 3.2.1 Ensure that a minimal audit policy is created (Scored) - -**Result:** PASS - -**Remediation:** -Create an audit policy file for your cluster. - -**Audit Script:** 3.2.1.sh - -``` -#!/bin/bash -e - -api_server_bin=${1} - -/bin/ps -ef | /bin/grep ${api_server_bin} | /bin/grep -v ${0} | /bin/grep -v grep -``` - -**Audit Execution:** - -``` -./3.2.1.sh kube-apiserver -``` - -**Expected result**: - -``` -'--audit-policy-file' is present -``` - -## 4 Worker Node Security Configuration -### 4.1 Worker Node Configuration Files - -#### 4.1.1 Ensure that the kubelet service file permissions are set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. - -#### 4.1.2 Ensure that the kubelet service file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. - -#### 4.1.3 Ensure that the proxy kubeconfig file permissions are set to `644` or more restrictive (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the each worker node. -For example, - -``` bash -chmod 644 /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml -``` - -**Audit:** - -``` -/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; then stat -c %a /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; fi' -``` - -**Expected result**: - -``` -'644' is present OR '640' is present OR '600' is equal to '600' OR '444' is present OR '440' is present OR '400' is present OR '000' is present -``` - -#### 4.1.4 Ensure that the proxy kubeconfig file ownership is set to `root:root` (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the each worker node. -For example, - -``` bash -chown root:root /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml -``` - -**Audit:** - -``` -/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; then stat -c %U:%G /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; fi' -``` - -**Expected result**: - -``` -'root:root' is present -``` - -#### 4.1.5 Ensure that the kubelet.conf file permissions are set to `644` or more restrictive (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the each worker node. -For example, - -``` bash -chmod 644 /etc/kubernetes/ssl/kubecfg-kube-node.yaml -``` - -**Audit:** - -``` -/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-node.yaml; then stat -c %a /etc/kubernetes/ssl/kubecfg-kube-node.yaml; fi' -``` - -**Expected result**: - -``` -'644' is present OR '640' is present OR '600' is equal to '600' OR '444' is present OR '440' is present OR '400' is present OR '000' is present -``` - -#### 4.1.6 Ensure that the kubelet.conf file ownership is set to `root:root` (Scored) - -**Result:** PASS - -**Remediation:** -Run the below command (based on the file location on your system) on the each worker node. -For example, - -``` bash -chown root:root /etc/kubernetes/ssl/kubecfg-kube-node.yaml -``` - -**Audit:** - -``` -/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-node.yaml; then stat -c %U:%G /etc/kubernetes/ssl/kubecfg-kube-node.yaml; fi' -``` - -**Expected result**: - -``` -'root:root' is equal to 'root:root' -``` - -#### 4.1.7 Ensure that the certificate authorities file permissions are set to `644` or more restrictive (Scored) - -**Result:** PASS - -**Remediation:** -Run the following command to modify the file permissions of the - -``` bash ---client-ca-file chmod 644 -``` - -**Audit:** - -``` -stat -c %a /etc/kubernetes/ssl/kube-ca.pem -``` - -**Expected result**: - -``` -'644' is equal to '644' OR '640' is present OR '600' is present -``` - -#### 4.1.8 Ensure that the client certificate authorities file ownership is set to `root:root` (Scored) - -**Result:** PASS - -**Remediation:** -Run the following command to modify the ownership of the `--client-ca-file`. - -``` bash -chown root:root -``` - -**Audit:** - -``` -/bin/sh -c 'if test -e /etc/kubernetes/ssl/kube-ca.pem; then stat -c %U:%G /etc/kubernetes/ssl/kube-ca.pem; fi' -``` - -**Expected result**: - -``` -'root:root' is equal to 'root:root' -``` - -#### 4.1.9 Ensure that the kubelet configuration file has permissions set to `644` or more restrictive (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. - -#### 4.1.10 Ensure that the kubelet configuration file ownership is set to `root:root` (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. - -### 4.2 Kubelet - -#### 4.2.1 Ensure that the `--anonymous-auth argument` is set to false (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set authentication: `anonymous`: enabled to -`false`. -If using executable arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. - -``` bash ---anonymous-auth=false -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'false' is equal to 'false' -``` - -#### 4.2.2 Ensure that the `--authorization-mode` argument is not set to `AlwaysAllow` (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set authorization: `mode` to `Webhook`. If -using executable arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -set the below parameter in `KUBELET_AUTHZ_ARGS` variable. - -``` bash ---authorization-mode=Webhook -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'Webhook' not have 'AlwaysAllow' -``` - -#### 4.2.3 Ensure that the `--client-ca-file` argument is set as appropriate (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set authentication: `x509`: `clientCAFile` to -the location of the client CA file. -If using command line arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -set the below parameter in `KUBELET_AUTHZ_ARGS` variable. - -``` bash ---client-ca-file= -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'--client-ca-file' is present -``` - -#### 4.2.4 Ensure that the `--read-only-port` argument is set to `0` (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set `readOnlyPort` to `0`. -If using command line arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. - -``` bash ---read-only-port=0 -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'0' is equal to '0' -``` - -#### 4.2.5 Ensure that the `--streaming-connection-idle-timeout` argument is not set to `0` (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set `streamingConnectionIdleTimeout` to a -value other than `0`. -If using command line arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. - -``` bash ---streaming-connection-idle-timeout=5m -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'30m' is not equal to '0' OR '--streaming-connection-idle-timeout' is not present -``` - -#### 4.2.6 Ensure that the ```--protect-kernel-defaults``` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set `protectKernelDefaults`: `true`. -If using command line arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. - -``` bash ---protect-kernel-defaults=true -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'true' is equal to 'true' -``` - -#### 4.2.7 Ensure that the `--make-iptables-util-chains` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to set `makeIPTablesUtilChains`: `true`. -If using command line arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -remove the `--make-iptables-util-chains` argument from the -`KUBELET_SYSTEM_PODS_ARGS` variable. -Based on your system, restart the kubelet service. For example: - -```bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'true' is equal to 'true' OR '--make-iptables-util-chains' is not present -``` - -#### 4.2.10 Ensure that the `--tls-cert-file` and `--tls-private-key-file` arguments are set as appropriate (Scored) - -**Result:** Not Applicable - -**Remediation:** -RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. - -#### 4.2.11 Ensure that the `--rotate-certificates` argument is not set to `false` (Scored) - -**Result:** PASS - -**Remediation:** -If using a Kubelet config file, edit the file to add the line `rotateCertificates`: `true` or -remove it altogether to use the default value. -If using command line arguments, edit the kubelet service file -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and -remove `--rotate-certificates=false` argument from the `KUBELET_CERTIFICATE_ARGS` -variable. -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'--rotate-certificates' is present OR '--rotate-certificates' is not present -``` - -#### 4.2.12 Ensure that the `RotateKubeletServerCertificate` argument is set to `true` (Scored) - -**Result:** PASS - -**Remediation:** -Edit the kubelet service file `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` -on each worker node and set the below parameter in `KUBELET_CERTIFICATE_ARGS` variable. - -``` bash ---feature-gates=RotateKubeletServerCertificate=true -``` - -Based on your system, restart the kubelet service. For example: - -``` bash -systemctl daemon-reload -systemctl restart kubelet.service -``` - -**Audit:** - -``` -/bin/ps -fC kubelet -``` - -**Audit Config:** - -``` -/bin/cat /var/lib/kubelet/config.yaml -``` - -**Expected result**: - -``` -'true' is equal to 'true' -``` - -## 5 Kubernetes Policies -### 5.1 RBAC and Service Accounts - -#### 5.1.5 Ensure that default service accounts are not actively used. (Scored) - -**Result:** PASS - -**Remediation:** -Create explicit service accounts wherever a Kubernetes workload requires specific access -to the Kubernetes API server. -Modify the configuration of each default service account to include this value - -``` bash -automountServiceAccountToken: false -``` - -**Audit Script:** 5.1.5.sh - -``` -#!/bin/bash - -export KUBECONFIG=${KUBECONFIG:-/root/.kube/config} - -kubectl version > /dev/null -if [ $? -ne 0 ]; then - echo "fail: kubectl failed" - exit 1 -fi - -accounts="$(kubectl --kubeconfig=${KUBECONFIG} get serviceaccounts -A -o json | jq -r '.items[] | select(.metadata.name=="default") | select((.automountServiceAccountToken == null) or (.automountServiceAccountToken == true)) | "fail \(.metadata.name) \(.metadata.namespace)"')" - -if [[ "${accounts}" != "" ]]; then - echo "fail: automountServiceAccountToken not false for accounts: ${accounts}" - exit 1 -fi - -default_binding="$(kubectl get rolebindings,clusterrolebindings -A -o json | jq -r '.items[] | select(.subjects[].kind=="ServiceAccount" and .subjects[].name=="default" and .metadata.name=="default").metadata.uid' | wc -l)" - -if [[ "${default_binding}" -gt 0 ]]; then - echo "fail: default service accounts have non default bindings" - exit 1 -fi - -echo "--pass" -exit 0 -``` - -**Audit Execution:** - -``` -./5.1.5.sh -``` - -**Expected result**: - -``` -'--pass' is present -``` - -### 5.2 Pod Security Policies - -#### 5.2.2 Minimize the admission of containers wishing to share the host process ID namespace (Scored) - -**Result:** PASS - -**Remediation:** -Create a PSP as described in the Kubernetes documentation, ensuring that the -`.spec.hostPID` field is omitted or set to `false`. - -**Audit:** - -``` -kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.hostPID == null) or (.spec.hostPID == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' -``` - -**Expected result**: - -``` -1 is greater than 0 -``` - -#### 5.2.3 Minimize the admission of containers wishing to share the host IPC namespace (Scored) - -**Result:** PASS - -**Remediation:** -Create a PSP as described in the Kubernetes documentation, ensuring that the -`.spec.hostIPC` field is omitted or set to `false`. - -**Audit:** - -``` -kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.hostIPC == null) or (.spec.hostIPC == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' -``` - -**Expected result**: - -``` -1 is greater than 0 -``` - -#### 5.2.4 Minimize the admission of containers wishing to share the host network namespace (Scored) - -**Result:** PASS - -**Remediation:** -Create a PSP as described in the Kubernetes documentation, ensuring that the -`.spec.hostNetwork` field is omitted or set to `false`. - -**Audit:** - -``` -kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.hostNetwork == null) or (.spec.hostNetwork == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' -``` - -**Expected result**: - -``` -1 is greater than 0 -``` - -#### 5.2.5 Minimize the admission of containers with `allowPrivilegeEscalation` (Scored) - -**Result:** PASS - -**Remediation:** -Create a PSP as described in the Kubernetes documentation, ensuring that the -`.spec.allowPrivilegeEscalation` field is omitted or set to `false`. - -**Audit:** - -``` -kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.allowPrivilegeEscalation == null) or (.spec.allowPrivilegeEscalation == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' -``` - -**Expected result**: - -``` -1 is greater than 0 -``` - -### 5.3 Network Policies and CNI - -#### 5.3.2 Ensure that all Namespaces have Network Policies defined (Scored) - -**Result:** PASS - -**Remediation:** -Follow the documentation and create `NetworkPolicy` objects as you need them. - -**Audit Script:** 5.3.2.sh - -``` -#!/bin/bash -e - -export KUBECONFIG=${KUBECONFIG:-"/root/.kube/config"} - -kubectl version > /dev/null -if [ $? -ne 0 ]; then - echo "fail: kubectl failed" - exit 1 -fi - -for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do - policy_count=$(kubectl get networkpolicy -n ${namespace} -o json | jq '.items | length') - if [ ${policy_count} -eq 0 ]; then - echo "fail: ${namespace}" - exit 1 - fi -done - -echo "pass" -``` - -**Audit Execution:** - -``` -./5.3.2.sh -``` - -**Expected result**: - -``` -'pass' is present -``` - -### 5.6 General Policies - -#### 5.6.4 The default namespace should not be used (Scored) - -**Result:** PASS - -**Remediation:** -Ensure that namespaces are created to allow for appropriate segregation of Kubernetes -resources and that all new resources are created in a specific namespace. - -**Audit Script:** 5.6.4.sh - -``` -#!/bin/bash -e - -export KUBECONFIG=${KUBECONFIG:-/root/.kube/config} - -kubectl version > /dev/null -if [[ $? -gt 0 ]]; then - echo "fail: kubectl failed" - exit 1 -fi - -default_resources=$(kubectl get all -o json | jq --compact-output '.items[] | select((.kind == "Service") and (.metadata.name == "kubernetes") and (.metadata.namespace == "default") | not)' | wc -l) - -echo "--count=${default_resources}" -``` - -**Audit Execution:** - -``` -./5.6.4.sh -``` - -**Expected result**: - -``` -'0' is equal to '0' -``` - diff --git a/content/rancher/v2.x/en/security/hardening-2.4/_index.md b/content/rancher/v2.x/en/security/hardening-2.4/_index.md deleted file mode 100644 index d4ddfccc434..00000000000 --- a/content/rancher/v2.x/en/security/hardening-2.4/_index.md +++ /dev/null @@ -1,720 +0,0 @@ ---- -title: Hardening Guide v2.4 -weight: 99 ---- - -This document provides prescriptive guidance for hardening a production installation of Rancher v2.4. It outlines the configurations and controls required to address Kubernetes benchmark controls from the Center for Information Security (CIS). - -> This hardening guide describes how to secure the nodes in your cluster, and it is recommended to follow this guide before installing Kubernetes. - -This hardening guide is intended to be used with specific versions of the CIS Kubernetes Benchmark, Kubernetes, and Rancher: - -Hardening Guide Version | Rancher Version | CIS Benchmark Version | Kubernetes Version -------------------------|----------------|-----------------------|------------------ -Hardening Guide v2.4 | Rancher v2.4 | Benchmark v1.5 | Kubernetes 1.15 - - -[Click here to download a PDF version of this document](https://releases.rancher.com/documents/security/2.4/Rancher_Hardening_Guide.pdf) - -### Overview - -This document provides prescriptive guidance for hardening a production installation of Rancher v2.4 with Kubernetes v1.15. It outlines the configurations required to address Kubernetes benchmark controls from the Center for Information Security (CIS). - -For more detail about evaluating a hardened cluster against the official CIS benchmark, refer to the [CIS Benchmark Rancher Self-Assessment Guide - Rancher v2.4]({{< baseurl >}}/rancher/v2.x/en/security/benchmark-2.4/). - -#### Known Issues - -- Rancher **exec shell** and **view logs** for pods are **not** functional in a CIS 1.5 hardened setup when only public IP is provided when registering custom nodes. This functionality requires a private IP to be provided when registering the custom nodes. -- When setting the `default_pod_security_policy_template_id:` to `restricted` Rancher creates **RoleBindings** and **ClusterRoleBindings** on the default service accounts. The CIS 1.5 5.1.5 check requires the default service accounts have no roles or cluster roles bound to it apart from the defaults. In addition the default service accounts should be configured such that it does not provide a service account token and does not have any explicit rights assignments. - -### Configure Kernel Runtime Parameters - -The following `sysctl` configuration is recommended for all nodes type in the cluster. Set the following parameters in `/etc/sysctl.d/90-kubelet.conf`: - -``` -vm.overcommit_memory=1 -vm.panic_on_oom=0 -kernel.panic=10 -kernel.panic_on_oops=1 -kernel.keys.root_maxbytes=25000000 -``` - -Run `sysctl -p /etc/sysctl.d/90-kubelet.conf` to enable the settings. - -### Configure `etcd` user and group -A user account and group for the **etcd** service is required to be setup prior to installing RKE. The **uid** and **gid** for the **etcd** user will be used in the RKE **config.yml** to set the proper permissions for files and directories during installation time. - -#### create `etcd` user and group -To create the **etcd** group run the following console commands. - -The commands below use `52034` for **uid** and **gid** are for example purposes. Any valid unused **uid** or **gid** could also be used in lieu of `52034`. - -``` -groupadd --gid 52034 etcd -useradd --comment "etcd service account" --uid 52034 --gid 52034 etcd -``` - -Update the RKE **config.yml** with the **uid** and **gid** of the **etcd** user: - -``` yaml -services: - etcd: - gid: 52034 - uid: 52034 -``` - -#### Set `automountServiceAccountToken` to `false` for `default` service accounts -Kubernetes provides a default service account which is used by cluster workloads where no specific service account is assigned to the pod. Where access to the Kubernetes API from a pod is required, a specific service account should be created for that pod, and rights granted to that service account. The default service account should be configured such that it does not provide a service account token and does not have any explicit rights assignments. - -For each namespace including **default** and **kube-system** on a standard RKE install the **default** service account must include this value: - -``` -automountServiceAccountToken: false -``` - -Save the following yaml to a file called `account_update.yaml` - -``` yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: default -automountServiceAccountToken: false -``` - -Create a bash script file called `account_update.sh`. Be sure to `chmod +x account_update.sh` so the script has execute permissions. - -``` -#!/bin/bash -e - -for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do - kubectl patch serviceaccount default -n ${namespace} -p "$(cat account_update.yaml)" -done -``` - -### Ensure that all Namespaces have Network Policies defined - -Running different applications on the same Kubernetes cluster creates a risk of one -compromised application attacking a neighboring application. Network segmentation is -important to ensure that containers can communicate only with those they are supposed -to. A network policy is a specification of how selections of pods are allowed to -communicate with each other and other network endpoints. - -Network Policies are namespace scoped. When a network policy is introduced to a given -namespace, all traffic not allowed by the policy is denied. However, if there are no network -policies in a namespace all traffic will be allowed into and out of the pods in that -namespace. To enforce network policies, a CNI (container network interface) plugin must be enabled. -This guide uses [canal](https://github.com/projectcalico/canal) to provide the policy enforcement. -Additional information about CNI providers can be found -[here](https://rancher.com/blog/2019/2019-03-21-comparing-kubernetes-cni-providers-flannel-calico-canal-and-weave/) - -Once a CNI provider is enabled on a cluster a default network policy can be applied. For reference purposes a -**permissive** example is provide below. If you want to allow all traffic to all pods in a namespace -(even if policies are added that cause some pods to be treated as “isolated”), -you can create a policy that explicitly allows all traffic in that namespace. Save the following `yaml` as -`default-allow-all.yaml`. Additional [documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/) -about network policies can be found on the Kubernetes site. - -> This `NetworkPolicy` is not recommended for production use - -``` yaml ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default-allow-all -spec: - podSelector: {} - ingress: - - {} - egress: - - {} - policyTypes: - - Ingress - - Egress -``` - -Create a bash script file called `apply_networkPolicy_to_all_ns.sh`. Be sure to -`chmod +x apply_networkPolicy_to_all_ns.sh` so the script has execute permissions. - -``` -#!/bin/bash -e - -for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do - kubectl apply -f default-allow-all.yaml -n ${namespace} -done -``` -Execute this script to apply the `default-allow-all.yaml` the **permissive** `NetworkPolicy` to all namespaces. - -### Reference Hardened RKE `cluster.yml` configuration -The reference `cluster.yml` is used by the RKE CLI that provides the configuration needed to achieve a hardened install -of Rancher Kubernetes Engine (RKE). Install [documentation](https://rancher.com/docs/rke/latest/en/installation/) is -provided with additional details about the configuration items. This reference `cluster.yml` does not include the required **nodes** directive which will vary depending on your environment. Documentation for node configuration can be found here: https://rancher.com/docs/rke/latest/en/config-options/nodes - - -``` yaml -# If you intend to deploy Kubernetes in an air-gapped environment, -# please consult the documentation on how to configure custom RKE images. -kubernetes_version: "v1.15.9-rancher1-1" -enable_network_policy: true -default_pod_security_policy_template_id: "restricted" -# the nodes directive is required and will vary depending on your environment -# documentation for node configuration can be found here: -# https://rancher.com/docs/rke/latest/en/config-options/nodes -nodes: -services: - etcd: - uid: 52034 - gid: 52034 - kube-api: - pod_security_policy: true - secrets_encryption_config: - enabled: true - audit_log: - enabled: true - admission_configuration: - event_rate_limit: - enabled: true - kube-controller: - extra_args: - feature-gates: "RotateKubeletServerCertificate=true" - scheduler: - image: "" - extra_args: {} - extra_binds: [] - extra_env: [] - kubelet: - generate_serving_certificate: true - extra_args: - feature-gates: "RotateKubeletServerCertificate=true" - protect-kernel-defaults: "true" - tls-cipher-suites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256" - extra_binds: [] - extra_env: [] - cluster_domain: "" - infra_container_image: "" - cluster_dns_server: "" - fail_swap_on: false - kubeproxy: - image: "" - extra_args: {} - extra_binds: [] - extra_env: [] -network: - plugin: "" - options: {} - mtu: 0 - node_selector: {} -authentication: - strategy: "" - sans: [] - webhook: null -addons: | - --- - apiVersion: v1 - kind: Namespace - metadata: - name: ingress-nginx - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: Role - metadata: - name: default-psp-role - namespace: ingress-nginx - rules: - - apiGroups: - - extensions - resourceNames: - - default-psp - resources: - - podsecuritypolicies - verbs: - - use - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: RoleBinding - metadata: - name: default-psp-rolebinding - namespace: ingress-nginx - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: default-psp-role - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:serviceaccounts - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated - --- - apiVersion: v1 - kind: Namespace - metadata: - name: cattle-system - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: Role - metadata: - name: default-psp-role - namespace: cattle-system - rules: - - apiGroups: - - extensions - resourceNames: - - default-psp - resources: - - podsecuritypolicies - verbs: - - use - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: RoleBinding - metadata: - name: default-psp-rolebinding - namespace: cattle-system - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: default-psp-role - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:serviceaccounts - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated - --- - apiVersion: policy/v1beta1 - kind: PodSecurityPolicy - metadata: - name: restricted - spec: - requiredDropCapabilities: - - NET_RAW - privileged: false - allowPrivilegeEscalation: false - defaultAllowPrivilegeEscalation: false - fsGroup: - rule: RunAsAny - runAsUser: - rule: MustRunAsNonRoot - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - volumes: - - emptyDir - - secret - - persistentVolumeClaim - - downwardAPI - - configMap - - projected - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: psp:restricted - rules: - - apiGroups: - - extensions - resourceNames: - - restricted - resources: - - podsecuritypolicies - verbs: - - use - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: psp:restricted - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: psp:restricted - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:serviceaccounts - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated - --- - apiVersion: v1 - kind: ServiceAccount - metadata: - name: tiller - namespace: kube-system - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: tiller - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin - subjects: - - kind: ServiceAccount - name: tiller - namespace: kube-system - -addons_include: [] -system_images: - etcd: "" - alpine: "" - nginx_proxy: "" - cert_downloader: "" - kubernetes_services_sidecar: "" - kubedns: "" - dnsmasq: "" - kubedns_sidecar: "" - kubedns_autoscaler: "" - coredns: "" - coredns_autoscaler: "" - kubernetes: "" - flannel: "" - flannel_cni: "" - calico_node: "" - calico_cni: "" - calico_controllers: "" - calico_ctl: "" - calico_flexvol: "" - canal_node: "" - canal_cni: "" - canal_flannel: "" - canal_flexvol: "" - weave_node: "" - weave_cni: "" - pod_infra_container: "" - ingress: "" - ingress_backend: "" - metrics_server: "" - windows_pod_infra_container: "" -ssh_key_path: "" -ssh_cert_path: "" -ssh_agent_auth: false -authorization: - mode: "" - options: {} -ignore_docker_version: false -private_registries: [] -ingress: - provider: "" - options: {} - node_selector: {} - extra_args: {} - dns_policy: "" - extra_envs: [] - extra_volumes: [] - extra_volume_mounts: [] -cluster_name: "" -prefix_path: "" -addon_job_timeout: 0 -bastion_host: - address: "" - port: "" - user: "" - ssh_key: "" - ssh_key_path: "" - ssh_cert: "" - ssh_cert_path: "" -monitoring: - provider: "" - options: {} - node_selector: {} -restore: - restore: false - snapshot_name: "" -dns: null -``` - -### Reference Hardened RKE Template configuration - -The reference RKE Template provides the configuration needed to achieve a hardened install of Kubenetes. -RKE Templates are used to provision Kubernetes and define Rancher settings. Follow the Rancher -[documentaion](https://rancher.com/docs/rancher/v2.x/en/installation) for additional installation and RKE Template details. - -``` yaml -# -# Cluster Config -# -default_pod_security_policy_template_id: restricted -docker_root_dir: /var/lib/docker -enable_cluster_alerting: false -enable_cluster_monitoring: false -enable_network_policy: true -# -# Rancher Config -# -rancher_kubernetes_engine_config: - addon_job_timeout: 30 - addons: |- - --- - apiVersion: v1 - kind: Namespace - metadata: - name: ingress-nginx - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: Role - metadata: - name: default-psp-role - namespace: ingress-nginx - rules: - - apiGroups: - - extensions - resourceNames: - - default-psp - resources: - - podsecuritypolicies - verbs: - - use - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: RoleBinding - metadata: - name: default-psp-rolebinding - namespace: ingress-nginx - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: default-psp-role - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:serviceaccounts - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated - --- - apiVersion: v1 - kind: Namespace - metadata: - name: cattle-system - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: Role - metadata: - name: default-psp-role - namespace: cattle-system - rules: - - apiGroups: - - extensions - resourceNames: - - default-psp - resources: - - podsecuritypolicies - verbs: - - use - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: RoleBinding - metadata: - name: default-psp-rolebinding - namespace: cattle-system - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: default-psp-role - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:serviceaccounts - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated - --- - apiVersion: policy/v1beta1 - kind: PodSecurityPolicy - metadata: - name: restricted - spec: - requiredDropCapabilities: - - NET_RAW - privileged: false - allowPrivilegeEscalation: false - defaultAllowPrivilegeEscalation: false - fsGroup: - rule: RunAsAny - runAsUser: - rule: MustRunAsNonRoot - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - volumes: - - emptyDir - - secret - - persistentVolumeClaim - - downwardAPI - - configMap - - projected - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: psp:restricted - rules: - - apiGroups: - - extensions - resourceNames: - - restricted - resources: - - podsecuritypolicies - verbs: - - use - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: psp:restricted - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: psp:restricted - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:serviceaccounts - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated - --- - apiVersion: v1 - kind: ServiceAccount - metadata: - name: tiller - namespace: kube-system - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: tiller - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin - subjects: - - kind: ServiceAccount - name: tiller - namespace: kube-system - ignore_docker_version: true - kubernetes_version: v1.15.9-rancher1-1 -# -# If you are using calico on AWS -# -# network: -# plugin: calico -# calico_network_provider: -# cloud_provider: aws -# -# # To specify flannel interface -# -# network: -# plugin: flannel -# flannel_network_provider: -# iface: eth1 -# -# # To specify flannel interface for canal plugin -# -# network: -# plugin: canal -# canal_network_provider: -# iface: eth1 -# - network: - mtu: 0 - plugin: canal -# -# services: -# kube-api: -# service_cluster_ip_range: 10.43.0.0/16 -# kube-controller: -# cluster_cidr: 10.42.0.0/16 -# service_cluster_ip_range: 10.43.0.0/16 -# kubelet: -# cluster_domain: cluster.local -# cluster_dns_server: 10.43.0.10 -# - services: - etcd: - backup_config: - enabled: false - interval_hours: 12 - retention: 6 - safe_timestamp: false - creation: 12h - extra_args: - election-timeout: '5000' - heartbeat-interval: '500' - gid: 52034 - retention: 72h - snapshot: false - uid: 52034 - kube_api: - always_pull_images: false - audit_log: - enabled: true - event_rate_limit: - enabled: true - pod_security_policy: true - secrets_encryption_config: - enabled: true - service_node_port_range: 30000-32767 - kube_controller: - extra_args: - address: 127.0.0.1 - feature-gates: RotateKubeletServerCertificate=true - profiling: 'false' - terminated-pod-gc-threshold: '1000' - kubelet: - extra_args: - anonymous-auth: 'false' - event-qps: '0' - feature-gates: RotateKubeletServerCertificate=true - make-iptables-util-chains: 'true' - protect-kernel-defaults: 'true' - streaming-connection-idle-timeout: 1800s - tls-cipher-suites: >- - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256 - fail_swap_on: false - generate_serving_certificate: true - scheduler: - extra_args: - address: 127.0.0.1 - profiling: 'false' - ssh_agent_auth: false -windows_prefered_cluster: false -``` - -### Hardened Reference Ubuntu 18.04 LTS **cloud-config**: - -The reference **cloud-config** is generally used in cloud infrastructure environments to allow for -configuration management of compute instances. The reference config configures Ubuntu operating system level settings -needed before installing kubernetes. - -``` yaml -#cloud-config -packages: - - curl - - jq -runcmd: - - sysctl -w vm.overcommit_memory=1 - - sysctl -w kernel.panic=10 - - sysctl -w kernel.panic_on_oops=1 - - curl https://releases.rancher.com/install-docker/18.09.sh | sh - - usermod -aG docker ubuntu - - return=1; while [ $return != 0 ]; do sleep 2; docker ps; return=$?; done - - addgroup --gid 52034 etcd - - useradd --comment "etcd service account" --uid 52034 --gid 52034 etcd -write_files: - - path: /etc/sysctl.d/kubelet.conf - owner: root:root - permissions: "0644" - content: | - vm.overcommit_memory=1 - kernel.panic=10 - kernel.panic_on_oops=1 -``` From a19101ab62a77ad5367062a48c0947ce417f21f2 Mon Sep 17 00:00:00 2001 From: cluse Date: Mon, 9 Nov 2020 14:47:45 -0700 Subject: [PATCH 36/58] Document K3s resource profiling --- .../installation-requirements/_index.md | 2 + .../resource-profiling/_index.md | 139 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 content/k3s/latest/en/installation/installation-requirements/resource-profiling/_index.md diff --git a/content/k3s/latest/en/installation/installation-requirements/_index.md b/content/k3s/latest/en/installation/installation-requirements/_index.md index c8c330d6d7d..f4f416c9efd 100644 --- a/content/k3s/latest/en/installation/installation-requirements/_index.md +++ b/content/k3s/latest/en/installation/installation-requirements/_index.md @@ -36,6 +36,8 @@ Hardware requirements scale based on the size of your deployments. Minimum recom * RAM: 512MB Minimum (we recommend at least 1GB) * CPU: 1 Minimum +[This section](./resource-profiling) captures the results of tests to determine minimum resource requirements for the K3s agent, the K3s server with a workload, and the K3s server with one agent. It also contains analysis about what has the biggest impact on K3s server and agent utilization, and how the cluster datastore can be protected from interference from agents and workloads. + #### Disks K3s performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC. diff --git a/content/k3s/latest/en/installation/installation-requirements/resource-profiling/_index.md b/content/k3s/latest/en/installation/installation-requirements/resource-profiling/_index.md new file mode 100644 index 00000000000..53866c533c8 --- /dev/null +++ b/content/k3s/latest/en/installation/installation-requirements/resource-profiling/_index.md @@ -0,0 +1,139 @@ +--- +title: K3s Resource Profiling +shortTitle: Resource Profiling +weight: 1 +--- + +This section captures the results of tests to determine minimum resource requirements for K3s. + +The results are summarized as follows: + +| Components | Processor | Min CPU | Min RAM with Kine/SQLite | Min RAM with Embedded etcd | +|------------|-----|----------|-------------------------|---------------------------| +| K3s server with a workload | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | 10% of a core | 768 M | 896 M | +| K3s cluster with a single agent | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | 10% of a core | 512 M | 768 M | +| K3s agent | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | 5% of a core | 256 M | 256 M | +| K3s server with a workload | Pi4B BCM2711, 1.50 GHz | 20% of a core | 768 M | 896 M | +| K3s cluster with a single agent | Pi4B BCM2711, 1.50 GHz | 20% of a core | 512 M | 768 M | +| K3s agent | Pi4B BCM2711, 1.50 GHz | 10% of a core | 256 M | 256 M | + +- [Scope of Resource Testing](#scope-of-resource-testing) +- [Components Included for Baseline Measurements](#components-included-for-baseline-measurements) +- [Methodology](#methodology) +- [Environment](#environment) +- [Baseline Resource Requirements](#baseline-resource-requirements) + - [K3s Server with a Workload](#k3s-server-with-a-workload) + - [K3s Cluster with a Single Agent](#k3s-cluster-with-a-single-agent) + - [K3s Agent](#k3s-agent) +- [Analysis](#analysis) + - [Primary Resource Utilization Drivers](#primary-resource-utilization-drivers) + - [Preventing Agents and Workloads from Interfering with the Cluster Datastore](#preventing-agents-and-workloads-from-interfering-with-the-cluster-datastore) + +# Scope of Resource Testing + +The resource tests were intended to address the following problem statements: + +- On a single-node cluster, determine the legitimate minimum amount of CPU, memory, and IOPs that should be set aside to run the entire K3s stack server stack, assuming that a real workload will be deployed on the cluster. +- On an agent (worker) node, determine the legitimate minimum amount of CPU, memory, and IOPs that should be set aside for the Kubernetes and K3s control plane components (the kubelet and k3s agent). + +# Components Included for Baseline Measurements + +The tested components are: + +* K3s 1.19.2 with all packaged components enabled +* Prometheus + Grafana monitoring stack +* Kubernetes Example PHP Guestbook app + +These are baseline figures for a stable system using only K3s packaged components (Traefik Ingress, Klipper lb, local-path storage) running a standard monitoring stack (Prometheus and Grafana) and the Guestbook example app. + +Resource figures including IOPS are for the Kubernetes datastore and control plane only, and do not include overhead for system-level management agents or logging, container image management, or any workload-specific requirements. + +# Methodology + +A standalone instance of Prometheus v2.21.0 was used to collect host CPU, memory, and disk IO statistics using `prometheus-node-exporter` installed via apt. + +`systemd-cgtop` was used to spot-check systemd cgroup-level CPU and memory utilization. `system.slice/k3s.service` tracks resource utilization for both K3s and containerd, while individual pods are under the `kubepods` hierarchy. + +Additional detailed K3s memory utilization data was collected from the `process_resident_memory_bytes` and `go_memstats_alloc_bytes` metrics using the kubelet exporter integrated into the server and agent processes. + +Utilization figures were based on 95th percentile readings from steady state operation on nodes running the described workloads. + +# Environment + +OS: Ubuntu 20.04 x86_64, aarch64 + +Hardware: + +- AWS c5d.xlarge - 4 core, 8 GB RAM, NVME SSD +- Raspberry Pi 4 Model B - 4 core, 8 GB RAM, Class 10 SDHC + +# Baseline Resource Requirements + +This section captures the results of tests to determine minimum resource requirements for the K3s agent, the K3s server with a workload, and the K3s server with one agent. + +### K3s Server with a Workload + +These are the requirements for a single-node cluster in which the K3s server shares resources with a workload. + +The CPU requirements are: + +| Resource Requirement | Tested Processor | +|-----------|-----------------| +| 10% of a core | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | +| 20% of a core | Low-power processor such as Pi4B BCM2711, 1.50 GHz | + +The IOPS and memory requirements are: + +| Tested Datastore | IOPS | KiB/sec | Latency | RAM | +|-----------|------|---------|---------|--------| +| Kine/SQLite | 10 | 500 | < 10 ms | 768 M | +| Embedded etcd | 50 | 250 | < 5 ms | 896 M | + +### K3s Cluster with a Single Agent + +These are the baseline requirements for a K3s cluster with a K3s server node and a K3s agent, but no workload. + +The CPU requirements are: + +| Resource Requirement | Tested Processor | +|-----------|-----------------| +| 10% of a core | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | +| 20% of a core | Pi4B BCM2711, 1.50 GHz | + +The IOPS and memory requirements are: + +| Datastore | IOPS | KiB/sec | Latency | RAM | +|-----------|------|---------|---------|--------| +| Kine/SQLite | 10 | 500 | < 10 ms | 512 M | +| Embedded etcd | 50 | 250 | < 5 ms | 768 M | + +### K3s Agent + +The CPU requirements are: + + Resource Requirement | Tested Processor | +|-----------|-----------------| +| 5% of a core | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | +| 10% of a core | Pi4B BCM2711, 1.50 GHz | + +256 M of RAM is required. + +# Analysis + +This section captures what has the biggest impact on K3s server and agent utilization, and how the cluster datastore can be protected from interference from agents and workloads. + +### Primary Resource Utilization Drivers + +K3s server utilization figures are primarily driven by support of the Kubernetes datastore (kine or etcd), API Server, Controller-Manager, and Scheduler control loops, as well as any management tasks necessary to effect changes to the state of the system. Operations that place additional load on the Kubernetes control plane, such as creating/modifying/deleting resources, will cause temporary spikes in utilization. Using operators or apps that make extensive use of the Kubernetes datastore (such as Rancher or other Operator-type applications) will increase the server's resource requirements. Scaling up the cluster by adding additional nodes or creating many cluster resources will increase the server's resource requirements. + +K3s agent utilization figures are primarily driven by support of container lifecycle management control loops. Operations that involve managing images, provisioning storage, or creating/destroying containers will cause temporary spikes in utilization. Image pulls in particular are typically highly CPU and IO bound, as they involve decompressing image content to disk. If possible, workload storage (pod ephemeral storage and volumes) should be isolated from the agent components (/var/lib/rancher/k3s/agent) to ensure that there are no resource conflicts. + +### Preventing Agents and Workloads from Interfering with the Cluster Datastore + +When running in an environment where the server is also hosting workload pods, care should be taken to ensure that agent and workload IOPS do not interfere with the datastore. + +This can be best accomplished by placing the server components (/var/lib/rancher/k3s/server) on a different storage medium than the agent components (/var/lib/rancher/k3s/agent), which include the containerd image store. + +Workload storage (pod ephemeral storage and volumes) should also be isolated from the datastore. + +Failure to meet datastore throughput and latency requirements may result in delayed response from the control plane and/or failure of the control plane to maintain system state. \ No newline at end of file From f1285a9dd16af66775f191e73e4a24632a053ed9 Mon Sep 17 00:00:00 2001 From: cluse Date: Wed, 18 Nov 2020 14:23:03 -0700 Subject: [PATCH 37/58] Say that apps should be managed by either Cluster Manager or Cluster Explorer, not both --- .../v2.x/en/helm-charts/apps-marketplace/_index.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/content/rancher/v2.x/en/helm-charts/apps-marketplace/_index.md b/content/rancher/v2.x/en/helm-charts/apps-marketplace/_index.md index 183a775ad14..f2bc4b50a70 100644 --- a/content/rancher/v2.x/en/helm-charts/apps-marketplace/_index.md +++ b/content/rancher/v2.x/en/helm-charts/apps-marketplace/_index.md @@ -20,7 +20,9 @@ The charts page contains all Rancher, Partner, and Custom Charts. * Partner charts reside under the Partners label * Custom charts will show up under the name of the repository -All three types are deployed and managed in the same way. +All three types are deployed and managed in the same way. + +> Apps managed by the Cluster Manager should continue to be managed only by the Cluster Manager, and apps managed with the Cluster Explorer must be managed only by the Cluster Explorer. ### Repositories @@ -29,17 +31,17 @@ From the left sidebar select _"Repositories"_. These items represent helm repositories, and can be either traditional helm endpoints which have an index.yaml, or git repositories which will be cloned and can point to a specific branch. In order to use custom charts, simply add your repository here and they will become available in the Charts tab under the name of the repository. -### Helm compatilbitiy +### Helm Compatibility The Cluster Explorer only supports Helm 3 compatible charts. ### Deployment and Upgrades -From the _"Charts"_ tab select a Chart to install. Rancher and Partner charts may have extra configurations available through custom pages or questions.yaml files, but all chart installations can modify the values.yaml and other basic settings. Once you click install, a helm operation job is deployed, and the console for the job is displayed. +From the _"Charts"_ tab select a Chart to install. Rancher and Partner charts may have extra configurations available through custom pages or questions.yaml files, but all chart installations can modify the values.yaml and other basic settings. Once you click install, a Helm operation job is deployed, and the console for the job is displayed. To view all recent changes, go to the _"Recent Operations"_ tab. From there you can view the call that was made, conditions, events, and logs. -After installing a chart, you can find it in the _"Installed Apps"_ tab. In this section you can upgrade or delete the installation, and see further details. When choosing to upgrade, the form and values presented will be the same as installation. +After installing a chart, you can find it in the _"Installed Apps"_ tab. In this section you can upgrade or delete the installation, and see further details. When choosing to upgrade, the form and values presented will be the same as installation. Most Rancher tools have additional pages located in the toolbar below the _"Apps & Marketplace"_ section to help manage and use the features. These pages include links to dashboards, forms to easily add Custom Resources, and additional information. From c6e779ff25e4d63c1bac86dd76665e4c5c6b8b7c Mon Sep 17 00:00:00 2001 From: cluse Date: Wed, 18 Nov 2020 17:21:41 -0700 Subject: [PATCH 38/58] Add redirect to custom metrics page --- .../v2.0.x-v2.4.x/cluster-monitoring/custom-metrics/_index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-monitoring/custom-metrics/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-monitoring/custom-metrics/_index.md index 14c6e8af88f..0a1fe82a5cf 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-monitoring/custom-metrics/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.0.x-v2.4.x/cluster-monitoring/custom-metrics/_index.md @@ -4,6 +4,7 @@ weight: 5 aliases: - /rancher/v2.x/en/project-admin/tools/monitoring/custom-metrics - /rancher/v2.x/en/monitoring-alerting/legacy/monitoring/cluster-monitoring/custom-metrics + - /rancher/v2.x/en/cluster-admin/tools/monitoring/custom-metrics/ --- After you've enabled [cluster level monitoring]({{< baseurl >}}/rancher/v2.x/en/monitoring-alerting/legacy/monitoring/cluster-monitoring/#enabling-cluster-monitoring), You can view the metrics data from Rancher. You can also deploy the Prometheus custom metrics adapter then you can use the HPA with metrics stored in cluster monitoring. From 87ad677a111d8b3edc2bf08a6c558ff9ffaa96cc Mon Sep 17 00:00:00 2001 From: Sebastiaan van Steenis Date: Thu, 19 Nov 2020 16:06:43 +0100 Subject: [PATCH 39/58] Add info on etcd snapshots containing state file --- content/rke/latest/en/etcd-snapshots/_index.md | 13 +++++++++---- .../en/etcd-snapshots/example-scenarios/_index.md | 2 +- .../etcd-snapshots/restoring-from-backup/_index.md | 7 +++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/content/rke/latest/en/etcd-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/_index.md index b7b4aca5ce6..5af3516d95b 100644 --- a/content/rke/latest/en/etcd-snapshots/_index.md +++ b/content/rke/latest/en/etcd-snapshots/_index.md @@ -35,6 +35,10 @@ The snapshot is stored in `/opt/rke/etcd-snapshots`. If the directory is configu In the case when multiple etcd nodes exist, any created snapshot is created after the cluster has been health checked, so it can be considered a valid snapshot of the data in the etcd cluster. +_Available as of v1.1.4_ + +Each snapshot will include the cluster state file in addition to the etcd snapshot file. + ### Snapshot Naming The name of the snapshot is auto-generated. The `--name` option can be used to override the name of the snapshot when creating one-time snapshots with the RKE CLI. @@ -46,10 +50,11 @@ An example one-time snapshot name is `rke_etcd_snapshot_2020-10-15T16:47:24+02:0 On restore, the following process is used: 1. The snapshot is retrieved from S3, if S3 is configured. -2. The snapshot is unzipped (if zipped). -3. One of the etcd nodes in the cluster serves that snapshot file to the other nodes. -4. The other etcd nodes download the snapshot and validate the checksum so that they all use the same snapshot for the restore. -5. The cluster is restored and post-restore actions will be done in the cluster. +1. The snapshot is unzipped (if zipped). +1. It is checked if the cluster state file is included in the snapshot, if it is included, it will be used instead of the local cluster state file (_Available as of v1.1.4_) +1. One of the etcd nodes in the cluster serves that snapshot file to the other nodes. +1. The other etcd nodes download the snapshot and validate the checksum so that they all use the same snapshot for the restore. +1. The cluster is restored and post-restore actions will be done in the cluster. ## Troubleshooting diff --git a/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md b/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md index 2cf5ef5aa8b..abf4f768cbc 100644 --- a/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md +++ b/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md @@ -73,7 +73,7 @@ nodes: ### 4. Restore etcd on the New Node from the Backup -> **Prerequisite:** Ensure your `cluster.rkestate` is present before starting the restore, because this contains your certificate data for the cluster. +> **Prerequisite:** If the snapshot was created using RKE v1.1.4 or higher, the cluster state file should be included in the snapshot. The cluster state file will be automatically extracted and used for the restore. If the snapshot was created using RKE v1.1.3 or lower, please ensure your `cluster.rkestate` is present before starting the restore, because this contains your certificate data for the cluster. After the new node is added to the `cluster.yml`, run the `rke etcd snapshot-restore` to launch `etcd` from the backup: diff --git a/content/rke/latest/en/etcd-snapshots/restoring-from-backup/_index.md b/content/rke/latest/en/etcd-snapshots/restoring-from-backup/_index.md index 3f26ea9ee47..7291c3605bd 100644 --- a/content/rke/latest/en/etcd-snapshots/restoring-from-backup/_index.md +++ b/content/rke/latest/en/etcd-snapshots/restoring-from-backup/_index.md @@ -23,6 +23,10 @@ The following actions will be performed when you run the command: The snapshot used to restore your etcd cluster can either be stored locally in `/opt/rke/etcd-snapshots` or from a S3 compatible backend. +_Available as of v1.1.4_ + +If the snapshot contains the cluster state file, it will automatically be extracted and used for the restore. If you want to force the use of the local state file, you can add `--use-local-state` to the command. If the snapshot was created using an RKE version before v1.1.4, or if the snapshot does not contain a state file, make sure the cluster state file (by default available as `cluster.rkestate`) is present before executing the command. + ### Example of Restoring from a Local Snapshot To restore etcd from a local snapshot, run: @@ -37,8 +41,6 @@ The snapshot is assumed to be located in `/opt/rke/etcd-snapshots`. ### Example of Restoring from a Snapshot in S3 -> **Prerequisite:** Ensure your `cluster.rkestate` is present before starting the restore, because this contains your certificate data for the cluster. - When restoring etcd from a snapshot located in S3, the command needs the S3 information in order to connect to the S3 backend and retrieve the snapshot. ```shell @@ -60,6 +62,7 @@ $ rke etcd snapshot-restore \ | --- | --- | ---| | `--name` value | Specify snapshot name | | | `--config` value | Specify an alternate cluster YAML file (default: `cluster.yml`) [$RKE_CONFIG] | | +| `--use-local-state` | Force the use of the local state file instead of looking for a state file in the snapshot _Available as of v1.1.4_ | | | `--s3` | Enabled backup to s3 |* | | `--s3-endpoint` value | Specify s3 endpoint url (default: "s3.amazonaws.com") | * | | `--access-key` value | Specify s3 accessKey | *| From 779cf03858d1bed6621802c74a33cb1109385b3d Mon Sep 17 00:00:00 2001 From: David Nuzik <45179589+davidnuzik@users.noreply.github.com> Date: Thu, 19 Nov 2020 08:37:24 -0700 Subject: [PATCH 40/58] Update issue templates I'd like to request the following GitHub issue templates for rancher/docs. I believe these may make it a bit easier for people to enter issues and to keep things more organized. --- .github/ISSUE_TEMPLATE/request-a-k3s-change.md | 14 ++++++++++++++ .../ISSUE_TEMPLATE/request-a-rancher-2-change.md | 14 ++++++++++++++ .github/ISSUE_TEMPLATE/request-something-else.md | 15 +++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/request-a-k3s-change.md create mode 100644 .github/ISSUE_TEMPLATE/request-a-rancher-2-change.md create mode 100644 .github/ISSUE_TEMPLATE/request-something-else.md diff --git a/.github/ISSUE_TEMPLATE/request-a-k3s-change.md b/.github/ISSUE_TEMPLATE/request-a-k3s-change.md new file mode 100644 index 00000000000..bb8d0ec0542 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-a-k3s-change.md @@ -0,0 +1,14 @@ +--- +name: Request a K3S change +about: I'd like to request a change to the K3s documentation. +title: "[K3s] " +labels: K3s +assignees: '' + +--- + +**Request Summary:** + + +**Details:** + diff --git a/.github/ISSUE_TEMPLATE/request-a-rancher-2-change.md b/.github/ISSUE_TEMPLATE/request-a-rancher-2-change.md new file mode 100644 index 00000000000..79eb0aa89e8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-a-rancher-2-change.md @@ -0,0 +1,14 @@ +--- +name: Request a Rancher 2 change +about: I'd like to request a change to the Rancher 2.x documentation. +title: "[Rancher2] " +labels: Rancher2 +assignees: '' + +--- + +**Request Summary:** + + +**Details:** + diff --git a/.github/ISSUE_TEMPLATE/request-something-else.md b/.github/ISSUE_TEMPLATE/request-something-else.md new file mode 100644 index 00000000000..a43d518ac83 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-something-else.md @@ -0,0 +1,15 @@ +--- +name: Request something else +about: I have a bug to report, or I'd like to request a change in documentation other + than Rancher2 and K3s. +title: '' +labels: '' +assignees: '' + +--- + +**Summary:** + + +**Details:** + From 5093e8d4ae6bc1ddc340a2782afc4b0a2348e786 Mon Sep 17 00:00:00 2001 From: Tejeev Date: Fri, 20 Nov 2020 16:24:59 +0000 Subject: [PATCH 41/58] needed to note how to pull specific version charts --- .../en/installation/upgrades-rollbacks/upgrades/ha/_index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md b/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md index 5e43559c054..e6ed5656b37 100644 --- a/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md +++ b/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md @@ -75,6 +75,11 @@ of your Kubernetes cluster running Rancher server. You'll use the snapshot as a ```plain helm fetch rancher-/rancher ``` + You can fetch the chart for the specific version you are upgrading to by adding in the `--version=` tag. For example: + + ```plain + helm fetch rancher-/rancher --version=v2.4.11 + ``` ### C. Upgrade Rancher From e8c33c314bbc0e8ec92bdff11bd4714aff77d008 Mon Sep 17 00:00:00 2001 From: Denise Schannon Date: Fri, 20 Nov 2020 21:45:17 -0800 Subject: [PATCH 42/58] Rancher v2.5 guides with CIS 1.5 --- .../rancher-2.5/1.5-benchmark-2.5/_index.md | 2265 +++++++++++++++++ .../rancher-2.5/1.5-hardening-2.5/_index.md | 720 ++++++ .../v2.x/en/security/rancher-2.5/_index.md | 29 + 3 files changed, 3014 insertions(+) create mode 100644 content/rancher/v2.x/en/security/rancher-2.5/1.5-benchmark-2.5/_index.md create mode 100644 content/rancher/v2.x/en/security/rancher-2.5/1.5-hardening-2.5/_index.md create mode 100644 content/rancher/v2.x/en/security/rancher-2.5/_index.md diff --git a/content/rancher/v2.x/en/security/rancher-2.5/1.5-benchmark-2.5/_index.md b/content/rancher/v2.x/en/security/rancher-2.5/1.5-benchmark-2.5/_index.md new file mode 100644 index 00000000000..736d478b6b6 --- /dev/null +++ b/content/rancher/v2.x/en/security/rancher-2.5/1.5-benchmark-2.5/_index.md @@ -0,0 +1,2265 @@ +--- +title: CIS 1.5 Benchmark - Self-Assessment Guide - Rancher v2.5 +weight: 204 +--- + +### CIS v1.5 Kubernetes Benchmark - Rancher v2.5 with Kubernetes v1.15 + +[Click here to download a PDF version of this document](https://releases.rancher.com/documents/security/2.5/Rancher_1.5_Benchmark_Assessment.pdf) + +#### Overview + +This document is a companion to the Rancher v2.5 security hardening guide. The hardening guide provides prescriptive guidance for hardening a production installation of Rancher, and this benchmark guide is meant to help you evaluate the level of security of the hardened cluster against each control in the benchmark. + +This guide corresponds to specific versions of the hardening guide, Rancher, CIS Benchmark, and Kubernetes: + +Hardening Guide Version | Rancher Version | CIS Benchmark Version | Kubernetes Version +---------------------------|----------|---------|------- +Hardening Guide with CIS 1.5 Benchmark | Rancher v2.5 | CIS v1.5| Kubernetes v1.15 + +Because Rancher and RKE install Kubernetes services as Docker containers, many of the control verification checks in the CIS Kubernetes Benchmark don't apply and will have a result of `Not Applicable`. This guide will walk through the various controls and provide updated example commands to audit compliance in Rancher-created clusters. + +This document is to be used by Rancher operators, security teams, auditors and decision makers. + +For more detail about each audit, including rationales and remediations for failing tests, you can refer to the corresponding section of the CIS Kubernetes Benchmark v1.5. You can download the benchmark after logging in to [CISecurity.org]( https://www.cisecurity.org/benchmark/kubernetes/). + +#### Testing controls methodology + +Rancher and RKE install Kubernetes services via Docker containers. Configuration is defined by arguments passed to the container at the time of initialization, not via configuration files. + +Where control audits differ from the original CIS benchmark, the audit commands specific to Rancher Labs are provided for testing. +When performing the tests, you will need access to the Docker command line on the hosts of all three RKE roles. The commands also make use of the the [jq](https://stedolan.github.io/jq/) and [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (with valid config) tools to and are required in the testing and evaluation of test results. + +> NOTE: only scored tests are covered in this guide. + +### Controls + +--- +## 1 Master Node Security Configuration +### 1.1 Master Node Configuration Files + +#### 1.1.1 Ensure that the API server pod specification file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the API server. All configuration is passed in as arguments at container run time. + +#### 1.1.2 Ensure that the API server pod specification file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the API server. All configuration is passed in as arguments at container run time. + +#### 1.1.3 Ensure that the controller manager pod specification file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. + +#### 1.1.4 Ensure that the controller manager pod specification file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. + +#### 1.1.5 Ensure that the scheduler pod specification file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. + +#### 1.1.6 Ensure that the scheduler pod specification file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. + +#### 1.1.7 Ensure that the etcd pod specification file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for etcd. All configuration is passed in as arguments at container run time. + +#### 1.1.8 Ensure that the etcd pod specification file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for etcd. All configuration is passed in as arguments at container run time. + +#### 1.1.11 Ensure that the etcd data directory permissions are set to `700` or more restrictive (Scored) + +**Result:** PASS + +**Remediation:** +On the etcd server node, get the etcd data directory, passed as an argument `--data-dir`, +from the below command: + +``` bash +ps -ef | grep etcd +``` + +Run the below command (based on the etcd data directory found above). For example, + +``` bash +chmod 700 /var/lib/etcd +``` + +**Audit Script:** 1.1.11.sh + +``` +#!/bin/bash -e + +etcd_bin=${1} + +test_dir=$(ps -ef | grep ${etcd_bin} | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%') + +docker inspect etcd | jq -r '.[].HostConfig.Binds[]' | grep "${test_dir}" | cut -d ":" -f 1 | xargs stat -c %a +``` + +**Audit Execution:** + +``` +./1.1.11.sh etcd +``` + +**Expected result**: + +``` +'700' is equal to '700' +``` + +#### 1.1.12 Ensure that the etcd data directory ownership is set to `etcd:etcd` (Scored) + +**Result:** PASS + +**Remediation:** +On the etcd server node, get the etcd data directory, passed as an argument `--data-dir`, +from the below command: + +``` bash +ps -ef | grep etcd +``` + +Run the below command (based on the etcd data directory found above). +For example, +``` bash +chown etcd:etcd /var/lib/etcd +``` + +**Audit Script:** 1.1.12.sh + +``` +#!/bin/bash -e + +etcd_bin=${1} + +test_dir=$(ps -ef | grep ${etcd_bin} | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%') + +docker inspect etcd | jq -r '.[].HostConfig.Binds[]' | grep "${test_dir}" | cut -d ":" -f 1 | xargs stat -c %U:%G +``` + +**Audit Execution:** + +``` +./1.1.12.sh etcd +``` + +**Expected result**: + +``` +'etcd:etcd' is present +``` + +#### 1.1.13 Ensure that the `admin.conf` file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE does not store the kubernetes default kubeconfig credentials file on the nodes. It’s presented to user where RKE is run. +We recommend that this `kube_config_cluster.yml` file be kept in secure store. + +#### 1.1.14 Ensure that the admin.conf file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE does not store the kubernetes default kubeconfig credentials file on the nodes. It’s presented to user where RKE is run. +We recommend that this `kube_config_cluster.yml` file be kept in secure store. + +#### 1.1.15 Ensure that the `scheduler.conf` file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. + +#### 1.1.16 Ensure that the `scheduler.conf` file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the scheduler. All configuration is passed in as arguments at container run time. + +#### 1.1.17 Ensure that the `controller-manager.conf` file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. + +#### 1.1.18 Ensure that the `controller-manager.conf` file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the controller manager. All configuration is passed in as arguments at container run time. + +#### 1.1.19 Ensure that the Kubernetes PKI directory and file ownership is set to `root:root` (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the master node. +For example, + +``` bash +chown -R root:root /etc/kubernetes/ssl +``` + +**Audit:** + +``` +stat -c %U:%G /etc/kubernetes/ssl +``` + +**Expected result**: + +``` +'root:root' is present +``` + +#### 1.1.20 Ensure that the Kubernetes PKI certificate file permissions are set to `644` or more restrictive (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the master node. +For example, + +``` bash +chmod -R 644 /etc/kubernetes/ssl +``` + +**Audit Script:** check_files_permissions.sh + +``` +#!/usr/bin/env bash + +# This script is used to ensure the file permissions are set to 644 or +# more restrictive for all files in a given directory or a wildcard +# selection of files +# +# inputs: +# $1 = /full/path/to/directory or /path/to/fileswithpattern +# ex: !(*key).pem +# +# $2 (optional) = permission (ex: 600) +# +# outputs: +# true/false + +# Turn on "extended glob" for use of '!' in wildcard +shopt -s extglob + +# Turn off history to avoid surprises when using '!' +set -H + +USER_INPUT=$1 + +if [[ "${USER_INPUT}" == "" ]]; then + echo "false" + exit +fi + + +if [[ -d ${USER_INPUT} ]]; then + PATTERN="${USER_INPUT}/*" +else + PATTERN="${USER_INPUT}" +fi + +PERMISSION="" +if [[ "$2" != "" ]]; then + PERMISSION=$2 +fi + +FILES_PERMISSIONS=$(stat -c %n\ %a ${PATTERN}) + +while read -r fileInfo; do + p=$(echo ${fileInfo} | cut -d' ' -f2) + + if [[ "${PERMISSION}" != "" ]]; then + if [[ "$p" != "${PERMISSION}" ]]; then + echo "false" + exit + fi + else + if [[ "$p" != "644" && "$p" != "640" && "$p" != "600" ]]; then + echo "false" + exit + fi + fi +done <<< "${FILES_PERMISSIONS}" + + +echo "true" +exit +``` + +**Audit Execution:** + +``` +./check_files_permissions.sh '/etc/kubernetes/ssl/*.pem' +``` + +**Expected result**: + +``` +'true' is present +``` + +#### 1.1.21 Ensure that the Kubernetes PKI key file permissions are set to `600` (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the master node. +For example, + +``` bash +chmod -R 600 /etc/kubernetes/ssl/certs/serverca +``` + +**Audit Script:** 1.1.21.sh + +``` +#!/bin/bash -e +check_dir=${1:-/etc/kubernetes/ssl} + +for file in $(find ${check_dir} -name "*key.pem"); do + file_permission=$(stat -c %a ${file}) + if [[ "${file_permission}" == "600" ]]; then + continue + else + echo "FAIL: ${file} ${file_permission}" + exit 1 + fi +done + +echo "pass" +``` + +**Audit Execution:** + +``` +./1.1.21.sh /etc/kubernetes/ssl +``` + +**Expected result**: + +``` +'pass' is present +``` + +### 1.2 API Server + +#### 1.2.2 Ensure that the `--basic-auth-file` argument is not set (Scored) + +**Result:** PASS + +**Remediation:** +Follow the documentation and configure alternate mechanisms for authentication. Then, +edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and remove the `--basic-auth-file=` parameter. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--basic-auth-file' is not present +``` + +#### 1.2.3 Ensure that the `--token-auth-file` parameter is not set (Scored) + +**Result:** PASS + +**Remediation:** +Follow the documentation and configure alternate mechanisms for authentication. Then, +edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and remove the `--token-auth-file=` parameter. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--token-auth-file' is not present +``` + +#### 1.2.4 Ensure that the `--kubelet-https` argument is set to true (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml +on the master node and remove the `--kubelet-https` parameter. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--kubelet-https' is present OR '--kubelet-https' is not present +``` + +#### 1.2.5 Ensure that the `--kubelet-client-certificate` and `--kubelet-client-key` arguments are set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and set up the TLS connection between the +apiserver and kubelets. Then, edit API server pod specification file +`/etc/kubernetes/manifests/kube-apiserver.yaml` on the master node and set the +kubelet client certificate and key parameters as below. + +``` bash +--kubelet-client-certificate= +--kubelet-client-key= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--kubelet-client-certificate' is present AND '--kubelet-client-key' is present +``` + +#### 1.2.6 Ensure that the `--kubelet-certificate-authority` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and setup the TLS connection between +the apiserver and kubelets. Then, edit the API server pod specification file +`/etc/kubernetes/manifests/kube-apiserver.yaml` on the master node and set the +`--kubelet-certificate-authority` parameter to the path to the cert file for the certificate authority. +`--kubelet-certificate-authority=` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--kubelet-certificate-authority' is present +``` + +#### 1.2.7 Ensure that the `--authorization-mode` argument is not set to `AlwaysAllow` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--authorization-mode` parameter to values other than `AlwaysAllow`. +One such example could be as below. + +``` bash +--authorization-mode=RBAC +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'Node,RBAC' not have 'AlwaysAllow' +``` + +#### 1.2.8 Ensure that the `--authorization-mode` argument includes `Node` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--authorization-mode` parameter to a value that includes `Node`. + +``` bash +--authorization-mode=Node,RBAC +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'Node,RBAC' has 'Node' +``` + +#### 1.2.9 Ensure that the `--authorization-mode` argument includes `RBAC` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--authorization-mode` parameter to a value that includes RBAC, +for example: + +``` bash +--authorization-mode=Node,RBAC +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'Node,RBAC' has 'RBAC' +``` + +#### 1.2.11 Ensure that the admission control plugin `AlwaysAdmit` is not set (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and either remove the `--enable-admission-plugins` parameter, or set it to a +value that does not include `AlwaysAdmit`. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' not have 'AlwaysAdmit' OR '--enable-admission-plugins' is not present +``` + +#### 1.2.14 Ensure that the admission control plugin `ServiceAccount` is set (Scored) + +**Result:** PASS + +**Remediation:** +Follow the documentation and create ServiceAccount objects as per your environment. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and ensure that the `--disable-admission-plugins` parameter is set to a +value that does not include `ServiceAccount`. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' has 'ServiceAccount' OR '--enable-admission-plugins' is not present +``` + +#### 1.2.15 Ensure that the admission control plugin `NamespaceLifecycle` is set (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--disable-admission-plugins` parameter to +ensure it does not include `NamespaceLifecycle`. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--disable-admission-plugins' is present OR '--disable-admission-plugins' is not present +``` + +#### 1.2.16 Ensure that the admission control plugin `PodSecurityPolicy` is set (Scored) + +**Result:** PASS + +**Remediation:** +Follow the documentation and create Pod Security Policy objects as per your environment. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--enable-admission-plugins` parameter to a +value that includes `PodSecurityPolicy`: + +``` bash +--enable-admission-plugins=...,PodSecurityPolicy,... +``` + +Then restart the API Server. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' has 'PodSecurityPolicy' +``` + +#### 1.2.17 Ensure that the admission control plugin `NodeRestriction` is set (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and configure `NodeRestriction` plug-in on kubelets. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--enable-admission-plugins` parameter to a +value that includes `NodeRestriction`. + +``` bash +--enable-admission-plugins=...,NodeRestriction,... +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction,Priority,TaintNodesByCondition,PersistentVolumeClaimResize,PodSecurityPolicy,EventRateLimit' has 'NodeRestriction' +``` + +#### 1.2.18 Ensure that the `--insecure-bind-address` argument is not set (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and remove the `--insecure-bind-address` parameter. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--insecure-bind-address' is not present +``` + +#### 1.2.19 Ensure that the `--insecure-port` argument is set to `0` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the below parameter. + +``` bash +--insecure-port=0 +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'0' is equal to '0' +``` + +#### 1.2.20 Ensure that the `--secure-port` argument is not set to `0` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and either remove the `--secure-port` parameter or +set it to a different **(non-zero)** desired port. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +6443 is greater than 0 OR '--secure-port' is not present +``` + +#### 1.2.21 Ensure that the `--profiling` argument is set to `false` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the below parameter. + +``` bash +--profiling=false +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'false' is equal to 'false' +``` + +#### 1.2.22 Ensure that the `--audit-log-path` argument is set (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--audit-log-path` parameter to a suitable path and +file where you would like audit logs to be written, for example: + +``` bash +--audit-log-path=/var/log/apiserver/audit.log +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--audit-log-path' is present +``` + +#### 1.2.23 Ensure that the `--audit-log-maxage` argument is set to `30` or as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--audit-log-maxage` parameter to `30` or as an appropriate number of days: + +``` bash +--audit-log-maxage=30 +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +30 is greater or equal to 30 +``` + +#### 1.2.24 Ensure that the `--audit-log-maxbackup` argument is set to `10` or as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--audit-log-maxbackup` parameter to `10` or to an appropriate +value. + +``` bash +--audit-log-maxbackup=10 +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +10 is greater or equal to 10 +``` + +#### 1.2.25 Ensure that the `--audit-log-maxsize` argument is set to `100` or as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--audit-log-maxsize` parameter to an appropriate size in **MB**. +For example, to set it as `100` **MB**: + +``` bash +--audit-log-maxsize=100 +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +100 is greater or equal to 100 +``` + +#### 1.2.26 Ensure that the `--request-timeout` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +and set the below parameter as appropriate and if needed. +For example, + +``` bash +--request-timeout=300s +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--request-timeout' is not present OR '--request-timeout' is present +``` + +#### 1.2.27 Ensure that the `--service-account-lookup` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the below parameter. + +``` bash +--service-account-lookup=true +``` + +Alternatively, you can delete the `--service-account-lookup` parameter from this file so +that the default takes effect. + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--service-account-lookup' is not present OR 'true' is equal to 'true' +``` + +#### 1.2.28 Ensure that the `--service-account-key-file` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--service-account-key-file` parameter +to the public key file for service accounts: + +``` bash +--service-account-key-file= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--service-account-key-file' is present +``` + +#### 1.2.29 Ensure that the `--etcd-certfile` and `--etcd-keyfile` arguments are set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the **etcd** certificate and **key** file parameters. + +``` bash +--etcd-certfile= +--etcd-keyfile= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--etcd-certfile' is present AND '--etcd-keyfile' is present +``` + +#### 1.2.30 Ensure that the `--tls-cert-file` and `--tls-private-key-file` arguments are set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and set up the TLS connection on the apiserver. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the TLS certificate and private key file parameters. + +``` bash +--tls-cert-file= +--tls-private-key-file= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--tls-cert-file' is present AND '--tls-private-key-file' is present +``` + +#### 1.2.31 Ensure that the `--client-ca-file` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and set up the TLS connection on the apiserver. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the client certificate authority file. + +``` bash +--client-ca-file= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--client-ca-file' is present +``` + +#### 1.2.32 Ensure that the `--etcd-cafile` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the etcd certificate authority file parameter. + +``` bash +--etcd-cafile= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--etcd-cafile' is present +``` + +#### 1.2.33 Ensure that the `--encryption-provider-config` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and configure a EncryptionConfig file. +Then, edit the API server pod specification file `/etc/kubernetes/manifests/kube-apiserver.yaml` +on the master node and set the `--encryption-provider-config` parameter to the path of that file: + +``` bash +--encryption-provider-config= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-apiserver | grep -v grep +``` + +**Expected result**: + +``` +'--encryption-provider-config' is present +``` + +#### 1.2.34 Ensure that encryption providers are appropriately configured (Scored) + +**Result:** PASS + +**Remediation:** +Follow the Kubernetes documentation and configure a `EncryptionConfig` file. +In this file, choose **aescbc**, **kms** or **secretbox** as the encryption provider. + +**Audit Script:** 1.2.34.sh + +``` +#!/bin/bash -e + +check_file=${1} + +grep -q -E 'aescbc|kms|secretbox' ${check_file} +if [ $? -eq 0 ]; then + echo "--pass" + exit 0 +else + echo "fail: encryption provider found in ${check_file}" + exit 1 +fi +``` + +**Audit Execution:** + +``` +./1.2.34.sh /etc/kubernetes/ssl/encryption.yaml +``` + +**Expected result**: + +``` +'--pass' is present +``` + +### 1.3 Controller Manager + +#### 1.3.1 Ensure that the `--terminated-pod-gc-threshold` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node and set the `--terminated-pod-gc-threshold` to an appropriate threshold, +for example: + +``` bash +--terminated-pod-gc-threshold=10 +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'--terminated-pod-gc-threshold' is present +``` + +#### 1.3.2 Ensure that the `--profiling` argument is set to false (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node and set the below parameter. + +``` bash +--profiling=false +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'false' is equal to 'false' +``` + +#### 1.3.3 Ensure that the `--use-service-account-credentials` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node to set the below parameter. + +``` bash +--use-service-account-credentials=true +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'true' is not equal to 'false' +``` + +#### 1.3.4 Ensure that the `--service-account-private-key-file` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node and set the `--service-account-private-key-file` parameter +to the private key file for service accounts. + +``` bash +--service-account-private-key-file= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'--service-account-private-key-file' is present +``` + +#### 1.3.5 Ensure that the `--root-ca-file` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node and set the `--root-ca-file` parameter to the certificate bundle file`. + +``` bash +--root-ca-file= +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'--root-ca-file' is present +``` + +#### 1.3.6 Ensure that the `RotateKubeletServerCertificate` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node and set the `--feature-gates` parameter to include `RotateKubeletServerCertificate=true`. + +``` bash +--feature-gates=RotateKubeletServerCertificate=true +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'RotateKubeletServerCertificate=true' is equal to 'RotateKubeletServerCertificate=true' +``` + +#### 1.3.7 Ensure that the `--bind-address argument` is set to `127.0.0.1` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Controller Manager pod specification file `/etc/kubernetes/manifests/kube-controller-manager.yaml` +on the master node and ensure the correct value for the `--bind-address` parameter. + +**Audit:** + +``` +/bin/ps -ef | grep kube-controller-manager | grep -v grep +``` + +**Expected result**: + +``` +'--bind-address' is present OR '--bind-address' is not present +``` + +### 1.4 Scheduler + +#### 1.4.1 Ensure that the `--profiling` argument is set to `false` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Scheduler pod specification file `/etc/kubernetes/manifests/kube-scheduler.yaml` file +on the master node and set the below parameter. + +``` bash +--profiling=false +``` + +**Audit:** + +``` +/bin/ps -ef | grep kube-scheduler | grep -v grep +``` + +**Expected result**: + +``` +'false' is equal to 'false' +``` + +#### 1.4.2 Ensure that the `--bind-address` argument is set to `127.0.0.1` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the Scheduler pod specification file `/etc/kubernetes/manifests/kube-scheduler.yaml` +on the master node and ensure the correct value for the `--bind-address` parameter. + +**Audit:** + +``` +/bin/ps -ef | grep kube-scheduler | grep -v grep +``` + +**Expected result**: + +``` +'--bind-address' is present OR '--bind-address' is not present +``` + +## 2 Etcd Node Configuration +### 2 Etcd Node Configuration Files + +#### 2.1 Ensure that the `--cert-file` and `--key-file` arguments are set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the etcd service documentation and configure TLS encryption. +Then, edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` +on the master node and set the below parameters. + +``` bash +--cert-file= +--key-file= +``` + +**Audit:** + +``` +/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep +``` + +**Expected result**: + +``` +'--cert-file' is present AND '--key-file' is present +``` + +#### 2.2 Ensure that the `--client-cert-auth` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master +node and set the below parameter. + +``` bash +--client-cert-auth="true" +``` + +**Audit:** + +``` +/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep +``` + +**Expected result**: + +``` +'true' is equal to 'true' +``` + +#### 2.3 Ensure that the `--auto-tls` argument is not set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master +node and either remove the `--auto-tls` parameter or set it to `false`. + +``` bash + --auto-tls=false +``` + +**Audit:** + +``` +/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep +``` + +**Expected result**: + +``` +'--auto-tls' is not present OR '--auto-tls' is not present +``` + +#### 2.4 Ensure that the `--peer-cert-file` and `--peer-key-file` arguments are set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +Follow the etcd service documentation and configure peer TLS encryption as appropriate +for your etcd cluster. Then, edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the +master node and set the below parameters. + +``` bash +--peer-client-file= +--peer-key-file= +``` + +**Audit:** + +``` +/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep +``` + +**Expected result**: + +``` +'--peer-cert-file' is present AND '--peer-key-file' is present +``` + +#### 2.5 Ensure that the `--peer-client-cert-auth` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master +node and set the below parameter. + +``` bash +--peer-client-cert-auth=true +``` + +**Audit:** + +``` +/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep +``` + +**Expected result**: + +``` +'true' is equal to 'true' +``` + +#### 2.6 Ensure that the `--peer-auto-tls` argument is not set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the etcd pod specification file `/etc/kubernetes/manifests/etcd.yaml` on the master +node and either remove the `--peer-auto-tls` parameter or set it to `false`. + +``` bash +--peer-auto-tls=false +``` + +**Audit:** + +``` +/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep +``` + +**Expected result**: + +``` +'--peer-auto-tls' is not present OR '--peer-auto-tls' is present +``` + +## 3 Control Plane Configuration +### 3.2 Logging + +#### 3.2.1 Ensure that a minimal audit policy is created (Scored) + +**Result:** PASS + +**Remediation:** +Create an audit policy file for your cluster. + +**Audit Script:** 3.2.1.sh + +``` +#!/bin/bash -e + +api_server_bin=${1} + +/bin/ps -ef | /bin/grep ${api_server_bin} | /bin/grep -v ${0} | /bin/grep -v grep +``` + +**Audit Execution:** + +``` +./3.2.1.sh kube-apiserver +``` + +**Expected result**: + +``` +'--audit-policy-file' is present +``` + +## 4 Worker Node Security Configuration +### 4.1 Worker Node Configuration Files + +#### 4.1.1 Ensure that the kubelet service file permissions are set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. + +#### 4.1.2 Ensure that the kubelet service file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. + +#### 4.1.3 Ensure that the proxy kubeconfig file permissions are set to `644` or more restrictive (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the each worker node. +For example, + +``` bash +chmod 644 /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml +``` + +**Audit:** + +``` +/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; then stat -c %a /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; fi' +``` + +**Expected result**: + +``` +'644' is present OR '640' is present OR '600' is equal to '600' OR '444' is present OR '440' is present OR '400' is present OR '000' is present +``` + +#### 4.1.4 Ensure that the proxy kubeconfig file ownership is set to `root:root` (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the each worker node. +For example, + +``` bash +chown root:root /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml +``` + +**Audit:** + +``` +/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; then stat -c %U:%G /etc/kubernetes/ssl/kubecfg-kube-proxy.yaml; fi' +``` + +**Expected result**: + +``` +'root:root' is present +``` + +#### 4.1.5 Ensure that the kubelet.conf file permissions are set to `644` or more restrictive (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the each worker node. +For example, + +``` bash +chmod 644 /etc/kubernetes/ssl/kubecfg-kube-node.yaml +``` + +**Audit:** + +``` +/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-node.yaml; then stat -c %a /etc/kubernetes/ssl/kubecfg-kube-node.yaml; fi' +``` + +**Expected result**: + +``` +'644' is present OR '640' is present OR '600' is equal to '600' OR '444' is present OR '440' is present OR '400' is present OR '000' is present +``` + +#### 4.1.6 Ensure that the kubelet.conf file ownership is set to `root:root` (Scored) + +**Result:** PASS + +**Remediation:** +Run the below command (based on the file location on your system) on the each worker node. +For example, + +``` bash +chown root:root /etc/kubernetes/ssl/kubecfg-kube-node.yaml +``` + +**Audit:** + +``` +/bin/sh -c 'if test -e /etc/kubernetes/ssl/kubecfg-kube-node.yaml; then stat -c %U:%G /etc/kubernetes/ssl/kubecfg-kube-node.yaml; fi' +``` + +**Expected result**: + +``` +'root:root' is equal to 'root:root' +``` + +#### 4.1.7 Ensure that the certificate authorities file permissions are set to `644` or more restrictive (Scored) + +**Result:** PASS + +**Remediation:** +Run the following command to modify the file permissions of the + +``` bash +--client-ca-file chmod 644 +``` + +**Audit:** + +``` +stat -c %a /etc/kubernetes/ssl/kube-ca.pem +``` + +**Expected result**: + +``` +'644' is equal to '644' OR '640' is present OR '600' is present +``` + +#### 4.1.8 Ensure that the client certificate authorities file ownership is set to `root:root` (Scored) + +**Result:** PASS + +**Remediation:** +Run the following command to modify the ownership of the `--client-ca-file`. + +``` bash +chown root:root +``` + +**Audit:** + +``` +/bin/sh -c 'if test -e /etc/kubernetes/ssl/kube-ca.pem; then stat -c %U:%G /etc/kubernetes/ssl/kube-ca.pem; fi' +``` + +**Expected result**: + +``` +'root:root' is equal to 'root:root' +``` + +#### 4.1.9 Ensure that the kubelet configuration file has permissions set to `644` or more restrictive (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. + +#### 4.1.10 Ensure that the kubelet configuration file ownership is set to `root:root` (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. + +### 4.2 Kubelet + +#### 4.2.1 Ensure that the `--anonymous-auth argument` is set to false (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set authentication: `anonymous`: enabled to +`false`. +If using executable arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. + +``` bash +--anonymous-auth=false +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'false' is equal to 'false' +``` + +#### 4.2.2 Ensure that the `--authorization-mode` argument is not set to `AlwaysAllow` (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set authorization: `mode` to `Webhook`. If +using executable arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +set the below parameter in `KUBELET_AUTHZ_ARGS` variable. + +``` bash +--authorization-mode=Webhook +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'Webhook' not have 'AlwaysAllow' +``` + +#### 4.2.3 Ensure that the `--client-ca-file` argument is set as appropriate (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set authentication: `x509`: `clientCAFile` to +the location of the client CA file. +If using command line arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +set the below parameter in `KUBELET_AUTHZ_ARGS` variable. + +``` bash +--client-ca-file= +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'--client-ca-file' is present +``` + +#### 4.2.4 Ensure that the `--read-only-port` argument is set to `0` (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set `readOnlyPort` to `0`. +If using command line arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. + +``` bash +--read-only-port=0 +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'0' is equal to '0' +``` + +#### 4.2.5 Ensure that the `--streaming-connection-idle-timeout` argument is not set to `0` (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set `streamingConnectionIdleTimeout` to a +value other than `0`. +If using command line arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. + +``` bash +--streaming-connection-idle-timeout=5m +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'30m' is not equal to '0' OR '--streaming-connection-idle-timeout' is not present +``` + +#### 4.2.6 Ensure that the ```--protect-kernel-defaults``` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set `protectKernelDefaults`: `true`. +If using command line arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +set the below parameter in `KUBELET_SYSTEM_PODS_ARGS` variable. + +``` bash +--protect-kernel-defaults=true +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'true' is equal to 'true' +``` + +#### 4.2.7 Ensure that the `--make-iptables-util-chains` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to set `makeIPTablesUtilChains`: `true`. +If using command line arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +remove the `--make-iptables-util-chains` argument from the +`KUBELET_SYSTEM_PODS_ARGS` variable. +Based on your system, restart the kubelet service. For example: + +```bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'true' is equal to 'true' OR '--make-iptables-util-chains' is not present +``` + +#### 4.2.10 Ensure that the `--tls-cert-file` and `--tls-private-key-file` arguments are set as appropriate (Scored) + +**Result:** Not Applicable + +**Remediation:** +RKE doesn’t require or maintain a configuration file for the kubelet service. All configuration is passed in as arguments at container run time. + +#### 4.2.11 Ensure that the `--rotate-certificates` argument is not set to `false` (Scored) + +**Result:** PASS + +**Remediation:** +If using a Kubelet config file, edit the file to add the line `rotateCertificates`: `true` or +remove it altogether to use the default value. +If using command line arguments, edit the kubelet service file +`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` on each worker node and +remove `--rotate-certificates=false` argument from the `KUBELET_CERTIFICATE_ARGS` +variable. +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'--rotate-certificates' is present OR '--rotate-certificates' is not present +``` + +#### 4.2.12 Ensure that the `RotateKubeletServerCertificate` argument is set to `true` (Scored) + +**Result:** PASS + +**Remediation:** +Edit the kubelet service file `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` +on each worker node and set the below parameter in `KUBELET_CERTIFICATE_ARGS` variable. + +``` bash +--feature-gates=RotateKubeletServerCertificate=true +``` + +Based on your system, restart the kubelet service. For example: + +``` bash +systemctl daemon-reload +systemctl restart kubelet.service +``` + +**Audit:** + +``` +/bin/ps -fC kubelet +``` + +**Audit Config:** + +``` +/bin/cat /var/lib/kubelet/config.yaml +``` + +**Expected result**: + +``` +'true' is equal to 'true' +``` + +## 5 Kubernetes Policies +### 5.1 RBAC and Service Accounts + +#### 5.1.5 Ensure that default service accounts are not actively used. (Scored) + +**Result:** PASS + +**Remediation:** +Create explicit service accounts wherever a Kubernetes workload requires specific access +to the Kubernetes API server. +Modify the configuration of each default service account to include this value + +``` bash +automountServiceAccountToken: false +``` + +**Audit Script:** 5.1.5.sh + +``` +#!/bin/bash + +export KUBECONFIG=${KUBECONFIG:-/root/.kube/config} + +kubectl version > /dev/null +if [ $? -ne 0 ]; then + echo "fail: kubectl failed" + exit 1 +fi + +accounts="$(kubectl --kubeconfig=${KUBECONFIG} get serviceaccounts -A -o json | jq -r '.items[] | select(.metadata.name=="default") | select((.automountServiceAccountToken == null) or (.automountServiceAccountToken == true)) | "fail \(.metadata.name) \(.metadata.namespace)"')" + +if [[ "${accounts}" != "" ]]; then + echo "fail: automountServiceAccountToken not false for accounts: ${accounts}" + exit 1 +fi + +default_binding="$(kubectl get rolebindings,clusterrolebindings -A -o json | jq -r '.items[] | select(.subjects[].kind=="ServiceAccount" and .subjects[].name=="default" and .metadata.name=="default").metadata.uid' | wc -l)" + +if [[ "${default_binding}" -gt 0 ]]; then + echo "fail: default service accounts have non default bindings" + exit 1 +fi + +echo "--pass" +exit 0 +``` + +**Audit Execution:** + +``` +./5.1.5.sh +``` + +**Expected result**: + +``` +'--pass' is present +``` + +### 5.2 Pod Security Policies + +#### 5.2.2 Minimize the admission of containers wishing to share the host process ID namespace (Scored) + +**Result:** PASS + +**Remediation:** +Create a PSP as described in the Kubernetes documentation, ensuring that the +`.spec.hostPID` field is omitted or set to `false`. + +**Audit:** + +``` +kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.hostPID == null) or (.spec.hostPID == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' +``` + +**Expected result**: + +``` +1 is greater than 0 +``` + +#### 5.2.3 Minimize the admission of containers wishing to share the host IPC namespace (Scored) + +**Result:** PASS + +**Remediation:** +Create a PSP as described in the Kubernetes documentation, ensuring that the +`.spec.hostIPC` field is omitted or set to `false`. + +**Audit:** + +``` +kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.hostIPC == null) or (.spec.hostIPC == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' +``` + +**Expected result**: + +``` +1 is greater than 0 +``` + +#### 5.2.4 Minimize the admission of containers wishing to share the host network namespace (Scored) + +**Result:** PASS + +**Remediation:** +Create a PSP as described in the Kubernetes documentation, ensuring that the +`.spec.hostNetwork` field is omitted or set to `false`. + +**Audit:** + +``` +kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.hostNetwork == null) or (.spec.hostNetwork == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' +``` + +**Expected result**: + +``` +1 is greater than 0 +``` + +#### 5.2.5 Minimize the admission of containers with `allowPrivilegeEscalation` (Scored) + +**Result:** PASS + +**Remediation:** +Create a PSP as described in the Kubernetes documentation, ensuring that the +`.spec.allowPrivilegeEscalation` field is omitted or set to `false`. + +**Audit:** + +``` +kubectl --kubeconfig=/root/.kube/config get psp -o json | jq .items[] | jq -r 'select((.spec.allowPrivilegeEscalation == null) or (.spec.allowPrivilegeEscalation == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}' +``` + +**Expected result**: + +``` +1 is greater than 0 +``` + +### 5.3 Network Policies and CNI + +#### 5.3.2 Ensure that all Namespaces have Network Policies defined (Scored) + +**Result:** PASS + +**Remediation:** +Follow the documentation and create `NetworkPolicy` objects as you need them. + +**Audit Script:** 5.3.2.sh + +``` +#!/bin/bash -e + +export KUBECONFIG=${KUBECONFIG:-"/root/.kube/config"} + +kubectl version > /dev/null +if [ $? -ne 0 ]; then + echo "fail: kubectl failed" + exit 1 +fi + +for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do + policy_count=$(kubectl get networkpolicy -n ${namespace} -o json | jq '.items | length') + if [ ${policy_count} -eq 0 ]; then + echo "fail: ${namespace}" + exit 1 + fi +done + +echo "pass" +``` + +**Audit Execution:** + +``` +./5.3.2.sh +``` + +**Expected result**: + +``` +'pass' is present +``` + +### 5.6 General Policies + +#### 5.6.4 The default namespace should not be used (Scored) + +**Result:** PASS + +**Remediation:** +Ensure that namespaces are created to allow for appropriate segregation of Kubernetes +resources and that all new resources are created in a specific namespace. + +**Audit Script:** 5.6.4.sh + +``` +#!/bin/bash -e + +export KUBECONFIG=${KUBECONFIG:-/root/.kube/config} + +kubectl version > /dev/null +if [[ $? -gt 0 ]]; then + echo "fail: kubectl failed" + exit 1 +fi + +default_resources=$(kubectl get all -o json | jq --compact-output '.items[] | select((.kind == "Service") and (.metadata.name == "kubernetes") and (.metadata.namespace == "default") | not)' | wc -l) + +echo "--count=${default_resources}" +``` + +**Audit Execution:** + +``` +./5.6.4.sh +``` + +**Expected result**: + +``` +'0' is equal to '0' +``` diff --git a/content/rancher/v2.x/en/security/rancher-2.5/1.5-hardening-2.5/_index.md b/content/rancher/v2.x/en/security/rancher-2.5/1.5-hardening-2.5/_index.md new file mode 100644 index 00000000000..599b75bf495 --- /dev/null +++ b/content/rancher/v2.x/en/security/rancher-2.5/1.5-hardening-2.5/_index.md @@ -0,0 +1,720 @@ +--- +title: Hardening Guide with CIS 1.5 Benchmark +weight: 99 +--- + +This document provides prescriptive guidance for hardening a production installation of a RKE cluster to be used with Rancher v2.5. It outlines the configurations and controls required to address Kubernetes benchmark controls from the Center for Information Security (CIS). + +> This hardening guide describes how to secure the nodes in your cluster, and it is recommended to follow this guide before installing Kubernetes. + +This hardening guide is intended to be used for RKE clusters and associated with specific versions of the CIS Kubernetes Benchmark, Kubernetes, and Rancher: + + Rancher Version | CIS Benchmark Version | Kubernetes Version +----------------|-----------------------|------------------ + Rancher v2.5 | Benchmark v1.5 | Kubernetes 1.15 + +[Click here to download a PDF version of this document](https://releases.rancher.com/documents/security/2.5/Rancher_Hardening_Guide_CIS_1.5.pdf) + +### Overview + +This document provides prescriptive guidance for hardening a RKE cluster to be used for installing Rancher v2.5 with Kubernetes v1.15 or provisioning a RKE cluster with Kubernetes 1.15 to be used within Rancher v2.5. It outlines the configurations required to address Kubernetes benchmark controls from the Center for Information Security (CIS). + +For more detail about evaluating a hardened cluster against the official CIS benchmark, refer to the [CIS 1.5 Benchmark - Self-Assessment Guide - Rancher v2.5]({{< baseurl >}}/rancher/v2.x/en/security/rancher-2.5/1.5-benchmark-2.5/). + +#### Known Issues + +- Rancher **exec shell** and **view logs** for pods are **not** functional in a CIS 1.5 hardened setup when only public IP is provided when registering custom nodes. This functionality requires a private IP to be provided when registering the custom nodes. +- When setting the `default_pod_security_policy_template_id:` to `restricted` Rancher creates **RoleBindings** and **ClusterRoleBindings** on the default service accounts. The CIS 1.5 5.1.5 check requires the default service accounts have no roles or cluster roles bound to it apart from the defaults. In addition the default service accounts should be configured such that it does not provide a service account token and does not have any explicit rights assignments. + +### Configure Kernel Runtime Parameters + +The following `sysctl` configuration is recommended for all nodes type in the cluster. Set the following parameters in `/etc/sysctl.d/90-kubelet.conf`: + +``` +vm.overcommit_memory=1 +vm.panic_on_oom=0 +kernel.panic=10 +kernel.panic_on_oops=1 +kernel.keys.root_maxbytes=25000000 +``` + +Run `sysctl -p /etc/sysctl.d/90-kubelet.conf` to enable the settings. + +### Configure `etcd` user and group +A user account and group for the **etcd** service is required to be setup prior to installing RKE. The **uid** and **gid** for the **etcd** user will be used in the RKE **config.yml** to set the proper permissions for files and directories during installation time. + +#### create `etcd` user and group +To create the **etcd** group run the following console commands. + +The commands below use `52034` for **uid** and **gid** are for example purposes. Any valid unused **uid** or **gid** could also be used in lieu of `52034`. + +``` +groupadd --gid 52034 etcd +useradd --comment "etcd service account" --uid 52034 --gid 52034 etcd +``` + +Update the RKE **config.yml** with the **uid** and **gid** of the **etcd** user: + +``` yaml +services: + etcd: + gid: 52034 + uid: 52034 +``` + +#### Set `automountServiceAccountToken` to `false` for `default` service accounts +Kubernetes provides a default service account which is used by cluster workloads where no specific service account is assigned to the pod. Where access to the Kubernetes API from a pod is required, a specific service account should be created for that pod, and rights granted to that service account. The default service account should be configured such that it does not provide a service account token and does not have any explicit rights assignments. + +For each namespace including **default** and **kube-system** on a standard RKE install the **default** service account must include this value: + +``` +automountServiceAccountToken: false +``` + +Save the following yaml to a file called `account_update.yaml` + +``` yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: default +automountServiceAccountToken: false +``` + +Create a bash script file called `account_update.sh`. Be sure to `chmod +x account_update.sh` so the script has execute permissions. + +``` +#!/bin/bash -e + +for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do + kubectl patch serviceaccount default -n ${namespace} -p "$(cat account_update.yaml)" +done +``` + +### Ensure that all Namespaces have Network Policies defined + +Running different applications on the same Kubernetes cluster creates a risk of one +compromised application attacking a neighboring application. Network segmentation is +important to ensure that containers can communicate only with those they are supposed +to. A network policy is a specification of how selections of pods are allowed to +communicate with each other and other network endpoints. + +Network Policies are namespace scoped. When a network policy is introduced to a given +namespace, all traffic not allowed by the policy is denied. However, if there are no network +policies in a namespace all traffic will be allowed into and out of the pods in that +namespace. To enforce network policies, a CNI (container network interface) plugin must be enabled. +This guide uses [canal](https://github.com/projectcalico/canal) to provide the policy enforcement. +Additional information about CNI providers can be found +[here](https://rancher.com/blog/2019/2019-03-21-comparing-kubernetes-cni-providers-flannel-calico-canal-and-weave/) + +Once a CNI provider is enabled on a cluster a default network policy can be applied. For reference purposes a +**permissive** example is provide below. If you want to allow all traffic to all pods in a namespace +(even if policies are added that cause some pods to be treated as “isolated”), +you can create a policy that explicitly allows all traffic in that namespace. Save the following `yaml` as +`default-allow-all.yaml`. Additional [documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/) +about network policies can be found on the Kubernetes site. + +> This `NetworkPolicy` is not recommended for production use + +``` yaml +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-allow-all +spec: + podSelector: {} + ingress: + - {} + egress: + - {} + policyTypes: + - Ingress + - Egress +``` + +Create a bash script file called `apply_networkPolicy_to_all_ns.sh`. Be sure to +`chmod +x apply_networkPolicy_to_all_ns.sh` so the script has execute permissions. + +``` +#!/bin/bash -e + +for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do + kubectl apply -f default-allow-all.yaml -n ${namespace} +done +``` +Execute this script to apply the `default-allow-all.yaml` the **permissive** `NetworkPolicy` to all namespaces. + +### Reference Hardened RKE `cluster.yml` configuration + +The reference `cluster.yml` is used by the RKE CLI that provides the configuration needed to achieve a hardened install +of Rancher Kubernetes Engine (RKE). Install [documentation](https://rancher.com/docs/rke/latest/en/installation/) is +provided with additional details about the configuration items. This reference `cluster.yml` does not include the required **nodes** directive which will vary depending on your environment. Documentation for node configuration can be found here: https://rancher.com/docs/rke/latest/en/config-options/nodes + + +``` yaml +# If you intend to deploy Kubernetes in an air-gapped environment, +# please consult the documentation on how to configure custom RKE images. +kubernetes_version: "v1.15.9-rancher1-1" +enable_network_policy: true +default_pod_security_policy_template_id: "restricted" +# the nodes directive is required and will vary depending on your environment +# documentation for node configuration can be found here: +# https://rancher.com/docs/rke/latest/en/config-options/nodes +nodes: +services: + etcd: + uid: 52034 + gid: 52034 + kube-api: + pod_security_policy: true + secrets_encryption_config: + enabled: true + audit_log: + enabled: true + admission_configuration: + event_rate_limit: + enabled: true + kube-controller: + extra_args: + feature-gates: "RotateKubeletServerCertificate=true" + scheduler: + image: "" + extra_args: {} + extra_binds: [] + extra_env: [] + kubelet: + generate_serving_certificate: true + extra_args: + feature-gates: "RotateKubeletServerCertificate=true" + protect-kernel-defaults: "true" + tls-cipher-suites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256" + extra_binds: [] + extra_env: [] + cluster_domain: "" + infra_container_image: "" + cluster_dns_server: "" + fail_swap_on: false + kubeproxy: + image: "" + extra_args: {} + extra_binds: [] + extra_env: [] +network: + plugin: "" + options: {} + mtu: 0 + node_selector: {} +authentication: + strategy: "" + sans: [] + webhook: null +addons: | + --- + apiVersion: v1 + kind: Namespace + metadata: + name: ingress-nginx + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: default-psp-role + namespace: ingress-nginx + rules: + - apiGroups: + - extensions + resourceNames: + - default-psp + resources: + - podsecuritypolicies + verbs: + - use + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: default-psp-rolebinding + namespace: ingress-nginx + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: default-psp-role + subjects: + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated + --- + apiVersion: v1 + kind: Namespace + metadata: + name: cattle-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: default-psp-role + namespace: cattle-system + rules: + - apiGroups: + - extensions + resourceNames: + - default-psp + resources: + - podsecuritypolicies + verbs: + - use + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: default-psp-rolebinding + namespace: cattle-system + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: default-psp-role + subjects: + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated + --- + apiVersion: policy/v1beta1 + kind: PodSecurityPolicy + metadata: + name: restricted + spec: + requiredDropCapabilities: + - NET_RAW + privileged: false + allowPrivilegeEscalation: false + defaultAllowPrivilegeEscalation: false + fsGroup: + rule: RunAsAny + runAsUser: + rule: MustRunAsNonRoot + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - emptyDir + - secret + - persistentVolumeClaim + - downwardAPI + - configMap + - projected + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: psp:restricted + rules: + - apiGroups: + - extensions + resourceNames: + - restricted + resources: + - podsecuritypolicies + verbs: + - use + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: psp:restricted + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: psp:restricted + subjects: + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated + --- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: tiller + namespace: kube-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: tiller + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin + subjects: + - kind: ServiceAccount + name: tiller + namespace: kube-system + +addons_include: [] +system_images: + etcd: "" + alpine: "" + nginx_proxy: "" + cert_downloader: "" + kubernetes_services_sidecar: "" + kubedns: "" + dnsmasq: "" + kubedns_sidecar: "" + kubedns_autoscaler: "" + coredns: "" + coredns_autoscaler: "" + kubernetes: "" + flannel: "" + flannel_cni: "" + calico_node: "" + calico_cni: "" + calico_controllers: "" + calico_ctl: "" + calico_flexvol: "" + canal_node: "" + canal_cni: "" + canal_flannel: "" + canal_flexvol: "" + weave_node: "" + weave_cni: "" + pod_infra_container: "" + ingress: "" + ingress_backend: "" + metrics_server: "" + windows_pod_infra_container: "" +ssh_key_path: "" +ssh_cert_path: "" +ssh_agent_auth: false +authorization: + mode: "" + options: {} +ignore_docker_version: false +private_registries: [] +ingress: + provider: "" + options: {} + node_selector: {} + extra_args: {} + dns_policy: "" + extra_envs: [] + extra_volumes: [] + extra_volume_mounts: [] +cluster_name: "" +prefix_path: "" +addon_job_timeout: 0 +bastion_host: + address: "" + port: "" + user: "" + ssh_key: "" + ssh_key_path: "" + ssh_cert: "" + ssh_cert_path: "" +monitoring: + provider: "" + options: {} + node_selector: {} +restore: + restore: false + snapshot_name: "" +dns: null +``` + +### Reference Hardened RKE Template configuration + +The reference RKE Template provides the configuration needed to achieve a hardened install of Kubenetes. +RKE Templates are used to provision Kubernetes and define Rancher settings. Follow the Rancher +[documentaion](https://rancher.com/docs/rancher/v2.x/en/installation) for additional installation and RKE Template details. + +``` yaml +# +# Cluster Config +# +default_pod_security_policy_template_id: restricted +docker_root_dir: /var/lib/docker +enable_cluster_alerting: false +enable_cluster_monitoring: false +enable_network_policy: true +# +# Rancher Config +# +rancher_kubernetes_engine_config: + addon_job_timeout: 30 + addons: |- + --- + apiVersion: v1 + kind: Namespace + metadata: + name: ingress-nginx + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: default-psp-role + namespace: ingress-nginx + rules: + - apiGroups: + - extensions + resourceNames: + - default-psp + resources: + - podsecuritypolicies + verbs: + - use + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: default-psp-rolebinding + namespace: ingress-nginx + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: default-psp-role + subjects: + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated + --- + apiVersion: v1 + kind: Namespace + metadata: + name: cattle-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: default-psp-role + namespace: cattle-system + rules: + - apiGroups: + - extensions + resourceNames: + - default-psp + resources: + - podsecuritypolicies + verbs: + - use + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: default-psp-rolebinding + namespace: cattle-system + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: default-psp-role + subjects: + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated + --- + apiVersion: policy/v1beta1 + kind: PodSecurityPolicy + metadata: + name: restricted + spec: + requiredDropCapabilities: + - NET_RAW + privileged: false + allowPrivilegeEscalation: false + defaultAllowPrivilegeEscalation: false + fsGroup: + rule: RunAsAny + runAsUser: + rule: MustRunAsNonRoot + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - emptyDir + - secret + - persistentVolumeClaim + - downwardAPI + - configMap + - projected + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: psp:restricted + rules: + - apiGroups: + - extensions + resourceNames: + - restricted + resources: + - podsecuritypolicies + verbs: + - use + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: psp:restricted + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: psp:restricted + subjects: + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts + - apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated + --- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: tiller + namespace: kube-system + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: tiller + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin + subjects: + - kind: ServiceAccount + name: tiller + namespace: kube-system + ignore_docker_version: true + kubernetes_version: v1.15.9-rancher1-1 +# +# If you are using calico on AWS +# +# network: +# plugin: calico +# calico_network_provider: +# cloud_provider: aws +# +# # To specify flannel interface +# +# network: +# plugin: flannel +# flannel_network_provider: +# iface: eth1 +# +# # To specify flannel interface for canal plugin +# +# network: +# plugin: canal +# canal_network_provider: +# iface: eth1 +# + network: + mtu: 0 + plugin: canal +# +# services: +# kube-api: +# service_cluster_ip_range: 10.43.0.0/16 +# kube-controller: +# cluster_cidr: 10.42.0.0/16 +# service_cluster_ip_range: 10.43.0.0/16 +# kubelet: +# cluster_domain: cluster.local +# cluster_dns_server: 10.43.0.10 +# + services: + etcd: + backup_config: + enabled: false + interval_hours: 12 + retention: 6 + safe_timestamp: false + creation: 12h + extra_args: + election-timeout: '5000' + heartbeat-interval: '500' + gid: 52034 + retention: 72h + snapshot: false + uid: 52034 + kube_api: + always_pull_images: false + audit_log: + enabled: true + event_rate_limit: + enabled: true + pod_security_policy: true + secrets_encryption_config: + enabled: true + service_node_port_range: 30000-32767 + kube_controller: + extra_args: + address: 127.0.0.1 + feature-gates: RotateKubeletServerCertificate=true + profiling: 'false' + terminated-pod-gc-threshold: '1000' + kubelet: + extra_args: + anonymous-auth: 'false' + event-qps: '0' + feature-gates: RotateKubeletServerCertificate=true + make-iptables-util-chains: 'true' + protect-kernel-defaults: 'true' + streaming-connection-idle-timeout: 1800s + tls-cipher-suites: >- + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256 + fail_swap_on: false + generate_serving_certificate: true + scheduler: + extra_args: + address: 127.0.0.1 + profiling: 'false' + ssh_agent_auth: false +windows_prefered_cluster: false +``` + +### Hardened Reference Ubuntu 18.04 LTS **cloud-config**: + +The reference **cloud-config** is generally used in cloud infrastructure environments to allow for +configuration management of compute instances. The reference config configures Ubuntu operating system level settings +needed before installing kubernetes. + +``` yaml +#cloud-config +packages: + - curl + - jq +runcmd: + - sysctl -w vm.overcommit_memory=1 + - sysctl -w kernel.panic=10 + - sysctl -w kernel.panic_on_oops=1 + - curl https://releases.rancher.com/install-docker/18.09.sh | sh + - usermod -aG docker ubuntu + - return=1; while [ $return != 0 ]; do sleep 2; docker ps; return=$?; done + - addgroup --gid 52034 etcd + - useradd --comment "etcd service account" --uid 52034 --gid 52034 etcd +write_files: + - path: /etc/sysctl.d/kubelet.conf + owner: root:root + permissions: "0644" + content: | + vm.overcommit_memory=1 + kernel.panic=10 + kernel.panic_on_oops=1 +``` diff --git a/content/rancher/v2.x/en/security/rancher-2.5/_index.md b/content/rancher/v2.x/en/security/rancher-2.5/_index.md new file mode 100644 index 00000000000..8640b28ec10 --- /dev/null +++ b/content/rancher/v2.x/en/security/rancher-2.5/_index.md @@ -0,0 +1,29 @@ +--- +title: Rancher v2.5 +weight: 1 +--- + +For Rancher v2.5, the guides are organized differntly than previous guides. Since Rancher v2.5 can be deployed on any Kubernetes cluster, the guides are broken up based on Rancher's Kubernetes distributions. To harden a Kubernetes cluster outside of Rancher's distributions, refer to your Kubernetes provider docs. + +Rancher has the following Kubernetes distributions: + +* RKE +* k3s +* RKE2 + +### Guides + +These guides have been tested along with the Rancher v2.5 release. Each self assessment guide is accompanied with a hardening guide and tested on a specific Kubernetes version and CIS benchmark version. If a CIS benchmark has not been validated for your Kubernetes version, you can choose to use the existing guides until a newer version is added. + + +#### RKE Guides + +Kubernetes Version | CIS Benchmark Version | Self Assessment Guide | Hardening Guides +---|---|---|--- +Kubernetes v1.15+ | CIS v1.5 | [Link](./1.5-benchmark-2.5) | [Link](./1.5-hardening-2.5) + +#### RKE2 Guides + +Kubernetes Version | CIS Benchmark Version | Self Assessment Guide | Hardening Guides +---|---|---|--- +Kubernetes v1.18 | CIS v1.5 | [Link](https://docs.rke2.io/security/cis_self_assessment/) | [Link](https://docs.rke2.io/security/hardening_guide/) From a4ea44bbf7e9d8461997122fa92214d32bbf00a9 Mon Sep 17 00:00:00 2001 From: Ryan Elliott-Smith <49007005+ryanelliottsmith@users.noreply.github.com> Date: Mon, 23 Nov 2020 12:01:02 +1300 Subject: [PATCH 43/58] Remove --reuse-values --- .../installation/upgrades-rollbacks/upgrades/ha/_index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md b/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md index e6ed5656b37..b415647193b 100644 --- a/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md +++ b/content/rancher/v2.x/en/installation/upgrades-rollbacks/upgrades/ha/_index.md @@ -114,12 +114,14 @@ helm upgrade rancher rancher-/rancher \ > **Note:** The above is an example, there may be more values from the previous step that need to be appended. -Alternatively, it's possible to reuse current values and make small changes with the `--reuse-values` flag. For example, to only change the Rancher version: +Alternatively, it's possible to export the current values to a file and reference that file during upgrade. For example, to only change the Rancher version: ``` +helm get values rancher -n cattle-system -o yaml > values.yaml + helm upgrade rancher rancher-/rancher \ --namespace cattle-system \ - --reuse-values \ + -f values.yaml \ --version=2.4.5 ``` From 5e58f77ac3080e4051d365535ce3579f8072dc2c Mon Sep 17 00:00:00 2001 From: scaeloutSean Date: Tue, 24 Nov 2020 00:11:34 +0800 Subject: [PATCH 44/58] Fix typo in mkdir command --- .../behind-proxy/launch-kubernetes/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/launch-kubernetes/_index.md b/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/launch-kubernetes/_index.md index d86e307d6f1..5c73de9021f 100644 --- a/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/launch-kubernetes/_index.md +++ b/content/rancher/v2.x/en/installation/other-installation-methods/behind-proxy/launch-kubernetes/_index.md @@ -42,7 +42,7 @@ sudo usermod -aG docker YOUR_USERNAME And configure the Docker daemon to use the proxy to pull images: ``` -sudo mkdir -p mkdir /etc/systemd/system/docker.service.d +sudo mkdir -p /etc/systemd/system/docker.service.d cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null [Service] Environment="HTTP_PROXY=http://${proxy_host}" From ea073c103d8ae4127721ffb9294860d553b11d2c Mon Sep 17 00:00:00 2001 From: Lucas Ramage Date: Mon, 23 Nov 2020 14:46:30 -0500 Subject: [PATCH 45/58] Fix typos in EKS documentation Resouces -> Resources Follwoing -> Following --- .../hosted-kubernetes-clusters/eks/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md b/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md index d5e7e13ddf0..67e87db0398 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md @@ -339,7 +339,7 @@ Documented here is a minimum set of permissions necessary to use all functionali Resource | Description ---------|------------ Service Role | The service role provides Kubernetes the permissions it requires to manage resources on your behalf. Rancher can create the service role with the following [Service Role Permissions](http://localhost:9001/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#service-role-permissions). -VPC | Provides isolated network resouces utilised by EKS and worker nodes. Rancher can create the VPC resouces with the follwoing [VPC Permissions](http://localhost:9001/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#vpc-permissions). +VPC | Provides isolated network resources utilised by EKS and worker nodes. Rancher can create the VPC resources with the following [VPC Permissions](http://localhost:9001/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#vpc-permissions). Resource targeting uses `*` as the ARN of many of the resources created cannot be known prior to creating the EKS cluster in Rancher. From 3570f205227a3fb9b8f65fa347e026cf16aef6d4 Mon Sep 17 00:00:00 2001 From: cluse Date: Fri, 20 Nov 2020 18:51:09 -0700 Subject: [PATCH 46/58] Fix formatting on monitoring page --- content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md index 451677b3e35..1a1b3001e76 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md @@ -183,4 +183,4 @@ At least 50Gi storage is recommended. # Known Issues -There is a [known issue](https://github.com/rancher/rancher/issues/28787#issuecomment-693611821) that K3s clusters require more default memory. If you are enabling monitoring on a K3s cluster, we recommend to setting `prometheus.prometheusSpec.resources.memory.limit` to 2500Mi` and `prometheus.prometheusSpec.resources.memory.request` to 1750Mi. +There is a [known issue](https://github.com/rancher/rancher/issues/28787#issuecomment-693611821) that K3s clusters require more default memory. If you are enabling monitoring on a K3s cluster, we recommend to setting `prometheus.prometheusSpec.resources.memory.limit` to 2500 Mi and `prometheus.prometheusSpec.resources.memory.request` to 1750 Mi. From f870e043afa3c18145ce45dc4e5242e23a0ee116 Mon Sep 17 00:00:00 2001 From: cluse Date: Mon, 23 Nov 2020 16:34:46 -0700 Subject: [PATCH 47/58] Add docs to persist Grafana dashboards --- .../en/monitoring-alerting/v2.5/_index.md | 4 +-- .../v2.5/persist-grafana/_index.md | 35 +++++++++++++++++++ .../monitoring-alerting/v2.5/rbac/_index.md | 4 +-- 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md index 451677b3e35..c400373f455 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/_index.md @@ -105,6 +105,8 @@ Rancher allows any users who are authenticated by Kubernetes and have access the However, users can choose to log in to Grafana as an [Admin](https://grafana.com/docs/grafana/latest/permissions/organization_roles/#admin-role) if necessary. The default Admin username and password for the Grafana instance will be `admin`/`prom-operator`, but alternative credentials can also be supplied on deploying or upgrading the chart. +> **Persistent Dashboards:** To allow the Grafana dashboard to persist after it restarts, add the dashboard configuration JSON into a ConfigMap. ConfigMaps also allow the dashboards to be deployed with a GitOps or CD based approach. This allows the dashboard to be put under version control. For details, refer to [this section.](./persist-grafana) + To see the Grafana UI, install `rancher-monitoring`. Then go to the **Cluster Explorer.** In the top left corner, click **Cluster Explorer > Monitoring.** Then click **Grafana.
Cluster Compute Resources Dashboard in Grafana
@@ -113,8 +115,6 @@ To see the Grafana UI, install `rancher-monitoring`. Then go to the **Cluster Ex
Default Dashboards in Grafana
![Default Dashboards in Grafana]({{}}/img/rancher/grafana-default-dashboard.png) -To allow the Grafana dashboard to persist after it restarts, you will need to add the configuration JSON into a ConfigMap. You can add this configuration to the ConfigMap using the Rancher UI. - ### Prometheus UI To see the Prometheus UI, install `rancher-monitoring`. Then go to the **Cluster Explorer.** In the top left corner, click **Cluster Explorer > Monitoring.** Then click **Prometheus Graph.** diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md new file mode 100644 index 00000000000..6ecf2b516e5 --- /dev/null +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md @@ -0,0 +1,35 @@ +--- +title: Persistent Grafana Dashboards +weight: 4 +--- + +To allow the Grafana dashboard to persist after the Grafana instance restarts, add the dashboard configuration JSON into a ConfigMap. ConfigMaps also allow the dashboards to be deployed with a GitOps or CD based approach. This allows the dashboard to be put under version control. + +> **Prerequisites:** +> +> - The monitoring application needs to be installed. +> - You must have the cluster-admin ClusterRole permission. + +1. Open the Grafana dashboard. From the **Cluster Explorer,** click **Cluster Explorer > Monitoring.** +1. Log in to Grafana. Note: The default Admin username and password for the Grafana instance is `admin/prom-operator`. (Regardless of who has the password, cluster administrator permission in Rancher is still required access the Grafana instance.) Alternative credentials can also be supplied on deploying or upgrading the chart. +1. Go to the dashboard that you want to persist. In the top navigation menu, go to the dashboard settings by clicking the gear icon. +1. In the left navigation menu, click **JSON Model.** +1. Copy the JSON data structure that appears. +1. Create a ConfigMap in the `cattle-dashboards` namespace. The ConfigMap needs to have the label `grafana_dashboard: "1"`. Paste the JSON into the ConfigMap in the format shown in the example below: + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + labels: + grafana_dashboard: "1" + name: + namespace: cattle-dashboards + data: + .json: |- + + ``` + +**Result:** After the ConfigMap is created, it should show up on the Grafana UI and be persisted even if the Grafana pod is restarted. + +Dashboards that are persisted using ConfigMaps cannot be deleted from the Grafana UI. If you attempt to delete the dashboard in the Grafana UI, you will see the error message "Dashboard cannot be deleted because it was provisioned." To delete the dashboard, you will need to delete the ConfigMap. diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/rbac/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/rbac/_index.md index 14d2b1bcb16..df44189e67d 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.5/rbac/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/rbac/_index.md @@ -49,7 +49,7 @@ Only those with the the cluster-admin / admin / edit `ClusterRole` should be abl Only those with who have some k8s `ClusterRole` should be able to: - View the configuration of Prometheuses that are deployed within the cluster -- View the configuraiton of Alertmanagers that are deployed within the cluster +- View the configuration of Alertmanagers that are deployed within the cluster - View the scrape configuration of Prometheus deployments via ServiceMonitor and PodMonitor CRs - View the alerting / recording rules of a Prometheus deployment via PrometheusRules CRs @@ -96,5 +96,5 @@ If cluster-admins would like to provide additional admin/edit access to users ou | k8s Resources | Namespace | Can it cause impact outside of a namespace / project? | Impact | |----------------------------| ------| ------| ----------------------------| -|
  • `secrets`
  • `configmaps`
| `cattle-monitoring-system` | Yes, Configs and Secrets in this namespace can impact the entire monitoring / alerting pipeline. | User will be able to create or edit Secrets / ConfigMaps such as the Alertmanager Config, Prometheus Adapter Config, TLS secrets, additional Grafana datasoruces, etc. This can have broad impact on all cluster monitoring / alerting. | +|
  • `secrets`
  • `configmaps`
| `cattle-monitoring-system` | Yes, Configs and Secrets in this namespace can impact the entire monitoring / alerting pipeline. | User will be able to create or edit Secrets / ConfigMaps such as the Alertmanager Config, Prometheus Adapter Config, TLS secrets, additional Grafana datasources, etc. This can have broad impact on all cluster monitoring / alerting. | |
  • `secrets`
  • `configmaps`
| `cattle-dashboards` | Yes, Configs and Secrets in this namespace can create dashboards that make queries on all metrics collected at a cluster-level. | User will be able to create Secrets / ConfigMaps that persist new Grafana Dashboards only. | From 11ef0e90a531ed6dec261106600cbcad2e746097 Mon Sep 17 00:00:00 2001 From: cluse Date: Tue, 24 Nov 2020 11:28:23 -0700 Subject: [PATCH 48/58] Add redirect for registries page --- content/rancher/v2.x/en/k8s-in-rancher/registries/_index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/k8s-in-rancher/registries/_index.md b/content/rancher/v2.x/en/k8s-in-rancher/registries/_index.md index 5c8c35b4a88..4513ec0a212 100644 --- a/content/rancher/v2.x/en/k8s-in-rancher/registries/_index.md +++ b/content/rancher/v2.x/en/k8s-in-rancher/registries/_index.md @@ -4,7 +4,8 @@ description: Learn about the Docker registry and Kubernetes registry, their use weight: 3063 aliases: - /rancher/v2.x/en/tasks/projects/add-registries/ - - /rancher/v2.x/en/k8s-in-rancher/registries + - /rancher/v2.x/en/k8s-in-rancher/registries + - /rancher/v2.x/en/k8s-resources/k8s-in-rancher/registries --- Registries are Kubernetes secrets containing credentials used to authenticate with [private Docker registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). From 5a54a8adc1527fc95717b4e36e1dc88c4e8788bc Mon Sep 17 00:00:00 2001 From: Ryan Elliott-Smith <49007005+ryanelliottsmith@users.noreply.github.com> Date: Wed, 25 Nov 2020 09:50:06 +1300 Subject: [PATCH 49/58] Fix hyperlinks in eks doc --- .../hosted-kubernetes-clusters/eks/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md b/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md index 67e87db0398..80bd0052162 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/_index.md @@ -338,8 +338,8 @@ Documented here is a minimum set of permissions necessary to use all functionali Resource | Description ---------|------------ -Service Role | The service role provides Kubernetes the permissions it requires to manage resources on your behalf. Rancher can create the service role with the following [Service Role Permissions](http://localhost:9001/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#service-role-permissions). -VPC | Provides isolated network resources utilised by EKS and worker nodes. Rancher can create the VPC resources with the following [VPC Permissions](http://localhost:9001/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#vpc-permissions). +Service Role | The service role provides Kubernetes the permissions it requires to manage resources on your behalf. Rancher can create the service role with the following [Service Role Permissions]({{}}/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#service-role-permissions). +VPC | Provides isolated network resources utilised by EKS and worker nodes. Rancher can create the VPC resources with the following [VPC Permissions]({{}}/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/eks/#vpc-permissions). Resource targeting uses `*` as the ARN of many of the resources created cannot be known prior to creating the EKS cluster in Rancher. From ea5dc8cda4efaed5e8e5a88c94f1ebdd941cd4c9 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Tue, 24 Nov 2020 14:02:27 -0700 Subject: [PATCH 50/58] Fix grafana dashboard ConfigMap label indentation --- .../v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md index 6ecf2b516e5..78234fd30d2 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md @@ -22,7 +22,7 @@ To allow the Grafana dashboard to persist after the Grafana instance restarts, a kind: ConfigMap metadata: labels: - grafana_dashboard: "1" + grafana_dashboard: "1" name: namespace: cattle-dashboards data: From 051e9e9f8e95325d033c22b2c560857dc6548957 Mon Sep 17 00:00:00 2001 From: Frits Date: Tue, 24 Nov 2020 19:31:11 -0800 Subject: [PATCH 51/58] Update _index.md --- content/k3s/latest/en/installation/network-options/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/k3s/latest/en/installation/network-options/_index.md b/content/k3s/latest/en/installation/network-options/_index.md index eaac4ea818e..97873e4151b 100644 --- a/content/k3s/latest/en/installation/network-options/_index.md +++ b/content/k3s/latest/en/installation/network-options/_index.md @@ -40,7 +40,7 @@ Apply the Canal YAML. Ensure the settings were applied by running the following command on the host: ``` -cat /etc/cni/net.d/10-calico.conflist +cat /etc/cni/net.d/10-canal.conflist ``` You should see that IP forwarding is set to true. @@ -61,7 +61,7 @@ Apply the Calico YAML. Ensure the settings were applied by running the following command on the host: ``` -cat /etc/cni/net.d/10-canal.conflist +cat /etc/cni/net.d/10-calico.conflist ``` You should see that IP forwarding is set to true. From ca3952f5ebbab6368b03e204d1bc5018531214eb Mon Sep 17 00:00:00 2001 From: cluse Date: Wed, 25 Nov 2020 13:22:57 -0700 Subject: [PATCH 52/58] Replace tab with spaces --- .../v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md b/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md index 78234fd30d2..d0d8823ca2c 100644 --- a/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md +++ b/content/rancher/v2.x/en/monitoring-alerting/v2.5/persist-grafana/_index.md @@ -22,7 +22,7 @@ To allow the Grafana dashboard to persist after the Grafana instance restarts, a kind: ConfigMap metadata: labels: - grafana_dashboard: "1" + grafana_dashboard: "1" name: namespace: cattle-dashboards data: From 346ba301a57e4d5b7ca09c370ddc1cfeacd08a44 Mon Sep 17 00:00:00 2001 From: Eugen Stan Date: Thu, 26 Nov 2020 11:35:58 +0200 Subject: [PATCH 53/58] Use newer klipper-helm image Fixes https://github.com/k3s-io/helm-controller/issues/79 --- content/k3s/latest/en/helm/_index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/k3s/latest/en/helm/_index.md b/content/k3s/latest/en/helm/_index.md index 5a41c5f85ff..574c36d6c66 100644 --- a/content/k3s/latest/en/helm/_index.md +++ b/content/k3s/latest/en/helm/_index.md @@ -60,6 +60,7 @@ spec: | spec.helmVersion | v3 | Helm version to use (`v2` or `v3`) | | | spec.bootstrap | False | Set to True if this chart is needed to bootstrap the cluster (Cloud Controller Manager, etc) | | | spec.set | | Override simple default Chart values. These take precedence over options set via valuesContent. | `--set` / `--set-string` | +| spec.jobImage | | Specify the image to use when installing the helm chart. E.g. rancher/klipper-helm:v0.3.0 . | | | spec.valuesContent | | Override complex default Chart values via YAML file content | `--values` | | spec.chartContent | | Base64-encoded chart archive .tgz - overrides spec.chart | CHART | From 15dca4fe059a7d7a483afd2349ba055753fa437d Mon Sep 17 00:00:00 2001 From: Olivier Bondu Date: Fri, 27 Nov 2020 19:05:03 +0100 Subject: [PATCH 54/58] Update _index.md --- content/k3s/latest/en/installation/airgap/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/k3s/latest/en/installation/airgap/_index.md b/content/k3s/latest/en/installation/airgap/_index.md index 56d16c1b2e9..93aed208fab 100644 --- a/content/k3s/latest/en/installation/airgap/_index.md +++ b/content/k3s/latest/en/installation/airgap/_index.md @@ -33,7 +33,7 @@ sudo mkdir -p /var/lib/rancher/k3s/agent/images/ sudo cp ./k3s-airgap-images-$ARCH.tar /var/lib/rancher/k3s/agent/images/ ``` -Place the k3s binary at /usr/local/bin/k3s and ensure it is executable. +Place the k3s binary at `/usr/local/bin/k3s` and ensure it is executable. Follow the steps in the next section to install K3s. From 8345d274492e2796a62f69793810f0ca1e5b41db Mon Sep 17 00:00:00 2001 From: cluse Date: Tue, 1 Dec 2020 19:52:22 -0700 Subject: [PATCH 55/58] Edit landing page for Rancher v2.5 security guides --- .../v2.x/en/security/rancher-2.5/_index.md | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/content/rancher/v2.x/en/security/rancher-2.5/_index.md b/content/rancher/v2.x/en/security/rancher-2.5/_index.md index 8640b28ec10..49918270c93 100644 --- a/content/rancher/v2.x/en/security/rancher-2.5/_index.md +++ b/content/rancher/v2.x/en/security/rancher-2.5/_index.md @@ -3,27 +3,32 @@ title: Rancher v2.5 weight: 1 --- -For Rancher v2.5, the guides are organized differntly than previous guides. Since Rancher v2.5 can be deployed on any Kubernetes cluster, the guides are broken up based on Rancher's Kubernetes distributions. To harden a Kubernetes cluster outside of Rancher's distributions, refer to your Kubernetes provider docs. +Rancher v2.5 introduced the capability to deploy Rancher on any Kubernetes cluster. For that reason, we now provide separate security hardening guides for Rancher deployments on each of Rancher's Kubernetes distributions. Rancher has the following Kubernetes distributions: -* RKE -* k3s -* RKE2 +- [**RKE,**](https://rancher.com/docs/rke/latest/en/) Rancher Kubernetes Engine, is a CNCF-certified Kubernetes distribution that runs entirely within Docker containers. +- [**K3s,**]({{}}/k3s/latest/en/) Lightweight Kubernetes, is easy to install, with half the memory of upstream Kubernetes, all in a binary of less than 100 MB. +- [**RKE2**](https://docs.rke2.io/) is a fully conformant Kubernetes distribution that focuses on security and compliance within the U.S. Federal Government sector. -### Guides +To harden a Kubernetes cluster outside of Rancher's distributions, refer to your Kubernetes provider docs. + +# Guides These guides have been tested along with the Rancher v2.5 release. Each self assessment guide is accompanied with a hardening guide and tested on a specific Kubernetes version and CIS benchmark version. If a CIS benchmark has not been validated for your Kubernetes version, you can choose to use the existing guides until a newer version is added. - -#### RKE Guides +### RKE Guides Kubernetes Version | CIS Benchmark Version | Self Assessment Guide | Hardening Guides ---|---|---|--- Kubernetes v1.15+ | CIS v1.5 | [Link](./1.5-benchmark-2.5) | [Link](./1.5-hardening-2.5) -#### RKE2 Guides +### RKE2 Guides Kubernetes Version | CIS Benchmark Version | Self Assessment Guide | Hardening Guides ---|---|---|--- Kubernetes v1.18 | CIS v1.5 | [Link](https://docs.rke2.io/security/cis_self_assessment/) | [Link](https://docs.rke2.io/security/hardening_guide/) + +### K3s Guides + +The K3s security guides will be added soon. From c906228c71c66e2f51fe3b4ead95a8ff0e50b5ec Mon Sep 17 00:00:00 2001 From: cluse Date: Tue, 1 Dec 2020 20:10:16 -0700 Subject: [PATCH 56/58] Minor edits --- content/rancher/v2.x/en/security/rancher-2.5/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/security/rancher-2.5/_index.md b/content/rancher/v2.x/en/security/rancher-2.5/_index.md index 49918270c93..4b12b4458b6 100644 --- a/content/rancher/v2.x/en/security/rancher-2.5/_index.md +++ b/content/rancher/v2.x/en/security/rancher-2.5/_index.md @@ -7,8 +7,8 @@ Rancher v2.5 introduced the capability to deploy Rancher on any Kubernetes clust Rancher has the following Kubernetes distributions: -- [**RKE,**](https://rancher.com/docs/rke/latest/en/) Rancher Kubernetes Engine, is a CNCF-certified Kubernetes distribution that runs entirely within Docker containers. -- [**K3s,**]({{}}/k3s/latest/en/) Lightweight Kubernetes, is easy to install, with half the memory of upstream Kubernetes, all in a binary of less than 100 MB. +- [**RKE,**]({{}}/rke/latest/en/) Rancher Kubernetes Engine, is a CNCF-certified Kubernetes distribution that runs entirely within Docker containers. +- [**K3s,**]({{}}/k3s/latest/en/) is a fully conformant, lightweight Kubernetes distribution. It is easy to install, with half the memory of upstream Kubernetes, all in a binary of less than 100 MB. - [**RKE2**](https://docs.rke2.io/) is a fully conformant Kubernetes distribution that focuses on security and compliance within the U.S. Federal Government sector. To harden a Kubernetes cluster outside of Rancher's distributions, refer to your Kubernetes provider docs. From 847d603a2b0f08d9ecf8df09b398b85acac93250 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Wed, 2 Dec 2020 10:47:49 -0700 Subject: [PATCH 57/58] Fix typo --- .../en/istio/v2.5/setup/deploy-workloads/_index.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md b/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md index 79fcdfe69bf..19bf73c3a11 100644 --- a/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md +++ b/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md @@ -18,13 +18,13 @@ Wait a few minutes for the workload to upgrade to have the istio sidecar. Click There are a few ways to add new **Deployments** in your namespace -1. From the **Cluster Explorer** click on Workload > Overview -1. Click **Create** -1. Select **Deployment** from the various workload options -1. Fill out the form, or **Edit as Yaml** -1. Click **Create** +1. From the **Cluster Explorer** click on **Workload > Overview.** +1. Click **Create.** +1. Select **Deployment** from the various workload options. +1. Fill out the form, or **Edit as Yaml.** +1. Click **Create.** -Alternatively, you can select the specific workload you want to deploy from worklod > specific workload and create from there. +Alternatively, you can select the specific workload you want to deploy from the **Workload** section of the left navigation bar and create it from there. To add a **Service** to your namespace From ddda2168c88381b79548fa1ba0b10438412fda96 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Wed, 2 Dec 2020 13:10:40 -0700 Subject: [PATCH 58/58] Fix typo and link --- content/rancher/v2.x/en/istio/v2.5/setup/_index.md | 2 +- .../v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md | 2 +- content/rancher/v2.x/en/istio/v2.5/setup/gateway/_index.md | 2 +- .../en/istio/v2.5/setup/set-up-traffic-management/_index.md | 2 +- .../rancher/v2.x/en/istio/v2.5/setup/view-traffic/_index.md | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/content/rancher/v2.x/en/istio/v2.5/setup/_index.md b/content/rancher/v2.x/en/istio/v2.5/setup/_index.md index f7237953385..eb9801f192b 100644 --- a/content/rancher/v2.x/en/istio/v2.5/setup/_index.md +++ b/content/rancher/v2.x/en/istio/v2.5/setup/_index.md @@ -27,4 +27,4 @@ The workloads and services that you want to be controlled by Istio must meet [Is 1. [Add deployments and services that have the Istio sidecar injected.]({{}}/rancher/v2.x/en/cluster-admin/tools/istio/setup/deploy-workloads) 1. [Set up the Istio gateway. ]({{}}/rancher/v2.x/en/cluster-admin/tools/istio/setup/gateway) 1. [Set up Istio's components for traffic management.]({{}}/rancher/v2.x/en/cluster-admin/tools/istio/setup/set-up-traffic-management) -1. [Generate traffic and see Istio in action.](#generate-traffic-and-see-istio-in-action) +1. [Generate traffic and see Istio in action.]({{}}/rancher/v2.x/en/istio/v2.5/setup/view-traffic/ ) diff --git a/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md b/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md index 19bf73c3a11..6d1a6995bcd 100644 --- a/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md +++ b/content/rancher/v2.x/en/istio/v2.5/setup/deploy-workloads/_index.md @@ -1,5 +1,5 @@ --- -title: 4. Add Deployments and Services with the Istio Sidecar +title: 3. Add Deployments and Services with the Istio Sidecar weight: 4 aliases: - /rancher/v2.x/en/cluster-admin/tools/istio/setup/deploy-workloads diff --git a/content/rancher/v2.x/en/istio/v2.5/setup/gateway/_index.md b/content/rancher/v2.x/en/istio/v2.5/setup/gateway/_index.md index 502dd76f48a..31c61d355e6 100644 --- a/content/rancher/v2.x/en/istio/v2.5/setup/gateway/_index.md +++ b/content/rancher/v2.x/en/istio/v2.5/setup/gateway/_index.md @@ -1,5 +1,5 @@ --- -title: 5. Set up the Istio Gateway +title: 4. Set up the Istio Gateway weight: 5 aliases: - /rancher/v2.x/en/cluster-admin/tools/istio/setup/gateway diff --git a/content/rancher/v2.x/en/istio/v2.5/setup/set-up-traffic-management/_index.md b/content/rancher/v2.x/en/istio/v2.5/setup/set-up-traffic-management/_index.md index e2449894cb6..f492fc33aa2 100644 --- a/content/rancher/v2.x/en/istio/v2.5/setup/set-up-traffic-management/_index.md +++ b/content/rancher/v2.x/en/istio/v2.5/setup/set-up-traffic-management/_index.md @@ -1,5 +1,5 @@ --- -title: 6. Set up Istio's Components for Traffic Management +title: 5. Set up Istio's Components for Traffic Management weight: 6 aliases: - /rancher/v2.x/en/cluster-admin/tools/istio/setup/set-up-traffic-management diff --git a/content/rancher/v2.x/en/istio/v2.5/setup/view-traffic/_index.md b/content/rancher/v2.x/en/istio/v2.5/setup/view-traffic/_index.md index 15325d222d2..01b6687ebab 100644 --- a/content/rancher/v2.x/en/istio/v2.5/setup/view-traffic/_index.md +++ b/content/rancher/v2.x/en/istio/v2.5/setup/view-traffic/_index.md @@ -1,5 +1,5 @@ --- -title: 7. Generate and View Traffic +title: 6. Generate and View Traffic weight: 7 aliases: - /rancher/v2.x/en/cluster-admin/tools/istio/setup/view-traffic @@ -10,7 +10,7 @@ This section describes how to view the traffic that is being managed by Istio. # The Kiali Traffic Graph -The Istio overpage provides a link to the Kiali dashboard. From the Kiali dashboard, you are able to view graphs for each namespace. The Kiali graph provides a powerful way to visualize the topology of your Istio service mesh. It shows you which services communicate with each other. +The Istio overview page provides a link to the Kiali dashboard. From the Kiali dashboard, you are able to view graphs for each namespace. The Kiali graph provides a powerful way to visualize the topology of your Istio service mesh. It shows you which services communicate with each other. >**Prerequisite:** To enable traffic to show up in the graph, ensure you have prometheus installed in the cluster. Rancher-istio installs Kiali configured by default to work with the rancher-monitoring chart. You can use rancher-monitoring or install your own monitoring solution. Optional: you can change configuration on how data scraping occurs by setting the [Selectors & Scrape Configs]({{}}/rancher/v2.x/en/istio/setup/enable-istio-in-cluster/#selectors-scrape-configs) options. @@ -19,7 +19,7 @@ To see the traffic graph, 1. From the **Cluster Explorer**, select **Istio** from the nav dropdown. 1. Click the **Kiali** link on the Istio **Overview** page. 1. Click on **Graph** in the side nav. -1. Change the namespace in the **Namesace** dropdown to view the traffic for each namespace. +1. Change the namespace in the **Namespace** dropdown to view the traffic for each namespace. If you refresh the URL to the BookInfo app several times, you should be able to see green arrows on the Kiali graph showing traffic to `v1` and `v3` of the `reviews` service. The control panel on the right side of the graph lets you configure details including how many minutes of the most recent traffic should be shown on the graph.