Zachi Nachshon
Zachi Nachshon Software Architect and DevOps Engineer. Passionate technologist, OSS enthusiast and Raspberry Pi addict.

Enabling Kubernetes Dashboard over HTTPS with RBAC Authorization

Enabling Kubernetes Dashboard over HTTPS with RBAC Authorization

Installing Kubernetes dashboard and enabling access via ingress controller with role-based access control (RBAC) authorization.


Prerequisites


k8s-dashboard-preview


Dashboard

The dashboard is a web based user interface allowing us an overview of the cluster which consists of information about the state of Kubernetes resources and potential errors they might have for troubleshooting. We will install the Kubernetes dashboard using Helm chart.

Prepare

We want Kubernetes to create the dashboard pod on the master node. In order to do that, we’ll have to label that node and use nodeSelector attribute when installing kubernetes-dashboard Helm chart.

  1. Get all nodes names and labels

    1
    
    kubectl get nodes --show-labels
    
  2. Label kmaster node with node-type=master

    1
    
    kubectl label nodes kmaster node-type=master
    
  3. Verify that label had been created successfully

    1
    
    kubectl get nodes --show-labels | grep node-type
    

Install

  1. Create a kubernetes-dashboard namespace

    1
    
    kubectl create namespace kubernetes-dashboard
    
  2. Add the kubernetes-dashboard Helm repository

    1
    
    helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
    
  3. Update local Helm chart repository cache

    1
    
    helm repo update
    
  4. Search for latest kubernetes-dashboard/kubernetes-dashboard official Helm chart version

    1
    2
    3
    4
    
    helm search repo kubernetes-dashboard
       
    # NAME                                        CHART VERSION   APP VERSION
    # kubernetes-dashboard/kubernetes-dashboard   4.0.2           2.2.0      
    
  5. Install the kubernetes-dashboard Helm chart using the version from previous step

    1
    2
    3
    4
    5
    6
    
    helm upgrade --install kubernetes-dashboard \
      --set metricsScraper.enabled=true \
      --set nodeSelector.node-type=master \
      --namespace kubernetes-dashboard \
      kubernetes-dashboard/kubernetes-dashboard \
      --version 4.0.2
    

Uninstall

  1. Remove kubernetes-dashboard from the cluster

    1
    
    helm uninstall kubernetes-dashboard --namespace kubernetes-dashboard
    
  2. Clear the kubernetes-dashboard namespace

    1
    
    kubectl delete namespaces kubernetes-dashboard
    


Ingress

We will expose the Kubernetes dashboard using traefik ingress controller to avoid using the kubectl proxy option and allow access to the dashboard via HTTPS with proper TLS/Cert.

Certificate

We will create a certificate using cert-manager to allow accessing the kubernetes dashboard using the hosted name kubernetes.MY_DOMAIN.com within our home network. Create a self signed certificate as described in here under kubernetes-dashboard namespace.

Verify that a TLS secret had been created for the certificate:

1
kubectl get secret MY_DOMAIN-com-cert-secret --namespace kubernetes-dashboard

