Kubernetes Cluster using RKE2 HA and Rancher
I will show how to install kubernetes cluster with High Availibility using RKE2 and install Rancher to manage the cluster under ubuntu. To simplify access to the application deployed in the cluster, I set up nginx as load balancer to forward domain name request to the application. Here, I use simple ansible script to install the cluster.
Server Architecture
Ansible host configuration
[allnode:children] rke2-firstnode rke2-nextnode [rke2-firstnode] rke2-node1 ansible_host=192.168.1.11 [rke2-nextnode] rke2-node2 ansible_host=192.168.1.12 rke2-node3 ansible_host=192.168.1.13
---
- hosts: allnode
  become: true
  tasks:
    - name: Copy Proxy Config
      copy:
        src: proxy
        dest: /etc/default/proxy
        mode: '0644'
      tags: [ 'envproxy', 'proxy' ]
    - name: Copy APT Proxy Config
      copy:
        src: proxy.conf
        dest: /etc/apt/apt.conf.d/proxy.conf
        mode: '0644'
      tags: [ 'aptproxy', 'proxy' ]
    - name: Insert Proxy Env
      lineinfile:
        path: /etc/environment
        line: '{{ item }}'
      with_items:
        - 'HTTP_PROXY="http://192.168.1.1:3128"'
        - 'HTTPS_PROXY="http://192.168.1.1:3128"'
        - 'NO_PROXY="127.0.0.0/8,10.0.0.0/8,192.168.1.0/16,*.mydomain.com"'
      tags: [ 'envproxy', 'proxy' ]
- hosts: rke2-firstnode
  become: true
  tasks:
    - name: create directory with parent directories
      file:
        path: /etc/rancher/rke2
        state: directory
        recurse: yes
      tags: [ 'rke-config']
    - name: create directory with parent directories
      file:
        path: /var/lib/rancher/rke2/server/manifests
        state: directory
        recurse: yes
      tags: [ 'rke-config']
    - name: Copy Master Config
      copy:
        src: config-master.yaml
        dest: /etc/rancher/rke2/config.yaml
        mode: '0644'
      tags: [ 'master','rke-config']
    - name: Run RKE2 script
      shell:
        cmd: curl -sfL https://get.rke2.io | sh -
        warn: False
      tags: [ 'download']
    - name: Add proxy in rke init script
      lineinfile:
        path: /usr/local/lib/systemd/system/rke2-server.service
        insertbefore: 'EnvironmentFile=-/etc/default/%N'
        line: EnvironmentFile=/etc/default/proxy
    - name: Copy Nginx Config
      copy:
        src: rke2-ingress-nginx-custom.yaml
        dest: /var/lib/rancher/rke2/server/manifests/rke2-ingress-nginx-custom.yaml
        mode: '0644'
      tags: [ 'master','rke-config']
    - name: Enable RKE2 script
      shell:
        cmd: systemctl enable rke2-server.service
        warn: False
    - name: Reload systemd
      shell:
        cmd: systemctl daemon-reload
        warn: False
    - name: Start RKE2 script
      shell:
        cmd: systemctl start rke2-server.service
        warn: False
- hosts: rke2-nextnode
  become: true
  tasks:
    - name: create directory with parent directories
      file:
        path: /etc/rancher/rke2
        state: directory
        recurse: yes
    - name: create directory with parent directories
      file:
        path: /var/lib/rancher/rke2/server/manifests
        state: directory
        recurse: yes
      tags: [ 'rke-config']
    - name: Copy Slave Config
      copy:
        src: config-slave.yaml
        dest: /etc/rancher/rke2/config.yaml
        mode: '0644'
      tags: [ 'slave','rke-config']
    - name: Run RKE2 script
      shell:
        cmd: curl -sfL https://get.rke2.io | sh -
        warn: False
      tags: [ 'download']
    - name: Add proxy in rke init script
      lineinfile:
        path: /usr/local/lib/systemd/system/rke2-server.service
        insertbefore: 'EnvironmentFile=-/etc/default/%N'
        line: EnvironmentFile=/etc/default/proxy
    - name: Copy Nginx Config
      copy:
        src: rke2-ingress-nginx-custom.yaml
        dest: /var/lib/rancher/rke2/server/manifests/rke2-ingress-nginx-custom.yaml
        mode: '0644'
      tags: [ 'master','rke-config']
    - name: Enable RKE2 script
      shell:
        cmd: systemctl enable rke2-server.service
        warn: False
    - name: Reload systemd
      shell:
        cmd: systemctl daemon-reload
        warn: False
    - name: Start RKE2 script
      shell:
        cmd: systemctl start rke2-server.service
        warn: False- proxy
