Skip to content
Kubernetes Dashboard YAML Analysis

Kubernetes Dashboard YAML Analysis

This page walks through the YAML manifest used to install the Kubernetes Dashboard.

Overall Structure

Resources that make up the Dashboard:
1. Namespace                 - Dedicated namespace
2. ServiceAccount            - The Pod's identity
3. Service (x2)              - Network endpoints
4. Secret (x3)               - Certificates and CSRF token
5. ConfigMap                 - Configuration storage
6. Role                      - Namespace permissions
7. ClusterRole               - Cluster permissions
8. RoleBinding               - Namespace permission binding
9. ClusterRoleBinding (x2)   - Cluster permission bindings
10. Deployment (x2)          - Pod deployment

1. Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: kubernetes-dashboard

Description

FieldValueDescription
namekubernetes-dashboardDedicated namespace for the Dashboard

Role

  • Isolates Dashboard-related resources
  • Separates them from the system namespace (kube-system)

2. ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

Description

FieldValueDescription
namekubernetes-dashboardServiceAccount name
namespacekubernetes-dashboardDashboard namespace

Role

  • The identity the Dashboard Pod uses when communicating with the Kubernetes API

3. Service - Dashboard

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30000
  selector:
    k8s-app: kubernetes-dashboard
  type: NodePort

Description

FieldValueDescription
port443Service port (HTTPS)
targetPort8443Container port
nodePort30000Port exposed on the node
typeNodePortExternal access through a node port

Access URL

https://<node IP>:30000

4. Secret (x3)

4-1. Certificate Store

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kubernetes-dashboard
type: Opaque

Role

  • Stores the Dashboard HTTPS certificates

4-2. CSRF Token

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-csrf
  namespace: kubernetes-dashboard
type: Opaque
data:
  csrf: ""

Role

  • A token that protects against Cross-Site Request Forgery (CSRF) attacks

4-3. Key Holder

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-key-holder
  namespace: kubernetes-dashboard
type: Opaque

Role

  • Holds encryption keys

5. ConfigMap

kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-settings
  namespace: kubernetes-dashboard

Role

  • Stores Dashboard settings
  • User settings, cluster information, etc.

6. Role

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
  # Manage the Dashboard's own Secrets
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["kubernetes-dashboard-key-holder", 
                    "kubernetes-dashboard-certs", 
                    "kubernetes-dashboard-csrf"]
    verbs: ["get", "update", "delete"]
    
  # Manage the settings ConfigMap
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["kubernetes-dashboard-settings"]
    verbs: ["get", "update"]
    
  # Metrics service proxy
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["heapster", "dashboard-metrics-scraper"]
    verbs: ["proxy"]
  - apiGroups: [""]
    resources: ["services/proxy"]
    resourceNames: ["heapster", "http:heapster:", 
                    "https:heapster:", 
                    "dashboard-metrics-scraper", 
                    "http:dashboard-metrics-scraper"]
    verbs: ["get"]

Permission Summary

ResourceResource NamesPermissions
Secretsthe three Dashboard Secretsget, update, delete
ConfigMapssettingsget, update
Servicesheapster, metrics-scraperproxy
Services/Proxyheapster, metrics-scraperget

7. ClusterRole

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Query metrics from the Metrics Server
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list", "watch"]

Role

  • Permission to query metrics across the entire cluster
  • Access to the same metrics data as kubectl top

8. RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

Role

  • Binds the Role’s permissions to the ServiceAccount

9. ClusterRoleBinding (x2)

9-1. Metrics Query Permission

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

Role

  • Binds the ClusterRole’s metrics query permission

9-2. Administrator Permissions (Important!)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard2
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

⚠️ Cautions

ItemDescription
roleRef.namecluster-admin
PermissionsCluster-wide administrator permissions
Risk levelHigh

This ClusterRoleBinding grants cluster-admin permissions to the Dashboard.

Security Considerations

⚠️ Risks:
1. The cluster can be fully controlled through the Dashboard
2. If the Dashboard is compromised, the entire cluster is compromised
3. Serious security risk if exposed externally

✅ Recommendations:
1. Use Ingress instead of NodePort
2. Strengthen authentication and authorization
3. Apply NetworkPolicies
4. Apply the principle of least privilege instead of cluster-admin

10. Deployment - Dashboard

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: kubernetes-dashboard
          image: kubernetesui/dashboard:v2.7.0
          imagePullPolicy: Always
          ports:
            - containerPort: 8443
              protocol: TCP
          args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            - --enable-skip-login
          volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs
            - mountPath: /tmp
              name: tmp-volume
          livenessProbe:
            httpGet:
              scheme: HTTPS
              path: /
              port: 8443
            initialDelaySeconds: 30
            timeoutSeconds: 30
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      volumes:
        - name: kubernetes-dashboard-certs
          secret:
            secretName: kubernetes-dashboard-certs
        - name: tmp-volume
          emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        "kubernetes.io/os": linux
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule

Container Arguments (args)

ArgumentDescription
--auto-generate-certificatesAutomatically generate certificates
--namespace=kubernetes-dashboardTarget namespace
--enable-skip-loginShow the skip-login button

Probes

livenessProbe:
  httpGet:
    scheme: HTTPS
    path: /         # Root path
    port: 8443
  initialDelaySeconds: 30  # First check after 30 seconds
  timeoutSeconds: 30       # 30-second timeout

Security Context

securityContext:
  allowPrivilegeEscalation: false  # Privilege escalation not allowed
  readOnlyRootFilesystem: true     # Root filesystem is read-only
  runAsUser: 1001                  # UID 1001
  runAsGroup: 2001                 # GID 2001

Volumes

volumes:
  - name: kubernetes-dashboard-certs
    secret:
      secretName: kubernetes-dashboard-certs  # Certificates
  - name: tmp-volume
    emptyDir: {}                              # Temporary directory

11. Service - Metrics Scraper

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 8000
      targetPort: 8000
  selector:
    k8s-app: dashboard-metrics-scraper

Role

  • Internal Service endpoint for the Metrics Scraper

12. Deployment - Metrics Scraper

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: dashboard-metrics-scraper
  template:
    metadata:
      labels:
        k8s-app: dashboard-metrics-scraper
    spec:
      containers:
        - name: dashboard-metrics-scraper
          image: kubernetesui/metrics-scraper:v1.0.8
          ports:
            - containerPort: 8000
              protocol: TCP
          livenessProbe:
            httpGet:
              scheme: HTTP
              path: /
              port: 8000
            initialDelaySeconds: 30
            timeoutSeconds: 30
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      serviceAccountName: kubernetes-dashboard
      volumes:
        - name: tmp-volume
          emptyDir: {}

Role

  • Fetches metrics data from the Metrics Server and provides it to the Dashboard
  • Caches and processes metrics data

Creating a Dashboard Admin User

# dashboard-adminuser.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

Issuing a Token

# Create a token
kubectl -n kubernetes-dashboard create token admin-user

# Use the printed token to log in to the Dashboard

Resource Relationship Diagram

This is the structure of the main resources that make up the Kubernetes Dashboard.

    graph TD
    NS[Namespace: kubernetes-dashboard] --> SA[ServiceAccount]
    
    subgraph Authorization
    SA --> RB1[RoleBinding: dashboard-settings]
    SA --> RB2[ClusterRoleBinding: metrics-reader]
    SA --> RB3[ClusterRoleBinding: cluster-admin ⚠️]
    end
    
    subgraph Core_Components
    DEP1[Deployment: kubernetes-dashboard] --> SVC1[Service: NodePort 30000]
    DEP2[Deployment: dashboard-metrics-scraper] --> SVC2[Service: Port 8000]
    end
    
    subgraph Config_Secrets
    S1[Secret: dashboard-certs]
    S2[Secret: dashboard-csrf]
    C1[ConfigMap: dashboard-settings]
    end
    
    DEP1 --- S1 & S2 & C1
    DEP2 -- "Collect" --> MS[Metrics Server]
  
ComponentMain Role
Dashboard UIProvides a web-based cluster management interface
Metrics ScraperFetches data from the Metrics Server and processes it into chart data
ServiceAccountThe identity the Dashboard Pod uses to access the API server
SecretsStore certificates for HTTPS communication and the CSRF token

Verifying the Installation

# Install the Dashboard
kubectl apply -f kubernetes-dashboard.yaml
kubectl apply -f dashboard-adminuser.yaml

# Check Pod status
kubectl get pods -n kubernetes-dashboard
# NAME                                  READY   STATUS    RESTARTS   AGE
# kubernetes-dashboard-xxxxxxxxx-xxxx   1/1     Running   0          1m
# dashboard-metrics-scraper-xxxx-xxx    1/1     Running   0          1m

# Check Service status
kubectl get svc -n kubernetes-dashboard
# NAME                        TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
# kubernetes-dashboard        NodePort   10.96.xxx.xxx  <none>        443:30000/TCP    1m
# dashboard-metrics-scraper   ClusterIP  10.96.xxx.xxx  <none>        8000/TCP         1m

# Issue a token
kubectl -n kubernetes-dashboard create token admin-user

# Access
# https://<node IP>:30000

Summary

ResourceCountPurpose
Namespace1Dedicated namespace
ServiceAccount1Pod identity
Service2Network endpoints
Secret3Certificates, CSRF, keys
ConfigMap1Configuration storage
Role1Namespace permissions
ClusterRole1Cluster permissions
RoleBinding1Namespace binding
ClusterRoleBinding2Cluster bindings
Deployment2Pod deployment
Total15

The Kubernetes Dashboard provides a web-based UI, and be careful about security when granting it cluster-admin permissions.