Configure

  1. Create an IngressRoute for accessing the dashboard, make sure to replace MY_DOMAIN with your domain name

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    cat <<EOF | kubectl apply -f -
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    spec:
      entryPoints:
        - websecure
        - web
      routes:
        - kind: Rule
          match: Host(\`kubernetes.MY_DOMAIN.com\`)
          services:
            - kind: Service
              port: 443
              name: kubernetes-dashboard
              namespace: kubernetes-dashboard
      tls:
        secretName: MY_DOMAIN-com-cert-secret 
    EOF
    
  2. Check the resource was created successfully

    1
    
    kubectl describe ingressroute kubernetes-dashboard --namespace kubernetes-dashboard
    
  3. Set a hosted name kubernetes.MY_DOMAIN.com on a client machine (laptop/desktop)

    1
    2
    3
    4
    5
    6
    
    # Edit the file using `sudo /etc/hosts`
    # Append manualy to the existing k3s master hosted name 
    111.222.333.444 kmaster, kubernetes.MY_DOMAIN.com
    
    # Alternatively, add a new hosted name entry with a one-liner
    echo -e "111.222.333.444\tkubernetes.MY_DOMAIN.com" | sudo tee -a /etc/hosts
    
  4. Open browser at https://kubernetes.MY_DOMAIN.com

    con-not-private

Remove Access

  1. Delete Traefik ingress route

    1
    
    kubectl delete ingressroute kubernetes-dashboard --namespace kubernetes-dashboard
    
  2. Delete certificate and secret

    1
    2
    3
    4
    5
    
    # Delete certificate
    kubectl delete certificate MY_DOMAIN-com-cert --namespace kubernetes-dashboard
       
    # Delete secret
    kubectl delete secret MY_DOMAIN-com-cert-secret --namespace kubernetes-dashboard
    


Authorization

These instructions describe how to connect to the dashboard using role based access control (RBAC) with service account tokens. For additional information about Kubernetes authentication options please read here.

Admin User

  1. Create a service account for an admin user

    1
    2
    3
    4
    5
    6
    7
    
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: k8s-dashboard-admin-user
      namespace: kubernetes-dashboard
    EOF
    
  2. Verify the secret was created successfully

    1
    
    kubectl -n kubernetes-dashboard get secret | grep k8s-dashboard-admin-user
    
  3. Create an admin ClusterRole with extensive permissions on specific resources

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    cat <<EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: k8s-dashboard-admin
      # "namespace" omitted since ClusterRoles are not namespaced
    rules:
      - apiGroups: ["", "extensions", "apps"]
        resources: ["deployments", "pods", "services", "secrets", "namespaces"]
        verbs: ["*"]
    EOF
    
  4. Bind the admin user to the admin role we have just created

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    cat <<EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: k8s-dashboard-admin
    subjects:
      - kind: ServiceAccount
        name: k8s-dashboard-admin-user
        namespace: kubernetes-dashboard
        apiGroup: ""
    roleRef:
      kind: ClusterRole
      name: k8s-dashboard-admin
      apiGroup: rbac.authorization.k8s.io
    EOF
    
  5. Retrieve the admin user secret token

    1
    2
    3
    
    kubectl -n kubernetes-dashboard describe secret \
       $(kubectl -n kubernetes-dashboard get secret \
       | grep k8s-dashboard-admin-user | awk '{print $1}')
    
    Show Output k8s-admin-user-token
     
  6. Open the login page, enter the secret under Token field and click Sign In

    Show Login k8s-dashboard-login


Cluster Admin User

  1. Create a service account for the cluster admin user

    1
    2
    3
    4
    5
    6
    7
    
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: k8s-dashboard-cluster-admin-user
      namespace: kubernetes-dashboard
    EOF
    
  2. Verify the secret was created successfully

    1
    
    kubectl -n kubernetes-dashboard get secret | grep k8s-dashboard-cluster-admin-user
    
  3. Bind the user to the Kubernetes cluster-admin role

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    cat <<EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: k8s-dashboard-cluster-admin
    subjects:
      - kind: ServiceAccount
        name: k8s-dashboard-cluster-admin-user
        namespace: kubernetes-dashboard
        apiGroup: ""
    roleRef:
      kind: ClusterRole
      name: cluster-admin
      apiGroup: rbac.authorization.k8s.io
    EOF
    
  4. Retrieve the cluster admin user secret token

    1
    2
    3
    
    kubectl -n kubernetes-dashboard describe secret \
       $(kubectl -n kubernetes-dashboard get secret \
       | grep k8s-dashboard-cluster-admin-user | awk '{print $1}')
    
    Show Output k8s-admin-user-token
     
  5. Open the login page, enter the secret under Token field and click Sign In

    Show Login k8s-dashboard-login


Read-Only User

  1. Create a service account for a read-only user

    1
    2
    3
    4
    5
    6
    7
    
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: k8s-dashboard-read-only-user
      namespace: kubernetes-dashboard
    EOF
    
  2. Verify the secret was created successfully

    1
    
    kubectl -n kubernetes-dashboard get secret | grep k8s-dashboard-read-only-user
    
  3. Create a namespace scoped read-only Role with get / list / watch permissions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    cat <<EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: k8s-dashboard-read-only
      namespace: kubernetes-dashboard
    rules:
      - apiGroups: ["", "extensions", "apps"]
        resources: ["deployments", "pods", "services", "secrets", "namespaces"]
        verbs: ["get", "list", "watch"]
    EOF
    
  4. Bind the read-only user to the read-only role we have just created

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    cat <<EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: k8s-dashboard-read-only
      # The namespace of the RoleBinding determines where the permissions are granted.
      # This only grants permissions within the "kubernetes-dashboard" namespace.
      namespace: kubernetes-dashboard
    subjects:
      - kind: ServiceAccount
        name: k8s-dashboard-read-only-user
        apiGroup: ""
    roleRef:
      kind: Role
      name: k8s-dashboard-read-only
      apiGroup: rbac.authorization.k8s.io
    EOF
    
  5. Retrieve the read-only user secret token

    1
    2
    3
    
    kubectl -n kubernetes-dashboard describe secret \
       $(kubectl -n kubernetes-dashboard get secret \
       | grep k8s-dashboard-read-only-user | awk '{print $1}')
    
    Show Output k8s-admin-user-token
     
  6. Open the login page, enter the secret under Token field and click Sign In

    Show Login k8s-dashboard-login


Access via kubeconfig

Kubernetes dashboard allows us to login using a kubeconfig file instead of copy-pasting a secret token on every login session. In order to do so, we will have to define one of our previously created users with their respective secret token as the kubectl current context.

  1. Select a user from above steps and set its name and credentials on the kubeconfig file

    1
    
    kubectl config set-credentials k8s-dashboard-read-only-user --token=<read-only-user-token-in-here>
    
  2. Set the current kubectl context to use the read-only user we have just added

    1
    
    kubectl config set-context --current --user=k8s-dashboard-read-only-user
    
  3. Verify the read-only user is properly set in context using cat $HOME/.kube/k3s/config (or any other path containing the k8s config file, default is $HOME/.kube/config)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: <cert-data>
        server: https://kmaster:6443
      name: default
    contexts:
    - context:
        cluster: default
        user: k8s-dashboard-read-only-user
      name: default
    current-context: default
    kind: Config
    preferences: {}
    users:
    - name: k8s-dashboard-read-only-user
      user:
        token: <read-only user token in here>
      ...
    
  4. Open the login page, select the kubeconfig option and choose the path $HOME/.kube/k3s/config (or any other path containing the k8s config file, default is $HOME/.kube/config)

    Show Login k8s-dashboard-kubeconfig
     
  5. Click Sign In

  6. (Optional): To revert the current context to the previous default user

    1
    2
    3
    4
    5
    
    # Unset the read-only user from config
    kubectl config unset users.k8s-dashboard-read-only-user
       
    # Set the context back to default
    kubectl config set-context --current --user=default
    


Summary

You now have a working Kubernetes dashboard accessible via web-browser at kubernetes.MY_DOMAIN.com with cluster-admin / admin / read-only users for authentication. Cluster visibility it at your hand ! :raised_hands:

What now? Keep on working on the Kubernetes cluster, deploying new resources and/or tweak existing ones while having the option to visualize the cluster state on every action that you take.

Please leave your comment, suggestion or any other input you think is relevant to this post in the discussion below.

Thanks !


Credits: Logo by kubernetes.io

comments powered by Disqus