- proxy.conf
- config-master.yaml
- rke2-ingress-nginx-custom.yaml
HTTP_PROXY=http://192.168.1.1:3128 HTTPS_PROXY=http://192.168.1.1:3128 NO_PROXY=127.0.0.0/8,10.0.0.0/8,192.168.1.0/16,*.mydomain.com
Acquire::http::Proxy "http://192.168.1.1:3128/"; Acquire::https::Proxy "https://192.168.1.1:3128/";
tls-san: - "mydomain.com" - "192.168.1.11" - "192.168.1.12" - "192.168.1.13"
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-ingress-nginx
  namespace: kube-system
spec:
  valuesContent: |-
    controller:
      kind: DaemonSet
      daemonset:
        useHostPort: true
Install the First Node
ansible-playbook rke2-ha.yml -i rke2-hosts -l rke2-node1
server: https://master.mydomain.com:9345 token: [token from /var/lib/rancher/rke2/server/node-token] tls-san: - "mydomain.com" - "192.168.1.11" - "192.168.1.12" - "192.168.1.13"
Install the rest of Node
ansible-playbook rke2-ha.yml -i rke2-hosts -l rke2-nextnode
/var/lib/rancher/rke2/bin/kubectl \
        --kubeconfig /etc/rancher/rke2/rke2.yaml get nodes
        
NAME           STATUS   ROLES                       AGE   VERSION
rke2-node1     Ready    control-plane,etcd,master   1m    v1.21.4+rke2r2
rke2-node2     Ready    control-plane,etcd,master   1m    v1.21.4+rke2r2
rke2-node3     Ready    control-plane,etcd,master   1m    v1.21.4+rke2r2
Installing Rancher (Kubernetes Dashboard Management)
After your cluster is up, you can already manage and deploy application using kubectl tools, but it'll be much more easy to manage the cluster from web interface. We use Rancher for that. To install rancher, you must do the following step from any rke2 nodes
Install helm
To install helm you can download the script from their website:
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 chmod 700 get_helm.sh ./get_helm.sh
Add Latest Helm Repo
helm repo add rancher-latest https://releases.rancher.com/server-charts/latest
Create a Namespace for Rancher
kubectl create namespace cattle-system
Install cert-manager
I use Rancher Generated Certificates, so the command will be:
# If you have installed the CRDs manually instead of with the `--set installCRDs=true` option added to your Helm install command, you should upgrade your CRD resources before upgrading the Helm chart: kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.1/cert-manager.crds.yaml # 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 cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.5.1
Wait until the cert-manager installed successfully and check using this command:
kubectl get pods --namespace cert-manager NAME READY STATUS RESTARTS AGE cert-manager-5c6866597-zw7kh 1/1 Running 0 2m cert-manager-cainjector-577f6d9fd7-tr77l 1/1 Running 0 2m cert-manager-webhook-787858fcdb-nlzsq 1/1 Running 0 2m
Install Rancher using helm
helm install rancher rancher-latest/rancher \ --namespace cattle-system \ --set hostname=rancher.mydomain.com \ --set replicas=3 \ --set proxy="http://192.168.1.1:3128/" \ --set noProxy=".mydomain.com\,127.0.0.0/8\,192.168.1.0/16\,10.0.0.0/8"
Wait until deployment is finish, check the deployment status
kubectl -n cattle-system get deploy rancher NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE rancher 3 3 3 3 3m
To access rancher, you must configure your DNS and Nginx because it uses domain to resolve the application
Configure DNS
Add this following entry into your DNS configuration
*.mydomain.com. IN A 192.168.1.1
Configure Nginx
Below is Nginx configuration that can be used to forward the request to the RKE2 cluster, put this config inside http section:
upstream kube {
  server 192.168.1.11:80;
  server 192.168.1.12:80;
  server 192.168.1.13:80;
}
server {
	listen 443 ssl;
	error_log   /var/log/nginx/kubes-error.log;
	ssl_certificate     /etc/ssl/private/kube.crt;
	ssl_certificate_key /etc/ssl/private/kube.key;
	# Support for wildcard domains
	server_name *.mydomain.com;
	location / {
		access_log      off;
		proxy_pass http://kube;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	}
}
server {
	listen 80;
	error_log   /var/log/nginx/kubes-error.log;
	# Support for wildcard domains
	server_name *.mydomain.com;
	return 301 https://$host$request_uri;
}
Inside Main section:
stream {
    map $ssl_preread_server_name $name {
        rancher.mydomain.com rancher_servers_https;
    }
    upstream rancher_servers_https {
        least_conn;
        server 192.168.1.11:443 max_fails=3 fail_timeout=5s;
        server 192.168.1.12:443 max_fails=3 fail_timeout=5s;
        server 192.168.1.13:443 max_fails=3 fail_timeout=5s;
    }
    server {
        listen     8443;
        proxy_pass $name;
        ssl_preread on;
    }
}
Please remember to pointing the ip to the agent node, not master node if you add more agent node. If everything are fine, you can access rancher in this url https://rancher.mydomain.com:8443
Using rancher you can deploy application using marketplace or using custom yaml, you can assign domain to application for example: grafana.mydomain.com without needed to configure DNS again, because all domain using mydomain.com will be forwarded to rke2 cluster.

Comments