Deliver Rancher with Cloud-init and Terraform
In my previous posts, I already showed how with a simple vanilla template and cloud-init template it’s possible to create a fully customized workload without “manual” interventions respecting the declarative methods where possible and in the same time injecting scripts able to prepare the virtual machine for the real purpose of the workload. In this post, I’ll show how to deliver a production-ready Rancher cluster following the same declarative method.
You can find the fully-function project on my GitHub repo here: https://github.com/linoproject/terraform/tree/master/rancher-lab
The single docker host method could be an easy way to test Rancher service, but it lacks resiliency and in some enterprise contexts it could result inefficient. For this reason following the official Rancher 2.x documentation, the best way to deliver Rancher is by the creation of a single-node K8S cluster using RKE (Rancher Kubernetes engine) and the Rancher installation as Helm deployment.
After docker, kubectl, and Helm and RKE (Rancher Kubernetes engine), the installation workflow is composed by:
- RKE up the first cluster
- Cert-manager installation
- Rancher installation by a Helm chart
After these steps rancher is ready to be configured with admin credentials, connections, templates,… and the first cluster. Let’s dive into the first step: the init
The init steps
The installation process is quite long and depending on your resources could result in a little bit hard to handle using a single cloud-init step. For this reason, the idea is to keep the VM preparation inside the cloud-init process and proceed using a remote-exec to inject the installation step as a flow of some imperative commands.
Checking the user-data file located under nodes/rancher/cloudinit the init steps are two:
- The file creations: the first single node cluster and the installation script could be delivered using the write_file statement, which is served before the runcmd statement.
- The environment setup commands which are running in runcmd statement and includes the first steps
At the end of the init-process the VM is prepared for the real installation. With the benefits of the template handling with Terraform, it’s possible to prepare and customize the cluster init like IP, hostname, and domain name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
write_files: - path: /home/ubuntu/rancher-cluster.yml owner: ubuntu content: | nodes: - address: ${ip} internal_address: ${ip} user: ubuntu role: [controlplane,etcd,worker] addon_job_timeout: 120 - path: /home/ubuntu/install.sh permissions: '0755' owner: ubuntu content: | #!/bin/bash rke up --config /home/ubuntu/rancher-cluster.yml mkdir -p /home/ubuntu/.kube ln -s /home/ubuntu/kube_config_rancher-cluster.yml /home/ubuntu/.kube/config kubectl create namespace cert-manager kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.12/deploy/manifests/00-crds.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm install cert-manager --namespace cert-manager --version v0.12.0 jetstack/cert-manager kubectl -n cert-manager rollout status deploy/cert-manager kubectl -n cert-manager rollout status deploy/cert-manager-webhook helm repo add rancher-latest https://releases.rancher.com/server-charts/latest helm repo update kubectl create namespace cattle-system helm install rancher rancher-latest/rancher --namespace cattle-system --set hostname=${hostname}.${domain_name} --set replicas=1 while true; do curl -kv https://${hostname}.${domain_name} 2>&1 | grep -q "dynamiclistener-ca"; if [ $? != 0 ]; then echo "Rancher isn't ready yet"; sleep 5; continue; fi; break; done; echo "Rancher is Ready"; |
Before proceeding, in order to speed up the process, I prepared the “default template” starting from another bunch of Terraform files and a single cloud-init file that contains the kick-off system (local-user and VMware vSphere cloud-init implementation like described here). After the VM creation with a simple cloud-to-template the template is ready for the real deployment. (You can check the example on my GitHub here: https://github.com/linoproject/terraform/tree/master/template-prep-adv ). This intermediate template will include:
- cloud-init VMware integration
- Kubectl, Helm, and RKE
- User ubuntu directly involved in the installation process.
Rancher installation steps
Finally, the real installation process starts with:
- RKE up based on rancher-cluster.yml config
- Cert-manager installation using Helm
- Rancher installation
During the cert-manager installation, it’s necessary to wait for the complete rollout before going ahead with the installation. Then after Rancher Helm installation, a loop is checking for the readiness of the cluster and the ability to connect with your browser to https://<hostname.domainname>.
I suggest using Firefox because it is one of the browsers that still bypass the restriction of the unverified certificate which is used in this installation. An enterprise installation should implement a real certificate issued by a real CA.
After setting the admin password it is possible to start deploying the first cluster like as seen here.
A final note
In the “main.tf” file, I introduced also a workaround way to set DNS record A with the rancher machine. It simply injects a PowerShell script able to test and add or modify the DNS record. Depending on your installation, you could skip this process by simply commenting out the null_resorce called “dnsrecord” or introducing your own automation step to correctly handle the DNS registration.
If you have any suggestions on how to improve this code, feel free to reach me via the contact form.