From d5b46dabe342aacd27e1920944afb81c3cb3f2a2 Mon Sep 17 00:00:00 2001 From: niusmallnan Date: Wed, 31 Jul 2019 14:36:24 +0800 Subject: [PATCH 01/25] RancherOS: caching imags when installing to disk --- .../server/install-to-disk/_index.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md b/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md index 86c83c842d5..29f7bbd647a 100644 --- a/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md +++ b/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md @@ -82,6 +82,22 @@ rancher/os:v0.5.0 remote Alternatively, you can set the installer image to any image in System Docker to install RancherOS. This is particularly useful for machines that will not have direct access to the internet. +#### Caching Images + +_Available as of v1.5.3_ + +Sometimes, some of the configurations included in cloud-config require additional docker images support. These images are typically downloaded automatically by RancherOS when booting after installation. These configurations can be: + +- rancher.services_include +- rancher.console +- rancher.docker + +If you want to download and save these images to disk during installation, they will be loaded automatically when booting next time. You can add `-s` when using `ros install`: + +``` +$ ros install -d -c -s +``` + ### SSH into RancherOS After installing RancherOS, you can ssh into RancherOS using your private key and the **rancher** user. From 26f580e1a6b178d7c5a4ca75aba1ad7f22ca5148 Mon Sep 17 00:00:00 2001 From: niusmallnan Date: Fri, 16 Aug 2019 17:26:36 +0800 Subject: [PATCH 02/25] RancherOS: add aliyun usage doc --- .../installation/running-rancheros/_index.md | 6 ++++ .../running-rancheros/cloud/aliyun/_index.md | 32 ++++++++++++++++++ static/img/os/RancherOS_aliyun1.jpg | Bin 0 -> 91532 bytes static/img/os/RancherOS_aliyun2.jpg | Bin 0 -> 84365 bytes 4 files changed, 38 insertions(+) create mode 100644 content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md create mode 100644 static/img/os/RancherOS_aliyun1.jpg create mode 100644 static/img/os/RancherOS_aliyun2.jpg diff --git a/content/os/v1.x/en/installation/running-rancheros/_index.md b/content/os/v1.x/en/installation/running-rancheros/_index.md index 4c8b2845a1f..c677f71c35e 100644 --- a/content/os/v1.x/en/installation/running-rancheros/_index.md +++ b/content/os/v1.x/en/installation/running-rancheros/_index.md @@ -24,6 +24,12 @@ RancherOS runs on virtualization platforms, cloud providers and bare metal serve [Azure]({{< baseurl >}}/os/v1.x/en/installation/running-rancheros/cloud/azure) +[OpenStack]({{< baseurl >}}/os/v1.x/en/installation/running-rancheros/cloud/openstack) + +[VMware ESXi]({{< baseurl >}}/os/v1.x/en/installation/running-rancheros/cloud/vmware-esxi) + +[Aliyun]({{< baseurl >}}/os/v1.x/en/installation/running-rancheros/cloud/aliyun) + #### Bare Metal & Virtual Servers [PXE]({{< baseurl >}}/os/v1.x/en/installation/running-rancheros/server/pxe) diff --git a/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md b/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md new file mode 100644 index 00000000000..53538461cd9 --- /dev/null +++ b/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md @@ -0,0 +1,32 @@ +--- +title: Aliyun +weight: 111 +--- + +### Adding the RancherOS Image into Aliyun + +RancherOS is available as an image in Aliyun, and can be easily run in Elastic Compute Service (ECS). Let’s walk through how to upload ECS image. + +1. Download the most recent RancherOS image. The image can be found in the [release artifacts](https://github.com/rancher/os/releases). It is a `rancheros-aliyun.vhd` file. +2. Follow Aliyun's instructions on how to [upload the image](https://help.aliyun.com/document_detail/127285.html). The image must be uploaded into a OSS bucket before it can be added. +3. Once the image is added to your ECS, we can start creating new instances! + +Here is a screenshot we can refer to: + +![RancherOS on Aliyun 1]({{< baseurl >}}/img/os/RancherOS_aliyun1.jpg) + +Please note these options: + +- Root disk size, it should be greater than 10GB and kept same as the value when booting an instance. +- Platform, it must be `Others Linux` +- Image Format, it must be `VHD` + +### Launching RancherOS using Aliyun Console + +After the image is uploaded, we can use the `Aliyun Console` to start a new instance. Currently RancherOS on Aliyun only supports ssh key access, so we need to fill it out in the console. + +Since the image is private, we need to use the `Custom Images`. + +![RancherOS on Aliyun 2]({{< baseurl >}}/img/os/RancherOS_aliyun2.jpg) + +After the instance is successfully started, we can login with the `rancher` user via SSH. diff --git a/static/img/os/RancherOS_aliyun1.jpg b/static/img/os/RancherOS_aliyun1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cc8c5c0d903606339412573c3a14ae1f34c0789 GIT binary patch literal 91532 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 pkPhIKMP%}ed%}JNVVl`1| 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 Date: Fri, 23 Aug 2019 11:24:18 -0700 Subject: [PATCH 03/25] Add information for cert-manager Problem: cert-manager is old and will be cut off soon Solution: Update docs to include current install instructions and instructions on how to upgrade cert-manager to the current version --- .../upgrade-cert-manager-airgap/_index.md | 92 +++++++++++++++++++ .../upgrade-cert-manager/_index.md | 47 ++++++++++ .../install-rancher/_index.md | 33 +++++-- .../prepare-private-registry/_index.md | 4 +- .../en/installation/ha/helm-rancher/_index.md | 40 ++++++-- .../ha-server-upgrade-helm-airgap/_index.md | 2 + .../upgrades/ha-server-upgrade-helm/_index.md | 4 + 7 files changed, 206 insertions(+), 16 deletions(-) create mode 100644 content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md create mode 100644 content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md diff --git a/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md b/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md new file mode 100644 index 00000000000..ddf7ee9e99d --- /dev/null +++ b/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md @@ -0,0 +1,92 @@ +--- +title: Upgrade Cert-manager Airgap +weight: 2040 +--- + +[Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow these instructions: + +>**Note:** The namespaces used in these instructions depends on the namespace cert-manager is currently installed in. If it is in kube-system use that in the instructions below. You can verify by running `kubectl get pods --all-namespaces` and checking which namespace the cert-manager-* pods are listed in. Do not change the namespace cert-manager is running in or this can cause issues. + +## Prerequisites + +- **Populate Images** + + Follow the guide to [Prepare the Private Registry]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-installation/prepare-private-reg/) with the images for the upgrade Rancher release. + +- **Prepare cert-manager** + +1. From a system connected to the internet, add the cert-manager repo to helm + + ```plain + helm repo add jetstack https://charts.jetstack.io + helm repo update + ``` + +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.9.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-v0.9.1.tgz --output-dir . \ + --name cert-manager --namespace kube-system \ + --set image.repository=/quay.io/jetstack/cert-manager-controller + ``` + +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.9/deploy/manifests/00-crds.yaml + ``` + +## Install cert-manager + +1. Back up existing resources as a precaution + + ```plain + kubectl get -o yaml --all-namespaces issuer,clusterissuer,certificates > cert-manager-backup.yaml + ``` + +1. Delete the existing deployment + + ```plain + helm delete --purge cert-manager + ``` + +1. Install the CustomResourceDefinition resources separately + + ```plain + kubectl apply -f cert-manager/cert-manager-crd.yaml + ``` + +1. Label the kube-system namespace to disable resource validation + + ```plain + kubectl label namespace kube-system certmanager.k8s.io/disable-validation=true + ``` + +1. Install cert-manager + + ```plain + kubectl -n kube-system apply -R -f ./cert-manager + ``` + +Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the kube-system namespace for running pods: + +``` +kubectl get pods --namespace kube-system + +NAME READY STATUS RESTARTS AGE +cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m +cert-manager-webhook-5b5dd6999-kst4x 1/1 Running 0 3m +cert-manager-cainjector-3ba5cd2bcd-de332x 1/1 Running 0 3m +``` + +If the ‘webhook’ pod (2nd line) is in a ContainerCreating state, it may still be waiting for the Secret to be mounted into the pod. Wait a couple of minutes for this to happen but if you experience problems, please check the [troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html) guide. + +[Additional information on the annotation.](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.4-0.5.html?highlight=certmanager.k8s.io%2Fdisable-validation#disabling-resource-validation-on-the-cert-manager-namespace) + +[Additional information on the webhook feature.](https://docs.cert-manager.io/en/latest/getting-started/webhook.html) \ No newline at end of file diff --git a/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md b/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md new file mode 100644 index 00000000000..70a59798003 --- /dev/null +++ b/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md @@ -0,0 +1,47 @@ +--- +title: Upgrade Cert-manager +weight: 2040 +--- + +[Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow these instructions: + + +``` +# Back up existing resources as a precaution +kubectl get -o yaml --all-namespaces issuer,clusterissuer,certificates > cert-manager-backup.yaml + +# Delete the existing deployment +helm delete --purge cert-manager + +# Install the CustomResourceDefinition resources separately +kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml + +# Label the kube-system namespace to disable resource validation +kubectl label namespace kube-system certmanager.k8s.io/disable-validation=true + +# Add the Jetstack Helm repository +helm repo add jetstack https://charts.jetstack.io + +# Update your local Helm chart repository cache +helm repo update + +# Install the new version of cert-manager +helm install --version 0.9.1 --name cert-manager --namespace kube-system jetstack/cert-manager +``` + +Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the kube-system namespace for running pods: + +``` +kubectl get pods --namespace kube-system + +NAME READY STATUS RESTARTS AGE +cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m +cert-manager-webhook-5b5dd6999-kst4x 1/1 Running 0 3m +cert-manager-cainjector-3ba5cd2bcd-de332x 1/1 Running 0 3m +``` + +If the ‘webhook’ pod (2nd line) is in a ContainerCreating state, it may still be waiting for the Secret to be mounted into the pod. Wait a couple of minutes for this to happen but if you experience problems, please check the [troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html) guide. + +[Additional information on the annotation.](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.4-0.5.html?highlight=certmanager.k8s.io%2Fdisable-validation#disabling-resource-validation-on-the-cert-manager-namespace) + +[Additional information on the webhook feature.](https://docs.cert-manager.io/en/latest/getting-started/webhook.html) \ No newline at end of file diff --git a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md index b6d09e42324..09174cdaa08 100644 --- a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md @@ -52,23 +52,43 @@ Based on the choice your made in [B. Choose your SSL Configuration](#b-optional- In this section you will configure your cert manager and private registry in the Rancher template. {{% accordion id="self-signed" label="Option A: Default Self-Signed Certificate" %}} -By default, Rancher generates a CA and uses cert manager to issue the certificate for access to the Rancher server interface. +By default, Rancher generates a CA and uses cert-manger to issue the certificate for access to the Rancher server interface. -1. From a system connected to the internet, fetch the latest cert-manager chart available from the [official Helm chart repository](https://github.com/helm/charts/tree/master/stable). +1. From a system connected to the internet, add the cert-manager repo to helm ```plain - helm fetch stable/cert-manager --version 0.5.2 + helm repo add jetstack https://charts.jetstack.io + helm repo update + ``` + +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.9.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-v0.5.2.tgz --output-dir . \ - --name cert-manager --namespace kube-system \ + helm template ./cert-manager-v0.9.1.tgz --output-dir . \ + --name cert-manager --namespace cert-manager \ --set image.repository=/quay.io/jetstack/cert-manager-controller ``` +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.9/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. To configure Rancher to use your private registry when starting the `rancher/rancher` container, use the `CATTLE_SYSTEM_DEFAULT_REGISTRY` variable. You can set the the extra environment variable `extraEnv` to use the same `name` and `value` keys as the container manifest definitions. Remember to quote the values: + + Placeholder | Description + ------------|------------- + `` | The version number of the output tarball. + `` | The DNS name you pointed at your load balancer. + `` | The DNS name for your private registry.). + ```plain helm template ./rancher-.tgz --output-dir . \ @@ -127,7 +147,8 @@ Use `kubectl` to create namespaces and apply the rendered manifests. If you are using self-signed certificates, install cert-manager: ```plain -kubectl -n kube-system apply -R -f ./cert-manager +kubectl apply -f cert-manager/cert-manager-crd.yaml +kubectl -n cert-manager apply -R -f ./cert-manager ``` Install rancher: diff --git a/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md b/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md index d02f1385b1e..22b18c3e6a1 100644 --- a/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md +++ b/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md @@ -50,7 +50,9 @@ Start by collecting all the images needed to install Rancher in an air gap envir 1. Fetch the latest `cert-manager` Helm chart and parse the template for image details. ```plain - helm fetch stable/cert-manager --version 0.5.2 + helm repo add jetstack https://charts.jetstack.io + helm repo update + helm fetch jetstack/cert-manager --version v0.9.1 helm template ./cert-manager-.tgz | grep -oP '(?<=image: ").*(?=")' >> ./rancher-images.txt ``` diff --git a/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md index 0e97eb52adc..779aed80ae5 100644 --- a/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md @@ -37,26 +37,48 @@ There are three recommended options for the source of the certificate. > **Important:** Due to an issue with Helm v2.12.0 and cert-manager, please use Helm v2.12.1 or higher. -Rancher relies on [cert-manager](https://github.com/kubernetes/charts/tree/master/stable/cert-manager) version v0.5.2 from the official Kubernetes Helm chart repository to issue certificates from Rancher's own generated CA or to request Let's Encrypt certificates. +Rancher relies on [cert-manager](https://github.com/jetstack/cert-manager) to issue certificates from Rancher's own generated CA or to request Let's Encrypt certificates. +[These instructions come from cert-manager's official docs.](https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html#installing-with-helm) -Install `cert-manager` from Kubernetes Helm chart repository. ``` -helm install stable/cert-manager \ +# Install the CustomResourceDefinition resources separately +kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml + +# Create the namespace for cert-manager +kubectl create namespace cert-manager + +# Label the cert-manager namespace to disable resource validation +kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true + +# Add the Jetstack Helm repository +helm repo add jetstack https://charts.jetstack.io + +# Update your local Helm chart repository cache +helm repo update + +# Install the cert-manager Helm chart +helm install \ --name cert-manager \ - --namespace kube-system \ - --version v0.5.2 + --namespace cert-manager \ + --version v0.9.1 \ + jetstack/cert-manager ``` -Wait for `cert-manager` to be rolled out: +Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the cert-manager namespace for running pods: ``` -kubectl -n kube-system rollout status deploy/cert-manager -Waiting for deployment "cert-manager" rollout to finish: 0 of 1 updated replicas are available... -deployment "cert-manager" successfully rolled out +kubectl get pods --namespace kube-system + +NAME READY STATUS RESTARTS AGE +cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m +cert-manager-webhook-5b5dd6999-kst4x 1/1 Running 0 3m +cert-manager-cainjector-3ba5cd2bcd-de332x 1/1 Running 0 3m ``` +If the ‘webhook’ pod (2nd line) is in a ContainerCreating state, it may still be waiting for the Secret to be mounted into the pod. Wait a couple of minutes for this to happen but if you experience problems, please check the [troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html) guide. +
#### Rancher Generated Certificates diff --git a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md index 9681ef22fed..8fc35406bf2 100644 --- a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md +++ b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md @@ -5,6 +5,8 @@ weight: 1021 The following instructions will guide you through upgrading a high-availability Rancher Server installed in an air gap environment. +>**Note:** [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow [these instructions.]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap) + ## Prerequisites - **Populate Images** diff --git a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md index 471a172acf8..e1a783e6a3e 100644 --- a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md +++ b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md @@ -11,6 +11,10 @@ The following instructions will guide you through upgrading a high-availability > > As of release v2.0.8, Rancher supports installation and upgrade by Helm chart, although RKE installs/upgrades are still supported as well. If you want to change upgrade method from RKE Add-on to Helm chart, follow this procedure. +--- + +>**Note:** [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow [these instructions.]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/upgrade-cert-manager) + ## Prerequisites From e2172b68a7ad3ce3f765e2eed956c8def1ab06ea Mon Sep 17 00:00:00 2001 From: Rui Lopes Date: Sat, 31 Aug 2019 12:30:23 +0100 Subject: [PATCH 04/25] fix typo --- .../v2.x/en/admin-settings/authentication/local/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/admin-settings/authentication/local/_index.md b/content/rancher/v2.x/en/admin-settings/authentication/local/_index.md index a5bde3dec91..3044cc298fd 100644 --- a/content/rancher/v2.x/en/admin-settings/authentication/local/_index.md +++ b/content/rancher/v2.x/en/admin-settings/authentication/local/_index.md @@ -5,7 +5,7 @@ aliases: - /rancher/v2.x/en/tasks/global-configuration/authentication/local-authentication/ --- -Local authentication is the default until you configure an external authentication provider. Local authentication is where Rancher stores the user information, i.e. names and passwords, of who can log in to Ranchehr. By default, the `admin` user that logs in to Rancher for the first time is a local user. +Local authentication is the default until you configure an external authentication provider. Local authentication is where Rancher stores the user information, i.e. names and passwords, of who can log in to Rancher. By default, the `admin` user that logs in to Rancher for the first time is a local user. ## Adding Local Users From 8667e4fd9e81e1c8912ca2e869b0c08a534e70ea Mon Sep 17 00:00:00 2001 From: Tejeev Date: Wed, 4 Sep 2019 15:56:39 +0100 Subject: [PATCH 05/25] Clarify Finishing Up Better to be explicit than implicit. There was some confusion on what this was referring to since the section was written with an implicit context that the customer and I were lacking. I've attempted to add the context here. --- .../v2.x/en/backups/restorations/ha-restoration/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md b/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md index f51bca614a3..267c50a4d09 100644 --- a/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md +++ b/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md @@ -229,6 +229,6 @@ rke up --config ./rancher-cluster-restore.yml #### Finishing Up -Rancher should now be running and available to manage your Kubernetes clusters. Swap your Rancher DNS or Load Balancer endpoints to target the new cluster. Once this is done the agents on your managed clusters should automatically reconnect. This may take 10-15 minutes due to reconnect back off timeouts. +Rancher should now be running and available to manage your Kubernetes clusters. Swap the endpoints for Rancher DNS or the Load Balancer you built during Step 1 of the HA install ([1. Create Nodes and Load Balancer]({{< baseurl >}}/rancher/v2.x/en/installation/ha/create-nodes-lb/#load-balancer)) to target the new cluster. It might help to review the [suggested architecture]({{< baseurl >}}/rancher/v2.x/en/installation/ha/#recommended-architecture). Once this is done the agents on your managed clusters should automatically reconnect. This may take 10-15 minutes due to reconnect back off timeouts. > **IMPORTANT:** Remember to save your new RKE config (`rancher-cluster-restore.yml`) and `kubectl` credentials (`kube_config_rancher-cluster-restore.yml`) files in a safe place for future maintenance. From 86e3fa24ec2cad10aa8ad96f9e95300329c9d9b8 Mon Sep 17 00:00:00 2001 From: Craig Jellick Date: Tue, 3 Sep 2019 19:57:30 -0700 Subject: [PATCH 06/25] Revamp cert-manager docs - Condense air gap and normal upgrade instructions for cert-manager down to a single page. This allowed us to consolidate some repetetive text. - Add a section explaining cert-manager's API change and the recommended data migration - Moved the upgrade instructions out of the cluster administration section and into the Advanced installation options (not perfect but our best fit) - On the pages where we instruct the user to install cert-manger, made a note and link to our upgrade documentation --- .../upgrade-cert-manager-airgap/_index.md | 92 ----------- .../upgrade-cert-manager/_index.md | 47 ------ .../install-rancher/_index.md | 9 +- .../en/installation/ha/helm-rancher/_index.md | 54 ++++--- .../options/upgrading-cert-manager/_index.md | 149 ++++++++++++++++++ 5 files changed, 189 insertions(+), 162 deletions(-) delete mode 100644 content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md delete mode 100644 content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md create mode 100644 content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md diff --git a/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md b/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md deleted file mode 100644 index ddf7ee9e99d..00000000000 --- a/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap/_index.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Upgrade Cert-manager Airgap -weight: 2040 ---- - -[Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow these instructions: - ->**Note:** The namespaces used in these instructions depends on the namespace cert-manager is currently installed in. If it is in kube-system use that in the instructions below. You can verify by running `kubectl get pods --all-namespaces` and checking which namespace the cert-manager-* pods are listed in. Do not change the namespace cert-manager is running in or this can cause issues. - -## Prerequisites - -- **Populate Images** - - Follow the guide to [Prepare the Private Registry]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-installation/prepare-private-reg/) with the images for the upgrade Rancher release. - -- **Prepare cert-manager** - -1. From a system connected to the internet, add the cert-manager repo to helm - - ```plain - helm repo add jetstack https://charts.jetstack.io - helm repo update - ``` - -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.9.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-v0.9.1.tgz --output-dir . \ - --name cert-manager --namespace kube-system \ - --set image.repository=/quay.io/jetstack/cert-manager-controller - ``` - -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.9/deploy/manifests/00-crds.yaml - ``` - -## Install cert-manager - -1. Back up existing resources as a precaution - - ```plain - kubectl get -o yaml --all-namespaces issuer,clusterissuer,certificates > cert-manager-backup.yaml - ``` - -1. Delete the existing deployment - - ```plain - helm delete --purge cert-manager - ``` - -1. Install the CustomResourceDefinition resources separately - - ```plain - kubectl apply -f cert-manager/cert-manager-crd.yaml - ``` - -1. Label the kube-system namespace to disable resource validation - - ```plain - kubectl label namespace kube-system certmanager.k8s.io/disable-validation=true - ``` - -1. Install cert-manager - - ```plain - kubectl -n kube-system apply -R -f ./cert-manager - ``` - -Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the kube-system namespace for running pods: - -``` -kubectl get pods --namespace kube-system - -NAME READY STATUS RESTARTS AGE -cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m -cert-manager-webhook-5b5dd6999-kst4x 1/1 Running 0 3m -cert-manager-cainjector-3ba5cd2bcd-de332x 1/1 Running 0 3m -``` - -If the ‘webhook’ pod (2nd line) is in a ContainerCreating state, it may still be waiting for the Secret to be mounted into the pod. Wait a couple of minutes for this to happen but if you experience problems, please check the [troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html) guide. - -[Additional information on the annotation.](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.4-0.5.html?highlight=certmanager.k8s.io%2Fdisable-validation#disabling-resource-validation-on-the-cert-manager-namespace) - -[Additional information on the webhook feature.](https://docs.cert-manager.io/en/latest/getting-started/webhook.html) \ No newline at end of file diff --git a/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md b/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md deleted file mode 100644 index 70a59798003..00000000000 --- a/content/rancher/v2.x/en/cluster-admin/upgrade-cert-manager/_index.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Upgrade Cert-manager -weight: 2040 ---- - -[Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow these instructions: - - -``` -# Back up existing resources as a precaution -kubectl get -o yaml --all-namespaces issuer,clusterissuer,certificates > cert-manager-backup.yaml - -# Delete the existing deployment -helm delete --purge cert-manager - -# Install the CustomResourceDefinition resources separately -kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml - -# Label the kube-system namespace to disable resource validation -kubectl label namespace kube-system certmanager.k8s.io/disable-validation=true - -# Add the Jetstack Helm repository -helm repo add jetstack https://charts.jetstack.io - -# Update your local Helm chart repository cache -helm repo update - -# Install the new version of cert-manager -helm install --version 0.9.1 --name cert-manager --namespace kube-system jetstack/cert-manager -``` - -Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the kube-system namespace for running pods: - -``` -kubectl get pods --namespace kube-system - -NAME READY STATUS RESTARTS AGE -cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m -cert-manager-webhook-5b5dd6999-kst4x 1/1 Running 0 3m -cert-manager-cainjector-3ba5cd2bcd-de332x 1/1 Running 0 3m -``` - -If the ‘webhook’ pod (2nd line) is in a ContainerCreating state, it may still be waiting for the Secret to be mounted into the pod. Wait a couple of minutes for this to happen but if you experience problems, please check the [troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html) guide. - -[Additional information on the annotation.](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.4-0.5.html?highlight=certmanager.k8s.io%2Fdisable-validation#disabling-resource-validation-on-the-cert-manager-namespace) - -[Additional information on the webhook feature.](https://docs.cert-manager.io/en/latest/getting-started/webhook.html) \ No newline at end of file diff --git a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md index 09174cdaa08..83071b85249 100644 --- a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md @@ -52,7 +52,10 @@ Based on the choice your made in [B. Choose your SSL Configuration](#b-optional- In this section you will configure your cert manager and private registry in the Rancher template. {{% accordion id="self-signed" label="Option A: Default Self-Signed Certificate" %}} -By default, Rancher generates a CA and uses cert-manger to issue the certificate for access to the Rancher server interface. +By default, Rancher generates a CA and uses cert-manager to issue the certificate for access to the Rancher server interface. + +> **Note:** +> Recent changes to cert-manager require an upgrade. If you are upgrading Rancher and using a version of cert-manager older than v0.9.1, please see our [upgrade documentation]({{< baseurl >}}/rancher/v2.x/en/installation/options/upgrading-cert-manager/). 1. From a system connected to the internet, add the cert-manager repo to helm @@ -88,7 +91,7 @@ By default, Rancher generates a CA and uses cert-manger to issue the certificate `` | The version number of the output tarball. `` | The DNS name you pointed at your load balancer. `` | The DNS name for your private registry.). - + ```plain helm template ./rancher-.tgz --output-dir . \ @@ -166,4 +169,4 @@ These resources could be helpful when you install Rancher: - [Adding TLS secrets]({{}}/rancher/v2.x/en/installation/ha/helm-rancher/tls-secrets/) - [Troubleshooting Rancher HA installations]({{}}/rancher/v2.x/en/installation/ha/helm-rancher/troubleshooting/) -### [Next: Configure Rancher System Charts]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-high-availability/config-rancher-system-charts/) \ No newline at end of file +### [Next: Configure Rancher System Charts]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-high-availability/config-rancher-system-charts/) diff --git a/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md index 779aed80ae5..ce6e551f9be 100644 --- a/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md @@ -35,36 +35,50 @@ There are three recommended options for the source of the certificate. > **Note:** cert-manager is only required for certificates issued by Rancher's generated CA (`ingress.tls.source=rancher`) and Let's Encrypt issued certificates (`ingress.tls.source=letsEncrypt`). You should skip this step if you are using your own certificate files (option `ingress.tls.source=secret`) or if you use [TLS termination on an External Load Balancer]({{< baseurl >}}/rancher/v2.x/en/installation/ha/helm-rancher/chart-options/#external-tls-termination). -> **Important:** Due to an issue with Helm v2.12.0 and cert-manager, please use Helm v2.12.1 or higher. +> **Important:** + +> Due to an issue with Helm v2.12.0 and cert-manager, please use Helm v2.12.1 or higher. + +> Recent changes to cert-manager require an upgrade. If you are upgrading Rancher and using a version of cert-manager older than v0.9.1, please see our [upgrade documentation]({{< baseurl >}}/rancher/v2.x/en/installation/options/upgrading-cert-manager/). Rancher relies on [cert-manager](https://github.com/jetstack/cert-manager) to issue certificates from Rancher's own generated CA or to request Let's Encrypt certificates. -[These instructions come from cert-manager's official docs.](https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html#installing-with-helm) +These instructions are adapted from the [official cert-manager documentation](https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html#installing-with-helm). -``` -# Install the CustomResourceDefinition resources separately -kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml +1. Install the CustomResourceDefinition resources separately + ```plain + kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml + ``` -# Create the namespace for cert-manager -kubectl create namespace cert-manager +1. Create the namespace for cert-manager + ```plain + kubectl create namespace cert-manager + ``` -# Label the cert-manager namespace to disable resource validation -kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true +1. Label the cert-manager namespace to disable resource validation + ```plain + kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true + ``` -# Add the Jetstack Helm repository -helm repo add jetstack https://charts.jetstack.io +1. Add the Jetstack Helm repository + ```plain + helm repo add jetstack https://charts.jetstack.io + ``` -# Update your local Helm chart repository cache -helm repo update +1. Update your local Helm chart repository cache + ```plain + helm repo update + ``` -# Install the cert-manager Helm chart -helm install \ - --name cert-manager \ - --namespace cert-manager \ - --version v0.9.1 \ - jetstack/cert-manager -``` +1. Install the cert-manager Helm chart + ```plain + helm install \ + --name cert-manager \ + --namespace cert-manager \ + --version v0.9.1 \ + jetstack/cert-manager + ``` Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the cert-manager namespace for running pods: diff --git a/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md b/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md new file mode 100644 index 00000000000..d898013bb8f --- /dev/null +++ b/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md @@ -0,0 +1,149 @@ +--- +title: Upgrading Cert-Manager +weight: 2040 +--- + +Rancher uses cert-manager to automatically generate and renew TLS certificates for HA deployments of Rancher. As of Fall 2019, two important changes to cert-manager are set to occur that you need to take aciton on if you have an HA deployment of Rancher: + +1. [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) +1. [Cert-manager is deprecating and replacing the certificate.spec.acme.solvers field](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.7-0.8.html#upgrading-from-v0-7-to-v0-8). This change has no exact deadline. + +To address these changes, this guide will do two things: + +1. Document the procedure for upgrading cert-manager +1. Explain the cert-manager API changes and link to cert-manager's offficial documentation for migrating your data + + +## Performing the upgrade +>**Note:** The namespace used in these instructions depends on the namespace cert-manager is currently installed in. If it is in kube-system use that in the instructions below. You can verify by running `kubectl get pods --all-namespaces` and checking which namespace the cert-manager-\* pods are listed in. Do not change the namespace cert-manager is running in or this can cause issues. + +In order to upgrade cert-manager to the follow these instructions: +{{% accordion id="normal" label="Upgrading cert-manager with Internet access" %}} +1. Back up existing resources as a precaution + ```plain + kubectl get -o yaml --all-namespaces issuer,clusterissuer,certificates > cert-manager-backup.yaml + ``` + +1. Delete the existing deployment + ```plain + helm delete --purge cert-manager + ``` + +1. Install the CustomResourceDefinition resources separately + ```plain + kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml + ``` + +1. Label the kube-system namespace to disable resource validation + ```plain + kubectl label namespace kube-system certmanager.k8s.io/disable-validation=true + ``` + +1. Add the Jetstack Helm repository + ```plain + helm repo add jetstack https://charts.jetstack.io + ``` + +1. Update your local Helm chart repository cache + ```plain + helm repo update + ``` + +1. Install the new version of cert-manager + ```plain + helm install --version 0.9.1 --name cert-manager --namespace kube-system jetstack/cert-manager + ``` +{{% /accordion %}} + +{{% accordion id="airgap" label="Upgrading cert-manager in an airgapped environment" %}} +### Prerequisites +Before you can perform the upgrade, you must prepare your air gapped environment by adding the necesary container images to your private registry and downloading or rendering the required Kubernetes manifest files. + +1. Follow the guide to [Prepare your Private Registry]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-installation/prepare-private-reg/) with the images needed for the upgrade. + +1. From a system connected to the internet, add the cert-manager repo to helm + + ```plain + helm repo add jetstack https://charts.jetstack.io + helm repo update + ``` + +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.9.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-v0.9.1.tgz --output-dir . \ + --name cert-manager --namespace kube-system \ + --set image.repository=/quay.io/jetstack/cert-manager-controller + ``` + +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.9/deploy/manifests/00-crds.yaml + ``` + +### Install cert-manager + +1. Back up existing resources as a precaution + + ```plain + kubectl get -o yaml --all-namespaces issuer,clusterissuer,certificates > cert-manager-backup.yaml + ``` + +1. Delete the existing deployment + + ```plain + helm delete --purge cert-manager + ``` + +1. Install the CustomResourceDefinition resources separately + + ```plain + kubectl apply -f cert-manager/cert-manager-crd.yaml + ``` + +1. Label the kube-system namespace to disable resource validation + + ```plain + kubectl label namespace kube-system certmanager.k8s.io/disable-validation=true + ``` + +1. Install cert-manager + + ```plain + kubectl -n kube-system apply -R -f ./cert-manager + ``` +{{% /accordion %}} + + +Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the kube-system namespace for running pods: + +``` +kubectl get pods --namespace kube-system + +NAME READY STATUS RESTARTS AGE +cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m +cert-manager-webhook-5b5dd6999-kst4x 1/1 Running 0 3m +cert-manager-cainjector-3ba5cd2bcd-de332x 1/1 Running 0 3m +``` + +If the ‘webhook’ pod (2nd line) is in a ContainerCreating state, it may still be waiting for the Secret to be mounted into the pod. Wait a couple of minutes for this to happen but if you experience problems, please check cert-manager's [troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html) guide. + +> **Note:** The above instructions ask you to add the disable-validation label to the kube-system namespace. Here are additional resources that explain why this is necessary: +> +> - [Information on the disable-validation label](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.4-0.5.html?highlight=certmanager.k8s.io%2Fdisable-validation#disabling-resource-validation-on-the-cert-manager-namespace) +> - [Information on webhook validation for certificates](https://docs.cert-manager.io/en/latest/getting-started/webhook.html) + +## Cert-Manager API change and data migration + +Cert-manager has deprecated the use of the `certificate.spec.acme.solvers` field and will drop support for it completely in an upcoming release. + +Per the cert-manager documentation, a new format for configuring ACME certificate resources was introduced in v0.8. Specifically, the challenge solver configuration field was moved. Both the old format and new are supported as of v0.9, but support for the old format will be dropped in an upcoming release of cert-manager. The cert-manager documentation strongly recommends that after upgrading you update your ACME Issuer and Certificate resources to the new format. + +Details about the change and migration instructions can be found in the [cert-manager v0.7 to v0.8 upgrade instructions](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.7-0.8.html). From 8b900cb2a57390faee613b2813b310f306ad317d Mon Sep 17 00:00:00 2001 From: Denise Date: Wed, 4 Sep 2019 09:46:57 -0700 Subject: [PATCH 07/25] Update _index.md --- .../v2.x/en/backups/restorations/ha-restoration/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md b/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md index 267c50a4d09..b3f757d8600 100644 --- a/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md +++ b/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md @@ -229,6 +229,6 @@ rke up --config ./rancher-cluster-restore.yml #### Finishing Up -Rancher should now be running and available to manage your Kubernetes clusters. Swap the endpoints for Rancher DNS or the Load Balancer you built during Step 1 of the HA install ([1. Create Nodes and Load Balancer]({{< baseurl >}}/rancher/v2.x/en/installation/ha/create-nodes-lb/#load-balancer)) to target the new cluster. It might help to review the [suggested architecture]({{< baseurl >}}/rancher/v2.x/en/installation/ha/#recommended-architecture). Once this is done the agents on your managed clusters should automatically reconnect. This may take 10-15 minutes due to reconnect back off timeouts. +Rancher should now be running and available to manage your Kubernetes clusters. Review the [recommended architecture]({{< baseurl >}}/rancher/v2.x/en/installation/ha/#recommended-architecture) for HA installations and update the endpoints for Rancher DNS or the Load Balancer that you built during Step 1 of the HA install ([1. Create Nodes and Load Balancer]({{< baseurl >}}/rancher/v2.x/en/installation/ha/create-nodes-lb/#load-balancer)) to target the new cluster. Once the endpoints are updated, the agents on your managed clusters should automatically reconnect. This may take 10-15 minutes due to reconnect back off timeouts. > **IMPORTANT:** Remember to save your new RKE config (`rancher-cluster-restore.yml`) and `kubectl` credentials (`kube_config_rancher-cluster-restore.yml`) files in a safe place for future maintenance. From 00fe9e67146a006beb92a24f896f64e9e48b8ab6 Mon Sep 17 00:00:00 2001 From: niusmallnan Date: Fri, 16 Aug 2019 14:58:42 +0800 Subject: [PATCH 08/25] Fix the url link --- .../configuration/switching-docker-versions/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/os/v1.x/en/installation/configuration/switching-docker-versions/_index.md b/content/os/v1.x/en/installation/configuration/switching-docker-versions/_index.md index 65fe0ad175a..e51d1d46405 100644 --- a/content/os/v1.x/en/installation/configuration/switching-docker-versions/_index.md +++ b/content/os/v1.x/en/installation/configuration/switching-docker-versions/_index.md @@ -83,7 +83,7 @@ FROM scratch COPY engine /engine ``` -Once the image is built a [system service]({{< baseurl >}}/os/v1.x/en/installation/system-services/adding-system-services/) configuration file must be created. An [example file](https://github.com/rancher/os-services/blob/master/d/docker-1.12.3.yml) can be found in the rancher/os-services repo. Change the `image` field to point to the Docker engine image you've built. +Once the image is built a [system service]({{< baseurl >}}/os/v1.x/en/installation/system-services/adding-system-services/) configuration file must be created. An [example file](https://github.com/rancher/os-services/blob/master/d/docker-18.06.3-ce.yml) can be found in the rancher/os-services repo. Change the `image` field to point to the Docker engine image you've built. All of the previously mentioned methods of switching Docker engines are now available. For example, if your service file is located at `https://myservicefile` then the following cloud-config file could be used to use your custom Docker engine. From 0a9b79edb4883698a3cb8de7b4b7f4472b4a7750 Mon Sep 17 00:00:00 2001 From: Denise Date: Wed, 4 Sep 2019 11:08:48 -0700 Subject: [PATCH 09/25] Update _index.md --- .../running-rancheros/cloud/aliyun/_index.md | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md b/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md index 53538461cd9..ce08ce913fb 100644 --- a/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md +++ b/content/os/v1.x/en/installation/running-rancheros/cloud/aliyun/_index.md @@ -3,27 +3,29 @@ title: Aliyun weight: 111 --- -### Adding the RancherOS Image into Aliyun +# Adding the RancherOS Image into Aliyun -RancherOS is available as an image in Aliyun, and can be easily run in Elastic Compute Service (ECS). Let’s walk through how to upload ECS image. +RancherOS is available as an image in Aliyun, and can be easily run in Elastic Compute Service (ECS). Let’s walk through how to upload the ECS image. -1. Download the most recent RancherOS image. The image can be found in the [release artifacts](https://github.com/rancher/os/releases). It is a `rancheros-aliyun.vhd` file. -2. Follow Aliyun's instructions on how to [upload the image](https://help.aliyun.com/document_detail/127285.html). The image must be uploaded into a OSS bucket before it can be added. +1. Download the most recent RancherOS image. The image `rancheros-aliyun.vhd` can be found in the [release artifacts](https://github.com/rancher/os/releases). +2. Follow Aliyun's instructions on how to [upload the image](https://help.aliyun.com/document_detail/127285.html). Before the image can be added, it must be uploaded into an OSS bucket. 3. Once the image is added to your ECS, we can start creating new instances! -Here is a screenshot we can refer to: +Example: ![RancherOS on Aliyun 1]({{< baseurl >}}/img/os/RancherOS_aliyun1.jpg) -Please note these options: +## Options -- Root disk size, it should be greater than 10GB and kept same as the value when booting an instance. -- Platform, it must be `Others Linux` -- Image Format, it must be `VHD` +| Option | Description | +| --- | --- | +| Root disk size | The size must be greater than 10GB. Note: When booting the instance, the value must be kept the same. | +| Platform | Select `Others Linux` | +| Image Format | Select `VHD` | ### Launching RancherOS using Aliyun Console -After the image is uploaded, we can use the `Aliyun Console` to start a new instance. Currently RancherOS on Aliyun only supports ssh key access, so we need to fill it out in the console. +After the image is uploaded, we can use the `Aliyun Console` to start a new instance. Currently, RancherOS on Aliyun only supports SSH key access, so it can only be deployed through the UI. Since the image is private, we need to use the `Custom Images`. From ccff461a6dbc696781262e7b31a68b8822a0521b Mon Sep 17 00:00:00 2001 From: Denise Date: Wed, 4 Sep 2019 11:14:01 -0700 Subject: [PATCH 10/25] Update _index.md --- .../running-rancheros/server/install-to-disk/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md b/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md index 29f7bbd647a..e0deb1b54a4 100644 --- a/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md +++ b/content/os/v1.x/en/installation/running-rancheros/server/install-to-disk/_index.md @@ -86,13 +86,13 @@ Alternatively, you can set the installer image to any image in System Docker to _Available as of v1.5.3_ -Sometimes, some of the configurations included in cloud-config require additional docker images support. These images are typically downloaded automatically by RancherOS when booting after installation. These configurations can be: +Some configurations included in `cloud-config` require images to be downloaded from Docker to start. After installation, these images are downloaded automatically by RancherOS when booting. An example of these configurations are: - rancher.services_include - rancher.console - rancher.docker -If you want to download and save these images to disk during installation, they will be loaded automatically when booting next time. You can add `-s` when using `ros install`: +If you want to download and save these images to disk during installation, they will be cached and not need to be downloaded again upon each boot. You can cache these images by adding `-s` when using `ros install`: ``` $ ros install -d -c -s From 644dd96f504d48c7fb2e2a8dc56b71f6fea53b06 Mon Sep 17 00:00:00 2001 From: Oleg Tarassov Date: Tue, 13 Aug 2019 11:33:26 -0400 Subject: [PATCH 11/25] Update _index.md the bash scripts compiles into a single line which results into something like this: ``` for module in br_netfilter ip6_udp_tunnel ip_set ip_set_hash_ip ip_set_hash_net iptable_filter iptable_nat iptable_mangle iptable_raw nf_conntrack_netlink nf_conntrack nf_conntrack_ipv4 nf_defrag_ipv4 nf_ nat nf_nat_ipv4 nf_nat_masquerade_ipv4 nfnetlink udp_tunnel veth vxlan x_tables xt_addrtype xt_conntrack xt_comment xt_mark xt_multiport xt_nat xt_recent xt_set xt_statistic xt_tcpudp; do if ! lsmod | grep -q $module; then echo "module $m odule is not present" fi done; ``` to avoid syntax error, extra semicolons fixes the issue --- 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 b92097c4823..fc2bea89aa9 100644 --- a/content/rke/latest/en/os/_index.md +++ b/content/rke/latest/en/os/_index.md @@ -50,9 +50,9 @@ RKE runs on almost any Linux OS with Docker installed. Most of the development a for module in br_netfilter ip6_udp_tunnel ip_set ip_set_hash_ip ip_set_hash_net iptable_filter iptable_nat iptable_mangle iptable_raw nf_conntrack_netlink nf_conntrack nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat nf_nat_ipv4 nf_nat_masquerade_ipv4 nfnetlink udp_tunnel veth vxlan x_tables xt_addrtype xt_conntrack xt_comment xt_mark xt_multiport xt_nat xt_recent xt_set xt_statistic xt_tcpudp; do if ! lsmod | grep -q $module; then - echo "module $module is not present" - fi - done; + echo "module $module is not present"; + fi; + done ``` Module name | From 351d2999bae88c663fe4932a812b3ac965c4536b Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Wed, 4 Sep 2019 13:54:48 -0700 Subject: [PATCH 12/25] Explain Rancher access scope in external auth docs --- .../admin-settings/authentication/_index.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/content/rancher/v2.x/en/admin-settings/authentication/_index.md b/content/rancher/v2.x/en/admin-settings/authentication/_index.md index 0dc19a78a1b..b4953edf743 100644 --- a/content/rancher/v2.x/en/admin-settings/authentication/_index.md +++ b/content/rancher/v2.x/en/admin-settings/authentication/_index.md @@ -40,6 +40,28 @@ Rancher relies on users and groups to determine who is allowed to log in to Ranc For more information, see [Users and Groups]({{< baseurl >}}/rancher/v2.x/en/admin-settings/authentication/user-groups/) +## Scope of Rancher Authorization + +After you configure Rancher to allow sign on using an external authentication service, you should configure who should be allowed to log in and use Rancher. The following options are available: + +| Access Level | Description | +|----------------------------------------------|-------------| +| Allow any valid Users | _Any_ user in the authorization service can access Rancher. We generally discourage use of this setting! | +| Allow members of Clusters, Projects, plus Authorized Users and Organizations | Any user in the authorization service and any group added as a **Cluster Member** or **Project Member** can log in to Rancher. Additionally, any user in the authentication service or group you add to the **Authorized Users and Organizations** list may log in to Rancher. | +| Restrict access to only Authorized Users and Organizations | Only users in the authentication service or groups added to the Authorized Users and Organizations can log in to Rancher. | + +To set the Rancher access level for users in the authorization service, follow these steps: + +1. From the **Global** view, click **Security > Authentication.** + +1. Use the **Site Access** options to configure the scope of user authorization. The table above explains the access level for each option. + +1. Optional: If you choose an option other than **Allow any valid Users,** you can add users to the list of authorized users and organizations by searching for them in the text field that appears. + +1. Click **Save.** + +**Result:** The Rancher access configuration settings are applied. + ## External Authentication Configuration and Principal Users Configuration of external authentication requires: From bcd9daea8eace23b9fe5bb0814f51d78ceeaa2b5 Mon Sep 17 00:00:00 2001 From: Tejeev Date: Thu, 29 Aug 2019 23:07:54 +0100 Subject: [PATCH 13/25] Corrected link for airgapped HA upgrades --- .../v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md index 471a172acf8..67b304ae622 100644 --- a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md +++ b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md @@ -42,7 +42,7 @@ Upgrades _to_ or _from_ any chart in the [rancher-alpha repository]({{< baseurl ## Upgrade Rancher -> **Note:** For Air Gap installs see [Upgrading HA Rancher - Air Gap]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-installation/install-rancher/#upgrading-rancher) +> **Note:** For Air Gap installs see [Upgrading HA Rancher - Air Gap]({{< baseurl >}}/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/) 1. Update your local helm repo cache. From 6f52fd43cd0e678d29c3f32ba76f547bc4774f22 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Steenis Date: Wed, 21 Aug 2019 15:58:03 +0200 Subject: [PATCH 14/25] Link NGINX config to avoid data being out of date --- .../ha/rke-add-on/layer-7-lb/nginx/_index.md | 53 +------------------ 1 file changed, 1 insertion(+), 52 deletions(-) diff --git a/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/nginx/_index.md b/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/nginx/_index.md index 0a99effcaba..74ea304f3d7 100644 --- a/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/nginx/_index.md +++ b/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/nginx/_index.md @@ -19,58 +19,7 @@ For help installing NGINX, refer to their [install documentation](https://www.ng ## Create NGINX Configuration -After installing NGINX, you need to create the NGINX config file, `/etc/nginx/conf.d/rancher.conf`, with the IP addresses for your Linux nodes, chosen FQDN and location of the certificate file and certificate key file. - ->**Note:** The example configuration below does not include all available Nginx options and may not be suitable for your production environment. For full configuration documentation, see [NGINX Load Balancing - HTTP Load Balancer](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/). - -1. Copy and paste the code sample below into your favorite text editor. Save it as `/etc/nginx/conf.d/rancher.conf`. - - **Example NGINX config:** - ``` - upstream rancher { - server IP_NODE_1:80; - server IP_NODE_2:80; - server IP_NODE_3:80; - } - - map $http_upgrade $connection_upgrade { - default Upgrade; - '' close; - } - - server { - listen 443 ssl http2; - server_name FQDN; - ssl_certificate /certs/fullchain.pem; - ssl_certificate_key /certs/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port $server_port; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://rancher; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - # This allows the ability for the execute shell window to remain open for up to 15 minutes. Without this parameter, the default is 1 minute and will automatically close. - proxy_read_timeout 900s; - } - } - - server { - listen 80; - server_name FQDN; - return 301 https://$server_name$request_uri; - } - ``` - -2. In `/etc/nginx/conf.d/rancher.conf`, replace `IP_NODE_1`, `IP_NODE_2`, and `IP_NODE_3` with the IPs of your Linux hosts. -3. In `/etc/nginx/conf.d/rancher.conf`, replace `FQDN` with the FQDN you chose for your Rancher installation. -4. In `/etc/nginx/conf.d/rancher.conf`, replace `/certs/fullchain.pem` with the path to your certificate. If there are intermediates required for you certificate, they should be included in this file. -5. In `/etc/nginx/conf.d/rancher.conf`, replace `/certs/privkey.pem` with the path to your certificate key. - - +See [Example NGINX config]({{< baseurl >}}/rancher/v2.x/en/installation/ha/helm-rancher/chart-options/#example-nginx-config). ## Run NGINX From eafe0afaa774a736c800ad3886f76669e3349862 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Wed, 4 Sep 2019 15:54:08 -0700 Subject: [PATCH 15/25] Add SAML caveats shortcode to auth docs --- content/rancher/v2.x/en/admin-settings/authentication/_index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/rancher/v2.x/en/admin-settings/authentication/_index.md b/content/rancher/v2.x/en/admin-settings/authentication/_index.md index b4953edf743..d9c21914168 100644 --- a/content/rancher/v2.x/en/admin-settings/authentication/_index.md +++ b/content/rancher/v2.x/en/admin-settings/authentication/_index.md @@ -62,6 +62,8 @@ To set the Rancher access level for users in the authorization service, follow t **Result:** The Rancher access configuration settings are applied. +{{< saml_caveats >}} + ## External Authentication Configuration and Principal Users Configuration of external authentication requires: From 3b87fee3b42e166dd9e876bd0acf2133f00485c3 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Steenis Date: Thu, 5 Sep 2019 14:21:50 +0200 Subject: [PATCH 16/25] Refer to official etcd site --- content/rancher/v2.x/en/cluster-admin/tools/alerts/_index.md | 2 +- content/rke/latest/en/config-options/services/_index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/cluster-admin/tools/alerts/_index.md b/content/rancher/v2.x/en/cluster-admin/tools/alerts/_index.md index 9ac774135f4..85a15aff2ca 100644 --- a/content/rancher/v2.x/en/cluster-admin/tools/alerts/_index.md +++ b/content/rancher/v2.x/en/cluster-admin/tools/alerts/_index.md @@ -154,7 +154,7 @@ This alert type monitors for the overload from Prometheus expression querying, i - [**Node**](https://github.com/prometheus/node_exporter) - [**Container**](https://github.com/google/cadvisor) - - [**ETCD**](https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/monitoring.md) + - [**ETCD**](https://etcd.io/docs/v3.3.12/op-guide/monitoring/) - [**Kubernetes Components**](https://github.com/kubernetes/metrics) - [**Kubernetes Resources**](https://github.com/kubernetes/kube-state-metrics) - [**Fluentd**](https://docs.fluentd.org/v1.0/articles/monitoring-prometheus) (supported by [Logging]({{< baseurl >}}/rancher/v2.x/en/tools/logging)) diff --git a/content/rke/latest/en/config-options/services/_index.md b/content/rke/latest/en/config-options/services/_index.md index f21b97906c4..8446aeb52b4 100644 --- a/content/rke/latest/en/config-options/services/_index.md +++ b/content/rke/latest/en/config-options/services/_index.md @@ -18,7 +18,7 @@ To deploy Kubernetes, RKE deploys several core components or services in Docker ## etcd -Kubernetes uses [etcd](https://github.com/coreos/etcd/blob/master/Documentation/docs.md) as a store for cluster state and data. Etcd is a reliable, consistent and distributed key-value store. +Kubernetes uses [etcd](https://etcd.io/) as a store for cluster state and data. Etcd is a reliable, consistent and distributed key-value store. RKE supports running etcd in a single node mode or in HA cluster mode. It also supports adding and removing etcd nodes to the cluster. From 01f7d723315a29b5c17e9af77f632ab3f50cfe78 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Steenis Date: Thu, 5 Sep 2019 14:11:32 +0200 Subject: [PATCH 17/25] Update etcd troubleshooting commands to 3.3.x+ --- .../kubernetes-components/_index.md | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md b/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md index 5aa3f29d4c9..fbce493de5e 100644 --- a/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md @@ -64,12 +64,12 @@ The address where etcd is listening depends on the address configuration of the Output should contain all the nodes with the `etcd` role and the output should be identical on all nodes. -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl member list ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list" ``` @@ -85,12 +85,12 @@ xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001 The values for `RAFT TERM` should be equal and `RAFT INDEX` should be not be too far apart from each other. -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table ``` @@ -108,12 +108,12 @@ Example output: * Check endpoint health -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl endpoint health --endpoints=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd etcdctl endpoint health --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") ``` @@ -127,7 +127,9 @@ https://IP:2379 is healthy: successfully committed proposal: took = 2.451201ms * Check connectivity on port TCP/2379 -Command when no internal address is configured on the host: +Requires the `curl` binary on the node. + +Command: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5"); do echo "Validating connection to ${endpoint}/health"; @@ -135,7 +137,7 @@ for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 done ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5"); do echo "Validating connection to ${endpoint}/health"; @@ -145,19 +147,19 @@ done If you are running on an operating system without `curl` (for example, RancherOS), you can use the following command which uses a Docker container to run the `curl` command. -Command when no internal address is configured on the host: +Command: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5"); do - echo "Validating connection to ${endpoint}/health"; - docker run --net=host -v /opt/rke/etc/kubernetes/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health" + echo "Validating connection to ${endpoint}/health" + docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health" done ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5"); do echo "Validating connection to ${endpoint}/health"; - docker run --net=host -v /opt/rke/etc/kubernetes/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health" + docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health" done ``` @@ -173,37 +175,37 @@ Validating connection to https://IP:2379/health * Check connectivity on port TCP/2380 -Command when no internal address is configured on the host: +Command: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f4"); do echo "Validating connection to ${endpoint}/version"; - curl -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"; + curl --http1.1 -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"; done ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f4"); do echo "Validating connection to ${endpoint}/version"; - curl -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"; + curl --http1.1 -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"; done ``` If you are running on an operating system without `curl` (for example, RancherOS), you can use the following command which uses a Docker container to run the `curl` command. -Command when no internal address is configured on the host: +Command: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f4"); do echo "Validating connection to ${endpoint}/version"; - docker run --net=host -v /opt/rke/etc/kubernetes/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version" + docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl --http1.1 -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version" done ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f4"); do echo "Validating connection to ${endpoint}/version"; - docker run --net=host -v /opt/rke/etc/kubernetes/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version" + docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl --http1.1 -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version" done ``` @@ -221,12 +223,12 @@ Validating connection to https://IP:2380/version etcd will trigger alarms, for instance when it runs out of space. -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl alarm list ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list" ``` @@ -246,13 +248,13 @@ Resolution: * Compact the keyspace -Command when no internal address is configured on the host: +Command: ``` rev=$(docker exec etcd etcdctl endpoint status --write-out json | egrep -o '"revision":[0-9]*' | egrep -o '[0-9]*') docker exec etcd etcdctl compact "$rev" ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` rev=$(docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT endpoint status --write-out json | egrep -o '\"revision\":[0-9]*' | egrep -o '[0-9]*'") docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT compact \"$rev\"" @@ -265,12 +267,12 @@ compacted revision xxx * Defrag all etcd members -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl defrag --endpoints=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd sh -c "etcdctl defrag --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','")" ``` @@ -284,12 +286,12 @@ Finished defragmenting etcd member[https://IP:2379] * Check endpoint status -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd sh -c "etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table" ``` @@ -309,14 +311,14 @@ Example output: After verifying that the DB size went down after compaction and defragmenting, the alarm needs to be disarmed for etcd to allow writes again. -Command when no internal address is configured on the host: +Command: ``` docker exec etcd etcdctl alarm list docker exec etcd etcdctl alarm disarm docker exec etcd etcdctl alarm list ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list" docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm disarm" @@ -337,24 +339,24 @@ docker exec etcd etcdctl alarm list The log level of etcd can be changed dynamically via the API. You can configure debug logging using the commands below. -Command when no internal address is configured on the host: +Command: ``` -curl -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) https://localhost:2379/config/local/log +curl -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINTS)/config/local/log ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` curl -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv $ETCDCTL_ENDPOINT)/config/local/log ``` To reset the log level back to the default (`INFO`), you can use the following command. -Command when no internal address is configured on the host: +Command: ``` -curl -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) https://localhost:2379/config/local/log +curl -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINTS)/config/local/log ``` -Command when internal address is configured on the host: +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: ``` curl -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv $ETCDCTL_ENDPOINT)/config/local/log ``` From 7a043aa67b7e00a02040cee5e95c3a6c83ed4fa7 Mon Sep 17 00:00:00 2001 From: Chris Van Vleit Date: Sat, 26 Jan 2019 14:57:41 -0800 Subject: [PATCH 18/25] Update _index.md --- content/rancher/v2.x/en/installation/references/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/rancher/v2.x/en/installation/references/_index.md b/content/rancher/v2.x/en/installation/references/_index.md index 9ccafe15b9c..7ff712a8132 100644 --- a/content/rancher/v2.x/en/installation/references/_index.md +++ b/content/rancher/v2.x/en/installation/references/_index.md @@ -112,6 +112,6 @@ When using the [AWS EC2 node driver]({{< baseurl >}}/rancher/v2.x/en/cluster-pro | Custom UDP Rule | UDP | 8472 | sg-xxx (rancher-nodes) | Inbound | | Custom TCP Rule | TCP | 10250-10252 | sg-xxx (rancher-nodes) | Inbound | | Custom TCP Rule | TCP | 10256 | sg-xxx (rancher-nodes) | Inbound | -| Custom TCP Rule | TCP | 30000-32767 | 30000-32767 | Inbound | -| Custom UDP Rule | UDP | 30000-32767 | 30000-32767 | Inbound | +| Custom TCP Rule | TCP | 30000-32767 | 0.0.0.0/0 | Inbound | +| Custom UDP Rule | UDP | 30000-32767 | 0.0.0.0/0 | Inbound | | All traffic | All | All | 0.0.0.0/0 | Outbound | From 222db8b4d5467f07a700290cd62ee44afef232a8 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Steenis Date: Thu, 5 Sep 2019 15:57:36 +0200 Subject: [PATCH 19/25] Add CoreDNS troubleshooting --- .../v2.x/en/troubleshooting/dns/_index.md | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/content/rancher/v2.x/en/troubleshooting/dns/_index.md b/content/rancher/v2.x/en/troubleshooting/dns/_index.md index 431942c9a44..f64f6e5729b 100644 --- a/content/rancher/v2.x/en/troubleshooting/dns/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/dns/_index.md @@ -7,7 +7,7 @@ The commands/steps listed on this page can be used to check name resolution issu Make sure you configured the correct kubeconfig (for example, `export KUBECONFIG=$PWD/kube_config_rancher-cluster.yml` for Rancher HA) or are using the embedded kubectl via the UI. -Before running the DNS checks, make sure that [the overlay network is functioning correctly]({{< baseurl >}}/rancher/v2.x/en/troubleshooting/networking/#check-if-overlay-network-is-functioning-correctly) as this can also be the reason why DNS resolution (partly) fails. +Before running the DNS checks, check the [default DNS provider]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/#default-dns-provider) for your cluster and make sure that [the overlay network is functioning correctly]({{< baseurl >}}/rancher/v2.x/en/troubleshooting/networking/#check-if-overlay-network-is-functioning-correctly) as this can also be the reason why DNS resolution (partly) fails. ### Check if DNS pods are running @@ -15,7 +15,13 @@ Before running the DNS checks, make sure that [the overlay network is functionin kubectl -n kube-system get pods -l k8s-app=kube-dns ``` -Example output: +Example output when using CoreDNS: +``` +NAME READY STATUS RESTARTS AGE +coredns-799dffd9c4-6jhlz 1/1 Running 0 76m +``` + +Example output when using kube-dns: ``` NAME READY STATUS RESTARTS AGE kube-dns-5fd74c7488-h6f7n 3/3 Running 0 4m13s @@ -123,9 +129,45 @@ command terminated with exit code 1 Cleanup the alpine DaemonSet by running `kubectl delete ds/dnstest`. -### Check upstream nameservers in kubedns container +### CoreDNS specific -By default, the configured nameservers on the host (in `/etc/resolv.conf`) will be used as upstream nameservers for `kube-dns`. Sometimes the host will run a local caching DNS nameserver, which means the address in `/etc/resolv.conf` will point to an address in the loopback range (`127.0.0.0/8`) which will be unreachable by the container. In case of Ubuntu 18.04, this is done by `systemd-resolved`. Since Rancher v2.0.7, we detect if `systemd-resolved` is running, and will automatically use the `/etc/resolv.conf` file with the correct upstream nameservers (which is located at `/run/systemd/resolve/resolv.conf`). +#### Check CoreDNS logging + +``` +kubectl -n kube-system logs -l k8s-app=kube-dns +``` + +#### Check configuration + +CoreDNS configuration is stored in the configmap `coredns` in the `kube-system` namespace. + +``` +kubectl -n kube-system get configmap coredns -o go-template={{.data.Corefile}} +``` + +#### Check upstream nameservers in resolv.conf + +By default, the configured nameservers on the host (in `/etc/resolv.conf`) will be used as upstream nameservers for CoreDNS. You can check this file on the host or run the following Pod with `dnsPolicy` set to `Default`, which will inherit the `/etc/resolv.conf` from the host it is running on. + +``` +kubectl run -i --restart=Never --rm test-${RANDOM} --image=ubuntu --overrides='{"kind":"Pod", "apiVersion":"v1", "spec": {"dnsPolicy":"Default"}}' -- sh -c 'cat /etc/resolv.conf' +``` + +#### Enable query logging + +Enabling query logging can be done by enabling the [log plugin](https://coredns.io/plugins/log/) in the Corefile configuration in the configmap `coredns`. You can do so by using `kubectl -n kube-system edit configmap coredns` or use the command below to replace the configuration in place: + +``` +kubectl get configmap -n kube-system coredns -o json | kubectl get configmap -n kube-system coredns -o json | sed -e 's_loadbalance_log\\n loadbalance_g' | kubectl apply -f - +``` + +All queries will now be logged and can be checked using the command in [Check CoreDNS logging](#check-coredns-logging). + +### kube-dns specific + +#### Check upstream nameservers in kubedns container + +By default, the configured nameservers on the host (in `/etc/resolv.conf`) will be used as upstream nameservers for kube-dns. Sometimes the host will run a local caching DNS nameserver, which means the address in `/etc/resolv.conf` will point to an address in the loopback range (`127.0.0.0/8`) which will be unreachable by the container. In case of Ubuntu 18.04, this is done by `systemd-resolved`. Since Rancher v2.0.7, we detect if `systemd-resolved` is running, and will automatically use the `/etc/resolv.conf` file with the correct upstream nameservers (which is located at `/run/systemd/resolve/resolv.conf`). Use the following command to check the upstream nameservers used by the kubedns container: From 4bf1fac1d0184c56c4b4b8bed0a649d6a504bb01 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Wed, 4 Sep 2019 15:08:37 -0700 Subject: [PATCH 20/25] Say that only clusters hosted by infrastructure providers can be cloned --- .../cluster-admin/cloning-clusters/_index.md | 110 +++++------------- 1 file changed, 27 insertions(+), 83 deletions(-) diff --git a/content/rancher/v2.x/en/cluster-admin/cloning-clusters/_index.md b/content/rancher/v2.x/en/cluster-admin/cloning-clusters/_index.md index 43c8dc93a5e..83f6361e8e9 100644 --- a/content/rancher/v2.x/en/cluster-admin/cloning-clusters/_index.md +++ b/content/rancher/v2.x/en/cluster-admin/cloning-clusters/_index.md @@ -7,22 +7,18 @@ aliases: If you have a cluster in Rancher that you want to use as a template for creating similar clusters, you can use Rancher CLI to clone the cluster's configuration, edit it, and then use it to quickly launch the cloned cluster. -## Caveats +You can clone clusters only if the nodes in the cluster are hosted by an infrastructure provider, such as EC2, Azure, or DigitalOcean. -- Only [cluster types]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/#cluster-creation-options) that interact with cloud hosts over API can be cloned. Duplication of imported clusters and custom clusters provisioned using Docker machine is not supported. +Duplication of imported clusters, clusters in hosted Kubernetes providers, and custom clusters provisioned using Docker machine is not supported. - | Cluster Type | Cloneable? | - | -------------------------------- | ------------- | - | [Hosted Kubernetes Providers][1] | ✓ | - | [Nodes Hosted by Infrastructure Provider][2] | ✓ | - | [Custom Cluster][3] | | - | [Imported Cluster][4] | | -- During the process of duplicating a cluster, you will edit a config file full of cluster settings. However, we recommend editing only values explicitly listed in this document, as cluster duplication is designed for simple cluster copying, _not_ wide scale configuration changes. Editing other values may invalidate the config file, which will lead to cluster deployment failure. +| Cluster Type | Cloneable? | +|----------------------------------|---------------| +| [Nodes Hosted by Infrastructure Provider]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/) | ✓ | +| [Hosted Kubernetes Providers]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/) | | +| [Custom Cluster]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/custom-clusters/) | | +| [Imported Cluster]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/imported-clusters/) | | -[1]: {{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/ -[2]: {{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/ -[3]: {{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/custom-clusters/ -[4]: {{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/imported-clusters/ +> **Warning:** During the process of duplicating a cluster, you will edit a config file full of cluster settings. However, we recommend editing only values explicitly listed in this document, as cluster duplication is designed for simple cluster copying, _not_ wide scale configuration changes. Editing other values may invalidate the config file, which will lead to cluster deployment failure. ## Prerequisites @@ -62,77 +58,25 @@ Use your favorite text editor to modify the cluster configuration in `cluster-te >**Warning:** Only edit the cluster config values explicitly called out below. Many of the values listed in this file are used to provision your cloned cluster, and editing their values may break the provisioning process. -1. As depicted in one of the examples below, at the `` placeholder, replace your original cluster's name with a unique name (``). If your cloned cluster has a duplicate name, the cluster will not provision successfully. -{{% accordion id="gke" label="GKE" %}} -```yml -Version: v3 -clusters: - : # ENTER UNIQUE NAME - dockerRootDir: /var/lib/docker - enableNetworkPolicy: false - googleKubernetesEngineConfig: - credential: |- - { - "type": "service_account", - "project_id": "gke-cluster-221300", - "private_key_id": "1d210afae352bc298bde1b3e680ec0c8b22cdd61" -``` -{{% /accordion %}} -{{% accordion id="eks" label="EKS" %}} -```yml -Version: v3 -clusters: - : # ENTER UNIQUE NAME - amazonElasticContainerServiceConfig: - accessKey: 00000000000000000000 - associateWorkerNodePublicIp: true - instanceType: t2.medium - maximumNodes: 3 - minimumNodes: 1 - region: us-west-2 - secretKey: 0000000000000000000000000000000000000000 - dockerRootDir: /var/lib/docker - enableNetworkPolicy: false -``` -{{% /accordion %}} -{{% accordion id="aks" label="AKS" %}} -```yml -Version: v3 -clusters: - : # ENTER UNIQUE NAME - azureKubernetesServiceConfig: - adminUsername: azureuser - agentPoolName: rancher - agentVmSize: Standard_D5_v2 - clientId: 00000000-0000-0000-0000-000000000000 - clientSecret: 00000000000000000000000000000000000000000000 - count: 3 - kubernetesVersion: 1.11.2 - location: westus - osDiskSizeGb: 100 - resourceGroup: docker-machine - sshPublicKeyContents: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJc2kDExgRaDLD -``` -{{% /accordion %}} -{{% accordion id="ec2" label="Nodes Hosted by Infrastructure Provider (EC2, Azure, or DigitalOcean )" %}} -```yml -Version: v3 -clusters: - : # ENTER UNIQUE NAME - dockerRootDir: /var/lib/docker - enableNetworkPolicy: false - rancherKubernetesEngineConfig: - addonJobTimeout: 30 - authentication: - strategy: x509 - authorization: {} - bastionHost: {} - cloudProvider: {} - ignoreDockerVersion: true -``` -{{% /accordion %}} +1. As depicted in the example below, at the `` placeholder, replace your original cluster's name with a unique name (``). If your cloned cluster has a duplicate name, the cluster will not provision successfully. -1. **Nodes Hosted by Infrastructure Provider Only:** For each `nodePools` section, replace the original nodepool name with a unique name at the `` placeholder. If your cloned cluster has a duplicate nodepool name, the cluster will not provision successfully. + ```yml + Version: v3 + clusters: + : # ENTER UNIQUE NAME + dockerRootDir: /var/lib/docker + enableNetworkPolicy: false + rancherKubernetesEngineConfig: + addonJobTimeout: 30 + authentication: + strategy: x509 + authorization: {} + bastionHost: {} + cloudProvider: {} + ignoreDockerVersion: true + ``` + +1. For each `nodePools` section, replace the original nodepool name with a unique name at the `` placeholder. If your cloned cluster has a duplicate nodepool name, the cluster will not provision successfully. ```yml nodePools: From 4bb7aa6c76150507e9e1b4f39b3f54ddf21a7110 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Thu, 5 Sep 2019 13:22:27 -0700 Subject: [PATCH 21/25] Update the etcd restoration process in RKE docs (#1679) * Edit RKE backup and recovery docs * Edit RKE backup and recovery docs * Edit RKE restore docs * Add manual steps to older RKE restore process * Make example scenario consistent with restore doc * Remove node3 from table in rke restore scenario * Remove node3 from both tables in rke restore doc * Fix typo * Add numbers to example scenario steps --- .../rke/latest/en/etcd-snapshots/_index.md | 291 +----------------- .../example-scenarios/_index.md | 253 +++++++++++++++ .../one-time-snapshots/_index.md | 92 ++++++ .../recurring-snapshots/_index.md | 97 ++++++ .../restoring-from-backup/_index.md | 112 +++++++ .../etcd-snapshots/troubleshooting/_index.md | 22 ++ 6 files changed, 585 insertions(+), 282 deletions(-) create mode 100644 content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md create mode 100644 content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md create mode 100644 content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md create mode 100644 content/rke/latest/en/etcd-snapshots/restoring-from-backup/_index.md create mode 100644 content/rke/latest/en/etcd-snapshots/troubleshooting/_index.md diff --git a/content/rke/latest/en/etcd-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/_index.md index efe05c2fb39..d973feb3d2f 100644 --- a/content/rke/latest/en/etcd-snapshots/_index.md +++ b/content/rke/latest/en/etcd-snapshots/_index.md @@ -11,295 +11,22 @@ RKE clusters can be configured to automatically take snapshots of etcd. In a dis _Available as of v0.2.0_ -RKE can also upload your snapshots to a S3 compatible backend. Additionally, the **pki.bundle.tar.gz** file usage is no longer required as v0.2.0 has changed how the [Kubernetes cluster state is stored]({{< baseurl >}}/rke/latest/en/installation/#kubernetes-cluster-state). +RKE can upload your snapshots to a S3 compatible backend. -## One-Time Snapshots +**Note:** As of RKE v0.2.0, the `pki.bundle.tar.gz` file is no longer required because of a change in how the [Kubernetes cluster state is stored]({{< baseurl >}}/rke/latest/en/installation/#kubernetes-cluster-state). -The `rke etcd snapshot-save` command will save a snapshot of etcd from each etcd node in the cluster config file. The snapshot is saved in `/opt/rke/etcd-snapshots`. When running the command, an additional container is created to take the snapshot. When the snapshot is completed, the container is automatically removed. +# Backing Up a Cluster -Prior to v0.2.0, along with the individual snapshot, RKE saves a backup of the certificates, i.e. a file named `pki.bundle.tar.gz`, in the same location. The snapshot and pki bundle file are required for the restore process in versions prior to v0.2.0. +You can create [one-time snapshots]({{}}/rke/latest/en/etcd-snapshots/one-time-snapshots) to back up your cluster, and you can also configure [recurring snapshots]({{}}/rke/latest/en/etcd-snapshots/recurring-snapshots). -As of v0.2.0, the one-time snapshot can be uploaded to a S3 compatible backend by using the additional options to specify the S3 backend. +# Restoring a Cluster from Backup -### Options for `rke etcd snapshot-save` +You can use RKE to [restore your cluster from backup]({{}}/rke/latest/en/etcd-snapshots/restoring-from-backup). -| Option | Description | S3 Specific | -| --- | --- | --- | -| `--name` value | Specify snapshot name | | -| `--config` value | Specify an alternate cluster YAML file (default: "cluster.yml") [$RKE_CONFIG] | | -| `--s3` | Enabled backup to s3 | * | -| `--s3-endpoint` value | Specify s3 endpoint url (default: "s3.amazonaws.com") | * | -| `--access-key` value | Specify s3 accessKey | * | -| `--secret-key` value | Specify s3 secretKey | * | -| `--bucket-name` value | Specify s3 bucket name | * | -| `--region` value | Specify the s3 bucket location (optional) | * | -| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | | -| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | +# Example Scenarios -### IAM Support for Storing Snapshots in S3 -In addition to API access keys, RKE supports using IAM roles for S3 authentication. The cluster etcd nodes must be assigned an IAM role that has read/write access to the designated backup bucket on S3. Also, the nodes must have network access to the S3 endpoint specified. - - To give an application access to S3, refer to the AWS documentation on [Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances.](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) - -### Local One-Time Snapshot Example - -``` -$ rke etcd snapshot-save --config cluster.yml --name snapshot-name -``` - -The snapshot is saved in `/opt/rke/etcd-snapshots` - -### One-Time Snapshots uploaded to S3 Example - -_Available as of v0.2.0_ - -``` -$ rke etcd snapshot-save --config cluster.yml --name snapshot-name \ ---s3 --access-key S3_ACCESS_KEY --secret-key S3_SECRET_KEY \ ---bucket-name s3-bucket-name --s3-endpoint s3.amazonaws.com -``` - -The snapshot is saved in `/opt/rke/etcd-snapshots` as well as uploaded to the S3 backend. - -## Recurring Snapshots - -To schedule automatic recurring etcd snapshots, you can enable the `etcd-snapshot` service with [extra configuration options the etcd service](#options-for-the-etcd-snapshot-service). `etcd-snapshot` runs in a service container alongside the `etcd` container. By default, the `etcd-snapshot` service takes a snapshot for every node that has the `etcd` role and stores them to local disk in `/opt/rke/etcd-snapshots`. If you set up the [options for S3](#options-for-the-etcd-snapshot-service), the snapshot will also be uploaded to the S3 backend. - -Prior to v0.2.0, along with the snapshots, RKE saves a backup of the certificates, i.e. a file named `pki.bundle.tar.gz`, in the same location. The snapshot and pki bundle file are required for the restore process in versions prior to v0.2.0. - -When a cluster is launched with the `etcd-snapshot` service enabled, you can view the `etcd-rolling-snapshots` logs to confirm backups are being created automatically. - -``` -$ docker logs etcd-rolling-snapshots - -time="2018-05-04T18:39:16Z" level=info msg="Initializing Rolling Backups" creation=1m0s retention=24h0m0s -time="2018-05-04T18:40:16Z" level=info msg="Created backup" name="2018-05-04T18:40:16Z_etcd" runtime=108.332814ms -time="2018-05-04T18:41:16Z" level=info msg="Created backup" name="2018-05-04T18:41:16Z_etcd" runtime=92.880112ms -time="2018-05-04T18:42:16Z" level=info msg="Created backup" name="2018-05-04T18:42:16Z_etcd" runtime=83.67642ms -time="2018-05-04T18:43:16Z" level=info msg="Created backup" name="2018-05-04T18:43:16Z_etcd" runtime=86.298499ms -``` - -### Options for the `Etcd-Snapshot` Service - -Depending on your version of RKE, the options used to configure recurring snapshots may be different. - -_Available as of v0.2.0_ - -|Option|Description| S3 Specific | -|---|---| --- | -|**interval_hours**| The duration in hours between recurring backups. This supercedes the `creation` option and will override it if both are specified.| | -|**retention**| The number of snapshots to retain before rotation. This supercedes the `retention` option and will override it if both are specified.| | -|**bucket_name**| S3 bucket name where backups will be stored| * | -|**access_key**| S3 access key with permission to access the backup bucket.| * | -|**secret_key** |S3 secret key with permission to access the backup bucket.| * | -|**region** |S3 region for the backup bucket. This is optional.| * | -|**endpoint** |S3 regions endpoint for the backup bucket.| * | - -
- - -```yaml -services: - etcd: - backup_config: - interval_hours: 12 - retention: 6 - s3backupconfig: - access_key: S3_ACCESS_KEY - secret_key: S3_SECRET_KEY - bucket_name: s3-bucket-name - region: "" - endpoint: s3.amazonaws.com -``` - -#### Prior to v0.2.0 - -|Option|Description| -|---|---| -|**Snapshot**|By default, the recurring snapshot service is disabled. To enable the service, you need to define it as part of `etcd` and set it to `true`.| -|**Creation**|By default, the snapshot service will take snapshots every 5 minutes (`5m0s`). You can change the time between snapshots as part of the `creation` directive for the `etcd` service.| -|**Retention**|By default, all snapshots are saved for 24 hours (`24h`) before being deleted and purged. You can change how long to store a snapshot as part of the `retention` directive for the `etcd` service.| - -```yaml -services: - etcd: - snapshot: true - creation: 5m0s - retention: 24h -``` - -## Etcd Disaster Recovery - -If there is a disaster with your Kubernetes cluster, you can use `rke etcd snapshot-restore` to recover your etcd. This command reverts etcd to a specific snapshot. RKE also removes the old `etcd` container before creating a new `etcd` cluster using the snapshot that you have chosen. - ->**Warning:** Restoring an etcd snapshot deletes your current etcd cluster and replaces it with a new one. Before you run the `rke etcd snapshot-restore` command, you should back up any important data in your cluster. - -The snapshot used to restore your etcd cluster can either be stored locally in `/opt/rke/etcd-snapshots` or from a S3 compatible backend. The S3 backend option is available as of v0.2.0. - -### Options for `rke etcd snapshot-restore` - -| Option | Description | S3 Specific | -| --- | --- | ---| -| `--name` value | Specify snapshot name | | -| `--config` value | Specify an alternate cluster YAML file (default: "cluster.yml") [$RKE_CONFIG] | | -| `--s3` | Enabled backup to s3 |* | -| `--s3-endpoint` value | Specify s3 endpoint url (default: "s3.amazonaws.com") | * | -| `--access-key` value | Specify s3 accessKey | *| -| `--secret-key` value | Specify s3 secretKey | *| -| `--bucket-name` value | Specify s3 bucket name | *| -| `--region` value | Specify the s3 bucket location (optional) | *| -| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | | -| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | - -### Example of Restoring from a Local Snapshot - -When restoring etcd from a local snapshot, the snapshot is assumed to be located in `/opt/rke/etcd-snapshots`. In versions prior to v0.2.0, the `pki.bundle.tar.gz` file is also expected to be in the same location. As of v0.2.0, this file is no longer needed as v0.2.0 has changed how the [Kubernetes cluster state is stored]({{< baseurl >}}/rke/latest/en/installation/#kubernetes-cluster-state). - -``` -$ rke etcd snapshot-restore --config cluster.yml --name mysnapshot -``` - -### Example of Restoring from a Snapshot in S3 - -_Available as of v0.2.0_ - -> **Note:** Ensure your `cluster.rkestate` is present before starting the restore, as 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 -$ rke etcd snapshot-restore --config cluster.yml --name snapshot-name \ ---s3 --access-key S3_ACCESS_KEY --secret-key S3_SECRET_KEY \ ---bucket-name s3-bucket-name --s3-endpoint s3.amazonaws.com -``` -> **Note:** if you were restoring a cluster that had rancher installed the UI should start-up after a few minutes; you don't need to re-run helm. - -### Example Scenario of restoring from a Local Snapshot - -In this example, the Kubernetes cluster was deployed on two AWS nodes. - -| Name | IP | Role | -|:-----:|:--------:|:----------------------:| -| node1 | 10.0.0.1 | [controlplane, worker] | -| node2 | 10.0.0.2 | [etcd] | - -### Back up the `etcd` cluster - -Take a local snapshot of the Kubernetes cluster. As of v0.2.0, you can also upload this snapshot directly to a S3 backend with the [S3 options](#options-for-rke-etcd-snapshot-save). - -``` -$ rke etcd snapshot-save --name snapshot.db --config cluster.yml -``` - -![etcd snapshot]({{< baseurl >}}/img/rke/rke-etcd-backup.png) - - -### Store the Snapshot Externally in S3 - -As of v0.2.0, this step is no longer required, as RKE can upload and download snapshots automatically from S3 by adding in [S3 options](#options-for-rke-etcd-snapshot-save) when running the `rke etcd snapshot-save` command. - -After taking the etcd snapshot on `node2`, we recommend saving this backup in a persistence place. One of the options is to save the backup and `pki.bundle.tar.gz` file on a S3 bucket or tape backup. - -> **Note:** As of v0.2.0, the file **pki.bundle.tar.gz** is no longer required for the restore process. - -``` -# If you're using an AWS host and have the ability to connect to S3 -root@node2:~# s3cmd mb s3://rke-etcd-backup -root@node2:~# s3cmd /opt/rke/etcd-snapshots/snapshot.db /opt/rke/etcd-snapshots/pki.bundle.tar.gz s3://rke-etcd-backup/ -``` - -### Place the backup on a new node - -To simulate the failure, let's power down `node2`. - -``` -root@node2:~# poweroff -``` - -| Name | IP | Role | -|:-----:|:--------:|:----------------------:| -| node1 | 10.0.0.1 | [controlplane, worker] | -| ~~node2~~ | ~~10.0.0.2~~ | ~~[etcd]~~ | -| node3 | 10.0.0.3 | [etcd] | -| | | | - - -Before restoring etcd and running `rke up`, we need to retrieve the backup saved on S3 to a new node, e.g. `node3`. As of v0.2.0, you can directly retrieve the snapshot from S3 when running the restore command, so this step is for users who stored the snapshot externally without using the integrated S3 options. - -``` -# Make a Directory -root@node3:~# mkdir -p /opt/rke/etcdbackup -# Get the Backup from S3 -root@node3:~# s3cmd get s3://rke-etcd-backup/snapshot.db /opt/rke/etcd-snapshots/snapshot.db -# Get the pki bundle from S3, only needed prior to v0.2.0 -root@node3:~# s3cmd get s3://rke-etcd-backup/pki.bundle.tar.gz /opt/rke/etcd-snapshots/pki.bundle.tar.gz -``` - -### Restore `etcd` on the new node from the backup - -Before updating and restoring etcd, you will need to add the new node into the Kubernetes cluster with the `etcd` role. In the `cluster.yml`, comment out the old node and add in the new node. ` - -```yaml -nodes: - - address: 10.0.0.1 - hostname_override: node1 - user: ubuntu - role: - - controlplane - - worker -# - address: 10.0.0.2 -# hostname_override: node2 -# user: ubuntu -# role: -# - etcd - - address: 10.0.0.3 - hostname_override: node3 - user: ubuntu - role: - - etcd -``` - -After the new node is added to the `cluster.yml`, run `rke etcd snapshot-restore` to launch `etcd` from the backup. The snapshot and `pki.bundle.tar.gz` file are expected to be saved at `/opt/rke/etcd-snapshots`. -As of v0.2.0, if you want to directly retrieve the snapshot from S3, add in the [S3 options](#options-for-rke-etcd-snapshot-restore). - -> **Note:** As of v0.2.0, the file **pki.bundle.tar.gz** is no longer required for the restore process as the certificates required to restore are preserved within the `cluster.rkestate` - -``` -$ rke etcd snapshot-restore --name snapshot.db --config cluster.yml -``` - -Finally, we need to restore the operations on the cluster by making the Kubernetes API point to the new `etcd` by running `rke up` again using the new `cluster.yml`. - -``` -$ rke up --config cluster.yml -``` - -Confirm that your Kubernetes cluster is functional by checking the pods on your cluster. - -``` -> kubectl get pods -NAME READY STATUS RESTARTS AGE -nginx-65899c769f-kcdpr 1/1 Running 0 17s -nginx-65899c769f-pc45c 1/1 Running 0 17s -nginx-65899c769f-qkhml 1/1 Running 0 17s -``` +These [example scenarios]({{}}/rke/latest/en/etcd-snapshots/example-scenarios) for backup and restore are different based on your version of RKE. ## Troubleshooting -As of **v0.1.9**, the **rke-bundle-cert** container is removed on both success and failure of a restore. To debug any issues, you will need to look at the **logs** generated from rke. - -As of **v0.1.8** and below, the **rke-bundle-cert** container is left over from a failed etcd restore. If you are having an issue with restoring an **etcd snapshot** then you can do the following on each etcd nodes before attempting to do another restore: - -``` -docker container rm --force rke-bundle-cert -``` - -The rke-bundle-cert container is usually removed when a backup or restore of **etcd** succeeds. Whenever something goes wrong, the **rke-bundle-cert** container will be left over. You can look -at the logs or inspect the container to see what the issue is. - -``` -docker container logs --follow rke-bundle-cert -docker container inspect rke-bundle-cert -``` - -The important thing to note is the mounts of the container and location of the **pki.bundle.tar.gz**. +If you have trouble restoring your cluster, you can refer to the [troubleshooting]({{}}/rke/latest/en/etcd-snapshots/troubleshooting) page. diff --git a/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md b/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md new file mode 100644 index 00000000000..5ddd113ff71 --- /dev/null +++ b/content/rke/latest/en/etcd-snapshots/example-scenarios/_index.md @@ -0,0 +1,253 @@ +--- +title: Example Scenarios +weight: 4 +--- + +These example scenarios for backup and restore are different based on your version of RKE. + +{{% tabs %}} +{{% tab "RKE v0.2.0+" %}} + +This walkthrough will demonstrate how to restore an etcd cluster from a local snapshot with the following steps: + +1. [Back up the cluster](#1-back-up-the-cluster) +1. [Simulate a node failure](#2-simulate-a-node-failure) +1. [Add a new etcd node to the cluster](#3-add-a-new-etcd-node-to-the-kubernetes-cluster) +1. [Restore etcd on the new node from the backup](#4-restore-etcd-on-the-new-node-from-the-backup) +1. [Confirm that cluster operations are restored](#5-confirm-that-cluster-operations-are-restored) + +In this example, the Kubernetes cluster was deployed on two AWS nodes. + +| Name | IP | Role | +|:-----:|:--------:|:----------------------:| +| node1 | 10.0.0.1 | [controlplane, worker] | +| node2 | 10.0.0.2 | [etcd] | + + +### 1. Back Up the Cluster + +Take a local snapshot of the Kubernetes cluster. + +You can upload this snapshot directly to an S3 backend with the [S3 options]({{}}/rke/latest/en/etcd-snapshots/one-time-snapshots/#options-for-rke-etcd-snapshot-save). + +``` +$ rke etcd snapshot-save --name snapshot.db --config cluster.yml +``` + +![etcd snapshot]({{< baseurl >}}/img/rke/rke-etcd-backup.png) + +### 2. Simulate a Node Failure + +To simulate the failure, let's power down `node2`. + +``` +root@node2:~# poweroff +``` + +| Name | IP | Role | +|:-----:|:--------:|:----------------------:| +| node1 | 10.0.0.1 | [controlplane, worker] | +| ~~node2~~ | ~~10.0.0.2~~ | ~~[etcd]~~ | + +### 3. Add a New etcd Node to the Kubernetes Cluster + +Before updating and restoring etcd, you will need to add the new node into the Kubernetes cluster with the `etcd` role. In the `cluster.yml`, comment out the old node and add in the new node. + +```yaml +nodes: + - address: 10.0.0.1 + hostname_override: node1 + user: ubuntu + role: + - controlplane + - worker +# - address: 10.0.0.2 +# hostname_override: node2 +# user: ubuntu +# role: +# - etcd + - address: 10.0.0.3 + hostname_override: node3 + user: ubuntu + role: + - etcd +``` + +### 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. + +After the new node is added to the `cluster.yml`, run the `rke etcd snapshot-restore` to launch `etcd` from the backup: + +``` +$ rke etcd snapshot-restore --name snapshot.db --config cluster.yml +``` + +The snapshot is expected to be saved at `/opt/rke/etcd-snapshots`. + +If you want to directly retrieve the snapshot from S3, add in the [S3 options](#options-for-rke-etcd-snapshot-restore). + +> **Note:** As of v0.2.0, the file `pki.bundle.tar.gz` is no longer required for the restore process because the certificates required to restore are preserved within the `cluster.rkestate`. + +### 5. Confirm that Cluster Operations are Restored + +The `rke etcd snapshot-restore` command triggers `rke up` using the new `cluster.yml`. Confirm that your Kubernetes cluster is functional by checking the pods on your cluster. + +``` +> kubectl get pods +NAME READY STATUS RESTARTS AGE +nginx-65899c769f-kcdpr 1/1 Running 0 17s +nginx-65899c769f-pc45c 1/1 Running 0 17s +nginx-65899c769f-qkhml 1/1 Running 0 17s +``` + +{{% /tab %}} +{{% tab "RKE prior to v0.2.0" %}} + +This walkthrough will demonstrate how to restore an etcd cluster from a local snapshot with the following steps: + +1. [Take a local snapshot of the cluster](#take-a-local-snapshot-of-the-cluster-rke-prior-to-v0.2.0) +1. [Store the snapshot externally](#store-the-snapshot-externally-rke-prior-to-v0.2.0) +1. [Simulate a node failure](#simulate-a-node-failure-rke-prior-to-v0.2.0) +1. [Remove the Kubernetes cluster and clean the nodes](#remove-the-kubernetes-cluster-and-clean-the-nodes-rke-prior-to-v0.2.0) +1. [Retrieve the backup and place it on a new node](#retrieve-the-backup-and-place-it-on-a-new-node-rke-prior-to-v0.2.0) +1. [Add a new etcd node to the Kubernetes cluster](#add-a-new-etcd-node-to-the-kubernetes-cluster-rke-prior-to-v0.2.0) +1. [Restore etcd on the new node from the backup](#restore-etcd-on-the-new-node-from-the-backup-rke-prior-to-v0.2.0) +1. [Restore Operations on the Cluster](#restore-operations-on-the-cluster-rke-prior-to-v0.2.0) + +### Example Scenario of restoring from a Local Snapshot + +In this example, the Kubernetes cluster was deployed on two AWS nodes. + +| Name | IP | Role | +|:-----:|:--------:|:----------------------:| +| node1 | 10.0.0.1 | [controlplane, worker] | +| node2 | 10.0.0.2 | [etcd] | + +
+### 1. Take a Local Snapshot of the Cluster + +Back up the Kubernetes cluster by taking a local snapshot: + +``` +$ rke etcd snapshot-save --name snapshot.db --config cluster.yml +``` + +![etcd snapshot]({{< baseurl >}}/img/rke/rke-etcd-backup.png) + + +### 2. Store the Snapshot Externally + +After taking the etcd snapshot on `node2`, we recommend saving this backup in a persistent place. One of the options is to save the backup and `pki.bundle.tar.gz` file on an S3 bucket or tape backup. + +``` +# If you're using an AWS host and have the ability to connect to S3 +root@node2:~# s3cmd mb s3://rke-etcd-backup +root@node2:~# s3cmd \ + /opt/rke/etcd-snapshots/snapshot.db \ + /opt/rke/etcd-snapshots/pki.bundle.tar.gz \ + s3://rke-etcd-backup/ +``` + + +### 3. Simulate a Node Failure + +To simulate the failure, let's power down `node2`. + +``` +root@node2:~# poweroff +``` + +| Name | IP | Role | +|:-----:|:--------:|:----------------------:| +| node1 | 10.0.0.1 | [controlplane, worker] | +| ~~node2~~ | ~~10.0.0.2~~ | ~~[etcd]~~ | + + +### 4. Remove the Kubernetes Cluster and Clean the Nodes + +The following command removes your cluster and cleans the nodes so that the cluster can be restored without any conflicts: + +``` +rke remove --config rancher-cluster.yml +``` + + +### 5. Retrieve the Backup and Place it On a New Node + +Before restoring etcd and running `rke up`, we need to retrieve the backup saved on S3 to a new node, e.g. `node3`. + +``` +# Make a Directory +root@node3:~# mkdir -p /opt/rke/etcdbackup + +# Get the Backup from S3 +root@node3:~# s3cmd get \ + s3://rke-etcd-backup/snapshot.db \ + /opt/rke/etcd-snapshots/snapshot.db + +# Get the pki bundle from S3 +root@node3:~# s3cmd get \ + s3://rke-etcd-backup/pki.bundle.tar.gz \ + /opt/rke/etcd-snapshots/pki.bundle.tar.gz +``` + +> **Note:** If you had multiple etcd nodes, you would have to manually sync the snapshot and `pki.bundle.tar.gz` across all of the etcd nodes in the cluster. + + +### 6. Add a New etcd Node to the Kubernetes Cluster + +Before updating and restoring etcd, you will need to add the new node into the Kubernetes cluster with the `etcd` role. In the `cluster.yml`, comment out the old node and add in the new node. ` + +```yaml +nodes: + - address: 10.0.0.1 + hostname_override: node1 + user: ubuntu + role: + - controlplane + - worker +# - address: 10.0.0.2 +# hostname_override: node2 +# user: ubuntu +# role: +# - etcd + - address: 10.0.0.3 + hostname_override: node3 + user: ubuntu + role: + - etcd +``` + + +### 7. Restore etcd on the New Node from the Backup + +After the new node is added to the `cluster.yml`, run the `rke etcd snapshot-restore` command to launch `etcd` from the backup: + +``` +$ rke etcd snapshot-restore --name snapshot.db --config cluster.yml +``` + +The snapshot and `pki.bundle.tar.gz` file are expected to be saved at `/opt/rke/etcd-snapshots` on each etcd node. + + +### 8. Restore Operations on the Cluster + +Finally, we need to restore the operations on the cluster. We will make the Kubernetes API point to the new `etcd` by running `rke up` again using the new `cluster.yml`. + +``` +$ rke up --config cluster.yml +``` + +Confirm that your Kubernetes cluster is functional by checking the pods on your cluster. + +``` +> kubectl get pods +NAME READY STATUS RESTARTS AGE +nginx-65899c769f-kcdpr 1/1 Running 0 17s +nginx-65899c769f-pc45c 1/1 Running 0 17s +nginx-65899c769f-qkhml 1/1 Running 0 17s +``` + +{{% /tab %}} +{{% /tabs %}} \ No newline at end of file diff --git a/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md new file mode 100644 index 00000000000..e9215aa71f5 --- /dev/null +++ b/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md @@ -0,0 +1,92 @@ +--- +title: One-time Snapshots +weight: 1 +--- + +One-time snapshots are handled differently depending on your version of RKE. + +{{% tabs %}} +{{% tab "RKE v0.2.0+" %}} + +To save a snapshot of etcd from each etcd node in the cluster config file, run the `rke etcd snapshot-save` command. + +The snapshot is saved in `/opt/rke/etcd-snapshots`. + +When running the command, an additional container is created to take the snapshot. When the snapshot is completed, the container is automatically removed. + +The one-time snapshot can be uploaded to a S3 compatible backend by using the additional options to specify the S3 backend. + +To create a local one-time snapshot, run: + +``` +$ rke etcd snapshot-save --config cluster.yml --name snapshot-name +``` + +**Result:** The snapshot is saved in `/opt/rke/etcd-snapshots`. + +To save a one-time snapshot to S3, run: + +``` +$ rke etcd snapshot-save \ +--config cluster.yml \ +--name snapshot-name \ +--s3 \ +--access-key S3_ACCESS_KEY \ +--secret-key S3_SECRET_KEY \ +--bucket-name s3-bucket-name \ +--s3-endpoint s3.amazonaws.com +``` + +**Result:** The snapshot is saved in `/opt/rke/etcd-snapshots` as well as uploaded to the S3 backend. + +### Options for `rke etcd snapshot-save` + +| Option | Description | S3 Specific | +| --- | --- | --- | +| `--name` value | Specify snapshot name | | +| `--config` value | Specify an alternate cluster YAML file (default: `cluster.yml`) [$RKE_CONFIG] | | +| `--s3` | Enabled backup to s3 | * | +| `--s3-endpoint` value | Specify s3 endpoint url (default: "s3.amazonaws.com") | * | +| `--access-key` value | Specify s3 accessKey | * | +| `--secret-key` value | Specify s3 secretKey | * | +| `--bucket-name` value | Specify s3 bucket name | * | +| `--region` value | Specify the s3 bucket location (optional) | * | +| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | | +| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | + +### IAM Support for Storing Snapshots in S3 + +In addition to API access keys, RKE supports using IAM roles for S3 authentication. The cluster etcd nodes must be assigned an IAM role that has read/write access to the designated backup bucket on S3. Also, the nodes must have network access to the S3 endpoint specified. + + To give an application access to S3, refer to the AWS documentation on [Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances.](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) + + + +{{% /tab %}} +{{% tab "RKE prior to v0.2.0" %}} + +To save a snapshot of etcd from each etcd node in the cluster config file, run the `rke etcd snapshot-save` command. + +When running the command, an additional container is created to take the snapshot. When the snapshot is completed, the container is automatically removed. + +RKE saves a backup of the certificates, i.e. a file named `pki.bundle.tar.gz`, in the same location. The snapshot and pki bundle file are required for the restore process. + +To create a local one-time snapshot, run: + +``` +$ rke etcd snapshot-save --config cluster.yml --name snapshot-name +``` + +**Result:** The snapshot is saved in `/opt/rke/etcd-snapshots`. + +### Options for `rke etcd snapshot-save` + +| Option | Description | +| --- | --- | +| `--name` value | Specify snapshot name | +| `--config` value | Specify an alternate cluster YAML file (default: `cluster.yml`) [$RKE_CONFIG] | +| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | +| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | + +{{% /tab %}} +{{% /tabs %}} \ No newline at end of file diff --git a/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md new file mode 100644 index 00000000000..913200ac2f4 --- /dev/null +++ b/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md @@ -0,0 +1,97 @@ +--- +title: Recurring Snapshots +weight: 2 +--- + +Recurring snapshots are handled differently based on your version of RKE. + +{{% tabs %}} +{{% tab "RKE v0.2.0+"%}} + +To schedule automatic recurring etcd snapshots, you can enable the `etcd-snapshot` service with [extra configuration options](#options-for-the-etcd-snapshot-service). `etcd-snapshot` runs in a service container alongside the `etcd` container. By default, the `etcd-snapshot` service takes a snapshot for every node that has the `etcd` role and stores them to local disk in `/opt/rke/etcd-snapshots`. + +If you set up the [options for S3](#options-for-the-etcd-snapshot-service), the snapshot will also be uploaded to the S3 backend. + +### Snapshot Service Logging + +When a cluster is launched with the `etcd-snapshot` service enabled, you can view the `etcd-rolling-snapshots` logs to confirm backups are being created automatically. + +``` +$ docker logs etcd-rolling-snapshots + +time="2018-05-04T18:39:16Z" level=info msg="Initializing Rolling Backups" creation=1m0s retention=24h0m0s +time="2018-05-04T18:40:16Z" level=info msg="Created backup" name="2018-05-04T18:40:16Z_etcd" runtime=108.332814ms +time="2018-05-04T18:41:16Z" level=info msg="Created backup" name="2018-05-04T18:41:16Z_etcd" runtime=92.880112ms +time="2018-05-04T18:42:16Z" level=info msg="Created backup" name="2018-05-04T18:42:16Z_etcd" runtime=83.67642ms +time="2018-05-04T18:43:16Z" level=info msg="Created backup" name="2018-05-04T18:43:16Z_etcd" runtime=86.298499ms +``` + +### Options for the `Etcd-Snapshot` Service + +|Option|Description| S3 Specific | +|---|---| --- | +|**interval_hours**| The duration in hours between recurring backups. This supercedes the `creation` option (which was used in RKE prior to v0.2.0) and will override it if both are specified.| | +|**retention**| The number of snapshots to retain before rotation. This supercedes the `retention` option and will override it if both are specified.| | +|**bucket_name**| S3 bucket name where backups will be stored| * | +|**access_key**| S3 access key with permission to access the backup bucket.| * | +|**secret_key** |S3 secret key with permission to access the backup bucket.| * | +|**region** |S3 region for the backup bucket. This is optional.| * | +|**endpoint** |S3 regions endpoint for the backup bucket.| * | + +### Configuring the Snapshot Service in YAML + +```yaml +services: + etcd: + backup_config: + interval_hours: 12 + retention: 6 + s3backupconfig: + access_key: S3_ACCESS_KEY + secret_key: S3_SECRET_KEY + bucket_name: s3-bucket-name + region: "" + endpoint: s3.amazonaws.com +``` + +{{% /tab %}} +{{% tab "RKE prior to v0.2.0"%}} + +To schedule automatic recurring etcd snapshots, you can enable the `etcd-snapshot` service with [extra configuration options](#options-for-the-local-etcd-snapshot-service). `etcd-snapshot` runs in a service container alongside the `etcd` container. By default, the `etcd-snapshot` service takes a snapshot for every node that has the `etcd` role and stores them to local disk in `/opt/rke/etcd-snapshots`. + +RKE saves a backup of the certificates, i.e. a file named `pki.bundle.tar.gz`, in the same location. The snapshot and pki bundle file are required for the restore process in versions prior to v0.2.0. + +### Snapshot Service Logging + +When a cluster is launched with the `etcd-snapshot` service enabled, you can view the `etcd-rolling-snapshots` logs to confirm backups are being created automatically. + +``` +$ docker logs etcd-rolling-snapshots + +time="2018-05-04T18:39:16Z" level=info msg="Initializing Rolling Backups" creation=1m0s retention=24h0m0s +time="2018-05-04T18:40:16Z" level=info msg="Created backup" name="2018-05-04T18:40:16Z_etcd" runtime=108.332814ms +time="2018-05-04T18:41:16Z" level=info msg="Created backup" name="2018-05-04T18:41:16Z_etcd" runtime=92.880112ms +time="2018-05-04T18:42:16Z" level=info msg="Created backup" name="2018-05-04T18:42:16Z_etcd" runtime=83.67642ms +time="2018-05-04T18:43:16Z" level=info msg="Created backup" name="2018-05-04T18:43:16Z_etcd" runtime=86.298499ms +``` + +### Options for the Local `Etcd-Snapshot` Service + +|Option|Description| +|---|---| +|**Snapshot**|By default, the recurring snapshot service is disabled. To enable the service, you need to define it as part of `etcd` and set it to `true`.| +|**Creation**|By default, the snapshot service will take snapshots every 5 minutes (`5m0s`). You can change the time between snapshots as part of the `creation` directive for the `etcd` service.| +|**Retention**|By default, all snapshots are saved for 24 hours (`24h`) before being deleted and purged. You can change how long to store a snapshot as part of the `retention` directive for the `etcd` service.| + +### Configuring the Snapshot Service in YAML + +```yaml +services: + etcd: + snapshot: true + creation: 5m0s + retention: 24h +``` + +{{% /tab %}} +{{% /tabs %}} \ No newline at end of file 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 new file mode 100644 index 00000000000..57f6f2ef008 --- /dev/null +++ b/content/rke/latest/en/etcd-snapshots/restoring-from-backup/_index.md @@ -0,0 +1,112 @@ +--- +title: Restoring from Backup +weight: 3 +--- + +The details of restoring your cluster from backup are different depending on your version of RKE. + +{{% tabs %}} +{{% tab "RKE v0.2.0+"%}} + +If there is a disaster with your Kubernetes cluster, you can use `rke etcd snapshot-restore` to recover your etcd. This command reverts the etcd to a specific snapshot. The following actions are included in the command: + +- Syncs the snapshot or downloads the snapshot from S3, if necessary. +- Checks snapshot checksum across etcd nodes to make sure they are identical. +- Deletes your current cluster and cleans old data by running `rke remove`. This removes the entire Kubernetes cluster, not just the etcd cluster. +- Rebuilds the etcd cluster from the chosen snapshot. +- Creates a new cluster by running `rke up`. +- Restarts cluster system pods. + +>**Warning:** You should back up any important data in your cluster before running `rke etcd snapshot-restore` because the command deletes your current Kubernetes cluster and replaces it with a new one. + +The snapshot used to restore your etcd cluster can either be stored locally in `/opt/rke/etcd-snapshots` or from a S3 compatible backend. + +### Example of Restoring from a Local Snapshot + +To restore etcd from a local snapshot, run: + +``` +$ rke etcd snapshot-restore --config cluster.yml --name mysnapshot +``` + +The snapshot is assumed to be located in `/opt/rke/etcd-snapshots`. + +**Note:** The `pki.bundle.tar.gz` file is not needed because RKE v0.2.0 changed how the [Kubernetes cluster state is stored]({{< baseurl >}}/rke/latest/en/installation/#kubernetes-cluster-state). + +### 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 +$ rke etcd snapshot-restore \ +--config cluster.yml \ +--name snapshot-name \ +--s3 \ +--access-key S3_ACCESS_KEY \ +--secret-key S3_SECRET_KEY \ +--bucket-name s3-bucket-name \ +--s3-endpoint s3.amazonaws.com +``` +**Note:** if you were restoring a cluster that had Rancher installed, the Rancher UI should start up after a few minutes; you don't need to re-run Helm. + +### Options for `rke etcd snapshot-restore` + +| Option | Description | S3 Specific | +| --- | --- | ---| +| `--name` value | Specify snapshot name | | +| `--config` value | Specify an alternate cluster YAML file (default: `cluster.yml`) [$RKE_CONFIG] | | +| `--s3` | Enabled backup to s3 |* | +| `--s3-endpoint` value | Specify s3 endpoint url (default: "s3.amazonaws.com") | * | +| `--access-key` value | Specify s3 accessKey | *| +| `--secret-key` value | Specify s3 secretKey | *| +| `--bucket-name` value | Specify s3 bucket name | *| +| `--region` value | Specify the s3 bucket location (optional) | *| +| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | | +| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | + +{{% /tab %}} +{{% tab "RKE prior to v0.2.0"%}} + +If there is a disaster with your Kubernetes cluster, you can use `rke etcd snapshot-restore` to recover your etcd. This command reverts etcd to a specific snapshot. + +The following actions are included in `rke etcd snapshot-restore`: + +- Removes the old etcd cluster +- Rebuilds the etcd cluster using the local snapshot + +Before you run this command, you must: + +- Run `rke remove` to remove your Kubernetes cluster and clean the nodes +- Download your etcd snapshot from S3, if applicable. Place the etcd snapshot and the `pki.bundle.tar.gz` file in `/opt/rke/etcd-snapshots`. Manually sync the snapshot across all `etcd` nodes. + +After the restore, you must rebuild your Kubernetes cluster with `rke up`. + +>**Warning:** You should back up any important data in your cluster before running `rke etcd snapshot-restore` because the command deletes your current etcd cluster and replaces it with a new one. + +### Example of Restoring from a Local Snapshot + +To restore etcd from a local snapshot, run: + +``` +$ rke etcd snapshot-restore --config cluster.yml --name mysnapshot +``` + +The snapshot is assumed to be located in `/opt/rke/etcd-snapshots`. + +The snapshot must be manually synched across all `etcd` nodes. + +The `pki.bundle.tar.gz` file is also expected to be in the same location. + +### Options for `rke etcd snapshot-restore` + +| Option | Description | +| --- | --- | +| `--name` value | Specify snapshot name | +| `--config` value | Specify an alternate cluster YAML file (default: `cluster.yml`) [$RKE_CONFIG] | +| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | +| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | + +{{% /tab %}} +{{% /tabs %}} \ No newline at end of file diff --git a/content/rke/latest/en/etcd-snapshots/troubleshooting/_index.md b/content/rke/latest/en/etcd-snapshots/troubleshooting/_index.md new file mode 100644 index 00000000000..372142f649a --- /dev/null +++ b/content/rke/latest/en/etcd-snapshots/troubleshooting/_index.md @@ -0,0 +1,22 @@ +--- +title: Troubleshooting +weight: 5 +--- + +As of **v0.1.9**, the **rke-bundle-cert** container is removed on both success and failure of a restore. To debug any issues, you will need to look at the **logs** generated from rke. + +As of **v0.1.8** and below, the **rke-bundle-cert** container is left over from a failed etcd restore. If you are having an issue with restoring an **etcd snapshot** then you can do the following on each etcd nodes before attempting to do another restore: + +``` +docker container rm --force rke-bundle-cert +``` + +The rke-bundle-cert container is usually removed when a backup or restore of **etcd** succeeds. Whenever something goes wrong, the **rke-bundle-cert** container will be left over. You can look +at the logs or inspect the container to see what the issue is. + +``` +docker container logs --follow rke-bundle-cert +docker container inspect rke-bundle-cert +``` + +The important thing to note is the mounts of the container and location of the `pki.bundle.tar.gz`. From 4f543ca7c68be7b74b15db600a512edb086ed971 Mon Sep 17 00:00:00 2001 From: Craig Jellick Date: Thu, 5 Sep 2019 18:56:47 -0700 Subject: [PATCH 22/25] address review comments --- .../install-rancher/_index.md | 27 +++++++++++++++---- .../prepare-private-registry/_index.md | 2 ++ .../en/installation/ha/helm-rancher/_index.md | 4 +-- .../options/upgrading-cert-manager/_index.md | 10 ++++--- .../ha-server-upgrade-helm-airgap/_index.md | 2 +- .../upgrades/ha-server-upgrade-helm/_index.md | 4 +-- 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md index 83071b85249..acabfbe8f7e 100644 --- a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md @@ -57,7 +57,7 @@ By default, Rancher generates a CA and uses cert-manager to issue the certificat > **Note:** > Recent changes to cert-manager require an upgrade. If you are upgrading Rancher and using a version of cert-manager older than v0.9.1, please see our [upgrade documentation]({{< baseurl >}}/rancher/v2.x/en/installation/options/upgrading-cert-manager/). -1. From a system connected to the internet, add the cert-manager repo to helm +1. From a system connected to the internet, add the cert-manager repo to Helm. ```plain helm repo add jetstack https://charts.jetstack.io @@ -76,6 +76,8 @@ By default, Rancher generates a CA and uses cert-manager to issue the certificat helm template ./cert-manager-v0.9.1.tgz --output-dir . \ --name cert-manager --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 ``` 1. Download the required CRD file for cert-manager @@ -149,10 +151,25 @@ Use `kubectl` to create namespaces and apply the rendered manifests. If you are using self-signed certificates, install cert-manager: -```plain -kubectl apply -f cert-manager/cert-manager-crd.yaml -kubectl -n cert-manager apply -R -f ./cert-manager -``` +1. Create the namespace for cert-manager. + ```plain + kubectl create namespace cert-manager + ``` + +1. Label the cert-manager namespace to disable resource validation. + ```plain + kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true + ``` + +1. Create the cert-manager CustomResourceDefinitions (CRDs). + ```plain + kubectl apply -f cert-manager/cert-manager-crd.yaml + ``` + +1. Launch cert-manager. + ```plain + kubectl apply -R -f ./cert-manager + ``` Install rancher: diff --git a/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md b/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md index 22b18c3e6a1..bf699e4bba1 100644 --- a/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md +++ b/content/rancher/v2.x/en/installation/air-gap-high-availability/prepare-private-registry/_index.md @@ -49,6 +49,8 @@ Start by collecting all the images needed to install Rancher in an air gap envir 1. Fetch the latest `cert-manager` Helm chart and parse the template for image details. + > **Note:** Recent changes to cert-manager require an upgrade. If you are upgrading Rancher and using a version of cert-manager older than v0.9.1, please see our [upgrade documentation]({{< baseurl >}}/rancher/v2.x/en/installation/options/upgrading-cert-manager/). + ```plain helm repo add jetstack https://charts.jetstack.io helm repo update diff --git a/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md b/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md index ce6e551f9be..601855b1d75 100644 --- a/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/ha/helm-rancher/_index.md @@ -33,7 +33,7 @@ There are three recommended options for the source of the certificate. ### Optional: Install cert-manager -> **Note:** cert-manager is only required for certificates issued by Rancher's generated CA (`ingress.tls.source=rancher`) and Let's Encrypt issued certificates (`ingress.tls.source=letsEncrypt`). You should skip this step if you are using your own certificate files (option `ingress.tls.source=secret`) or if you use [TLS termination on an External Load Balancer]({{< baseurl >}}/rancher/v2.x/en/installation/ha/helm-rancher/chart-options/#external-tls-termination). +**Note:** cert-manager is only required for certificates issued by Rancher's generated CA (`ingress.tls.source=rancher`) and Let's Encrypt issued certificates (`ingress.tls.source=letsEncrypt`). You should skip this step if you are using your own certificate files (option `ingress.tls.source=secret`) or if you use [TLS termination on an External Load Balancer]({{< baseurl >}}/rancher/v2.x/en/installation/ha/helm-rancher/chart-options/#external-tls-termination). > **Important:** @@ -83,7 +83,7 @@ These instructions are adapted from the [official cert-manager documentation](ht Once you’ve installed cert-manager, you can verify it is deployed correctly by checking the cert-manager namespace for running pods: ``` -kubectl get pods --namespace kube-system +kubectl get pods --namespace cert-manager NAME READY STATUS RESTARTS AGE cert-manager-7cbdc48784-rpgnt 1/1 Running 0 3m diff --git a/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md b/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md index d898013bb8f..9458da3fd59 100644 --- a/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md +++ b/content/rancher/v2.x/en/installation/options/upgrading-cert-manager/_index.md @@ -3,7 +3,7 @@ title: Upgrading Cert-Manager weight: 2040 --- -Rancher uses cert-manager to automatically generate and renew TLS certificates for HA deployments of Rancher. As of Fall 2019, two important changes to cert-manager are set to occur that you need to take aciton on if you have an HA deployment of Rancher: +Rancher uses cert-manager to automatically generate and renew TLS certificates for HA deployments of Rancher. As of Fall 2019, two important changes to cert-manager are set to occur that you need to take action on if you have an HA deployment of Rancher: 1. [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) 1. [Cert-manager is deprecating and replacing the certificate.spec.acme.solvers field](https://docs.cert-manager.io/en/latest/tasks/upgrading/upgrading-0.7-0.8.html#upgrading-from-v0-7-to-v0-8). This change has no exact deadline. @@ -17,7 +17,7 @@ To address these changes, this guide will do two things: ## Performing the upgrade >**Note:** The namespace used in these instructions depends on the namespace cert-manager is currently installed in. If it is in kube-system use that in the instructions below. You can verify by running `kubectl get pods --all-namespaces` and checking which namespace the cert-manager-\* pods are listed in. Do not change the namespace cert-manager is running in or this can cause issues. -In order to upgrade cert-manager to the follow these instructions: +In order to upgrade cert-manager, follow these instructions: {{% accordion id="normal" label="Upgrading cert-manager with Internet access" %}} 1. Back up existing resources as a precaution ```plain @@ -57,11 +57,11 @@ In order to upgrade cert-manager to the follow these instructions: {{% accordion id="airgap" label="Upgrading cert-manager in an airgapped environment" %}} ### Prerequisites -Before you can perform the upgrade, you must prepare your air gapped environment by adding the necesary container images to your private registry and downloading or rendering the required Kubernetes manifest files. +Before you can perform the upgrade, you must prepare your air gapped environment by adding the necessary container images to your private registry and downloading or rendering the required Kubernetes manifest files. 1. Follow the guide to [Prepare your Private Registry]({{< baseurl >}}/rancher/v2.x/en/installation/air-gap-installation/prepare-private-reg/) with the images needed for the upgrade. -1. From a system connected to the internet, add the cert-manager repo to helm +1. From a system connected to the internet, add the cert-manager repo to Helm ```plain helm repo add jetstack https://charts.jetstack.io @@ -80,6 +80,8 @@ Before you can perform the upgrade, you must prepare your air gapped environment helm template ./cert-manager-v0.9.1.tgz --output-dir . \ --name cert-manager --namespace kube-system \ --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 ``` 1. Download the required CRD file for cert-manager diff --git a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md index 8fc35406bf2..d16b051d8bd 100644 --- a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md +++ b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm-airgap/_index.md @@ -5,7 +5,7 @@ weight: 1021 The following instructions will guide you through upgrading a high-availability Rancher Server installed in an air gap environment. ->**Note:** [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow [these instructions.]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap) +>**Note:** [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) Upgrade cert-manager to the latest version by following [these instructions.]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/upgrade-cert-manager-airgap) ## Prerequisites diff --git a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md index e1a783e6a3e..9b34822a98c 100644 --- a/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md +++ b/content/rancher/v2.x/en/upgrades/upgrades/ha-server-upgrade-helm/_index.md @@ -7,13 +7,13 @@ The following instructions will guide you through upgrading a high-availability >**Note:** If you installed Rancher using the RKE Add-on yaml, see the following documents to migrate or upgrade. > ->* [Migrating from RKE Add-On Install]({{< baseurl >}}/rancher/v2.x/en/upgrades/upgrades/migrating-from-rke-add-on) +>- [Migrating from RKE Add-On Install]({{< baseurl >}}/rancher/v2.x/en/upgrades/upgrades/migrating-from-rke-add-on) > > As of release v2.0.8, Rancher supports installation and upgrade by Helm chart, although RKE installs/upgrades are still supported as well. If you want to change upgrade method from RKE Add-on to Helm chart, follow this procedure. --- ->**Note:** [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) In order to upgrade cert-manager to the newer version follow [these instructions.]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/upgrade-cert-manager) +>**Note:** [Let's Encrypt will be blocking cert-manager instances older than 0.8.0 starting November 1st 2019.](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) Upgrade cert-manager to the latest version by following [these instructions.]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/upgrade-cert-manager) ## Prerequisites From fa5973a4c42d577143c17222e4d4e962ec8bf6ff Mon Sep 17 00:00:00 2001 From: Chris Kim <30601846+Oats87@users.noreply.github.com> Date: Fri, 6 Sep 2019 11:08:45 -0700 Subject: [PATCH 23/25] Add NLB Disclaimer Add disclaimer that we do not support NLB terminating TLS connections --- .../v2.x/en/installation/ha/create-nodes-lb/nlb/_index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/rancher/v2.x/en/installation/ha/create-nodes-lb/nlb/_index.md b/content/rancher/v2.x/en/installation/ha/create-nodes-lb/nlb/_index.md index b5d4f4fcdf7..88b58cdc056 100644 --- a/content/rancher/v2.x/en/installation/ha/create-nodes-lb/nlb/_index.md +++ b/content/rancher/v2.x/en/installation/ha/create-nodes-lb/nlb/_index.md @@ -18,6 +18,7 @@ Configuring an Amazon NLB is a multistage process. We've broken it down into mul Use Amazon's Wizard to create an Network Load Balancer. As part of this process, you'll add the target groups you created in **1. Create Target Groups**. +> **Note:** Rancher only supports using the Amazon NLB when terminating traffic in `tcp` mode for port 443 rather than `tls` mode. This is due to the fact that the NLB does not inject the correct headers into requests when terminated at the NLB. This means that if you want to use certificates managed by the Amazon Certificate Manager (ACM), you should use an ELB or ALB. ## Create Target Groups From 7d1a5cfc8d66676fad169a3b8c706aa9ce18ab25 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Steenis Date: Fri, 6 Sep 2019 15:30:52 +0200 Subject: [PATCH 24/25] Add troubleshooting commands for etcd content --- .../kubernetes-components/_index.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md b/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md index fbce493de5e..1627ac79164 100644 --- a/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/kubernetes-components/_index.md @@ -361,6 +361,42 @@ Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) a curl -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv $ETCDCTL_ENDPOINT)/config/local/log ``` +### etcd content + +If you want to investigate the contents of your etcd, you can either watch streaming events or you can query etcd directly, see below for examples. + +* Watch streaming events + +Command: +``` +docker exec etcd etcdctl watch --prefix /registry +``` + +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: +``` +docker exec etcd etcdctl --endpoints=\$ETCDCTL_ENDPOINT watch --prefix /registry +``` + +If you only want to see the affected keys (and not the binary data), you can append `| grep -a ^/registry` to the command to filter for keys only. + +* Query etcd directly + +Command: +``` +docker exec etcd etcdctl get /registry --prefix=true --keys-only +``` + +Command when using etcd version lower than 3.3.x (Kubernetes 1.13.x and lower) and `--internal-address` was specified when adding the node: +``` +docker exec etcd etcdctl --endpoints=\$ETCDCTL_ENDPOINT get /registry --prefix=true --keys-only +``` + +You can process the data to get a summary of count per key, using the command below: + +``` +docker exec etcd etcdctl get /registry --prefix=true --keys-only | grep -v ^$ | awk -F'/' '{ if ($3 ~ /cattle.io/) {h[$3"/"$4]++} else { h[$3]++ }} END { for(k in h) print h[k], k }' | sort -nr +``` + ## controlplane This section applies to nodes with the `controlplane` role. From cbd327a952375041622d0099215cd055af5c9903 Mon Sep 17 00:00:00 2001 From: Catherine Luse Date: Fri, 6 Sep 2019 15:46:26 -0700 Subject: [PATCH 25/25] Include IAM policy for reading/writing S3 snapshots --- .../one-time-snapshots/_index.md | 26 ++++++++++++++-- .../recurring-snapshots/_index.md | 30 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md index e9215aa71f5..768f2c1a22a 100644 --- a/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md +++ b/content/rke/latest/en/etcd-snapshots/one-time-snapshots/_index.md @@ -54,13 +54,35 @@ $ rke etcd snapshot-save \ | `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | | | `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | +The `--access-key` and `--secret-key` options are not required if the `etcd` nodes are AWS EC2 instances that have been configured with a suitable IAM instance profile. + ### IAM Support for Storing Snapshots in S3 -In addition to API access keys, RKE supports using IAM roles for S3 authentication. The cluster etcd nodes must be assigned an IAM role that has read/write access to the designated backup bucket on S3. Also, the nodes must have network access to the S3 endpoint specified. +In addition to API access keys, RKE supports using IAM roles for S3 authentication. The cluster etcd nodes must be assigned an IAM role that has read/write access to the designated backup bucket on S3. Also, the nodes must have network access to the S3 endpoint specified. - To give an application access to S3, refer to the AWS documentation on [Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances.](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) +Below is an [example IAM policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_s3_rw-bucket.html) that would allow nodes to store and retrieve backups from S3: +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ListObjectsInBucket", + "Effect": "Allow", + "Action": ["s3:ListBucket"], + "Resource": ["arn:aws:s3:::bucket-name"] + }, + { + "Sid": "AllObjectActions", + "Effect": "Allow", + "Action": "s3:*Object", + "Resource": ["arn:aws:s3:::bucket-name/*"] + } + ] +} +``` +For details on giving an application access to S3, refer to the AWS documentation on [Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances.](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) {{% /tab %}} {{% tab "RKE prior to v0.2.0" %}} diff --git a/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md index 913200ac2f4..a5b5258964c 100644 --- a/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md +++ b/content/rke/latest/en/etcd-snapshots/recurring-snapshots/_index.md @@ -38,6 +38,36 @@ time="2018-05-04T18:43:16Z" level=info msg="Created backup" name="2018-05-04T18: |**region** |S3 region for the backup bucket. This is optional.| * | |**endpoint** |S3 regions endpoint for the backup bucket.| * | +The `--access-key` and `--secret-key` options are not required if the `etcd` nodes are AWS EC2 instances that have been configured with a suitable IAM instance profile. + +### IAM Support for Storing Snapshots in S3 + +In addition to API access keys, RKE supports using IAM roles for S3 authentication. The cluster etcd nodes must be assigned an IAM role that has read/write access to the designated backup bucket on S3. Also, the nodes must have network access to the S3 endpoint specified. + +Below is an [example IAM policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_s3_rw-bucket.html) that would allow nodes to store and retrieve backups from S3: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ListObjectsInBucket", + "Effect": "Allow", + "Action": ["s3:ListBucket"], + "Resource": ["arn:aws:s3:::bucket-name"] + }, + { + "Sid": "AllObjectActions", + "Effect": "Allow", + "Action": "s3:*Object", + "Resource": ["arn:aws:s3:::bucket-name/*"] + } + ] +} +``` + +For details on giving an application access to S3, refer to the AWS documentation on [Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances.](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) + ### Configuring the Snapshot Service in YAML ```yaml