RKE (Rancher Kubernetes Engine) is a CNCF-certified Kubernetes distribution that runs entirely within Docker containers. The guide will show how create a cluster using RKE.

Installing rke

chmod +x rke
rke --version

Deploying the cluster

For a non minimal cluster, RKE requires cluster.yml to deploy the cluster. Be aware that address and internal_address keys exist in the file. If there's an FIP, it is possible to add its value to address and the private IP address to internal_address. Otherwise, ignore internal_address and set address to the private IP address. Add hostname_override key if you would like to name the Kubernetes nodes else RKE will set their name according to what is present in address.

nodes:
  - address: <Private IP address>
    user: <user-name of the account in the machine>
    role:
      - controlplane
      - etcd
    hostname_override: <kubernetes node name>
  - address: <FIP>
    user: <user-name of the account in the machine>
    role:
      - worker
    labels:
      app: ingress
    internal_address: <Private IP address>
    hostname_override: <kubernetes node name>
  - address: <Private IP address>
    user: <user-name of the account in the machine>
    role:
      - worker
    hostname_override: <kubernetes node name>
network:
  plugin: canal
  options:
    canal_flannel_backend_type: vxlan
monitoring:
  provider: metrics-server
ingress:
  provider: none

NOTE: There is an option to enable NGINX ingress controller (it is the default option if not specified). However, it allows traffic only within the cluster. Therefore, disable it if you would like to manage ingress from outside the cluster. Later, the instructions show how to deploy your NGINX ingress controller with ingress management from the internet.

rke up --config cluster.yml --ssh-agent-auth ~/.ssh/id_rsa

NOTE: --ssh-agent-auth flag is set when instances require key authentication to be accessed.

RKE will create a kubernetes configuration file called kube_config_cluster.yml so it is necessary to create a copy of this file in the directory where kubectl will use it.

mkdir .kube
cp kube_config_cluster.yml .kube/config 

Deploying In-Cluster Rancher server:

There are two implementations of NGINX ingress controller: One provided by Kubernetes and the other by NGINX. Each one has separate annotations when Ingress resource is deployed. Rancher requires Kubernetes NGINX ingress controller so the following steps to deploy both the ingress controller and Rancher were taken:

kubectl label node k8s-worker-1 kubernetes.io/role=ingress --overwrite
controller:
  hostNetwork: true
  nodeSelector:
     kubernetes.io/role: ingress
  service:
    externalIPs: [131.154.96.63]
    type: NodePort
    nodePorts:
        http: 31811
        https: 30506
helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --values values.yml

The output of pods and services should be the following:

ubuntu@k8s-master:~$ kubectl get pods -n ingress-nginx
NAME                                       READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-cb87575f5-7j5zf   1/1     Running   0          3d1h
ubuntu@k8s-master:~$ kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.43.200.65   131.154.96.63   80:31811/TCP,443:30506/TCP   3d1h
ingress-nginx-controller-admission   ClusterIP   10.43.60.16    <none>          443/TCP                      3d1h
kubectl create namespace cattle-system
helm install rancher rancher-latest/rancher   --namespace cattle-system   --set hostname=rancher.my.org   --set bootstrapPassword=admin --set ingress.enabled=false 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/issuer: rancher
    cert-manager.io/issuer-kind: Issuer
    meta.helm.sh/release-name: rancher
    meta.helm.sh/release-namespace: cattle-system
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "1800"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "1800"
  generation: 2
  labels:
    app: rancher
    app.kubernetes.io/managed-by: Helm
    chart: rancher-2.6.3
    heritage: Helm
    release: rancher
  name: rancher
  namespace: cattle-system
spec:
  ingressClassName: nginx
  rules:
  - host: rancher.my.org
    http:
      paths:
      - backend:
          service:
            name: rancher
            port:
              number: 80
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - rancher.my.org
    secretName: tls-rancher-ingress
ubuntu@k8s-master:~$ kubectl get ingress -A
NAMESPACE       NAME      CLASS   HOSTS            ADDRESS         PORTS     AGE
cattle-system   rancher   nginx   rancher.my.org   131.154.96.63   80, 443   3d1h 

Add the line below to the end of /etc/hosts file on the personal device.

<Floating IP> <hostname>
# example
# 131.154.96.63 rancher.my.org

Open your browser and visit Rancher.

image-2022-04-04-13-10-35-586.png