This is an automated email from the ASF dual-hosted git repository.

pearl11594 pushed a commit to branch ghi12728-headlamp-k8s
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 7db663b7716996806f603d49f78dc7641e6747ff
Author: Pearl Dsilva <[email protected]>
AuthorDate: Tue Mar 10 00:08:58 2026 -0400

    Add support for Headlamp dashboard for kubernetes; deprecate legacy 
kubernetes dashboard
---
 .../cluster/utils/KubernetesClusterUtil.java       | 13 ++++-
 .../src/main/resources/conf/k8s-control-node.yml   | 19 ++++++-
 scripts/util/create-kubernetes-binaries-iso.sh     | 64 +++++++++++++++++++---
 ui/src/views/compute/KubernetesServiceTab.vue      |  2 +-
 4 files changed, 85 insertions(+), 13 deletions(-)

diff --git 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java
 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java
index 00625f6e076..023fc9ec7fa 100644
--- 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java
+++ 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java
@@ -171,11 +171,20 @@ public class KubernetesClusterUtil {
         // Check if dashboard service is up running.
         while (System.currentTimeMillis() < timeoutTime) {
             if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug(String.format("Checking dashboard service for the 
Kubernetes cluster: %s to come up", kubernetesCluster));
+                LOGGER.debug(String.format("Checking dashboard service 
(Kubernetes Dashboard or Headlamp) for the Kubernetes cluster: %s to come up", 
kubernetesCluster));
             }
+            // Check for Headlamp (new dashboard) in kube-system namespace
+            if (isKubernetesClusterAddOnServiceRunning(kubernetesCluster, 
ipAddress, port, user, sshKeyFile, "kube-system", "headlamp")) {
+                if (LOGGER.isInfoEnabled()) {
+                    LOGGER.info(String.format("Headlamp dashboard service for 
the Kubernetes cluster %s is in running state", kubernetesCluster));
+                }
+                running = true;
+                break;
+            }
+            // For backward compatibility, check for Kubernetes Dashboard in 
kubernetes-dashboard namespace
             if (isKubernetesClusterAddOnServiceRunning(kubernetesCluster, 
ipAddress, port, user, sshKeyFile, "kubernetes-dashboard", 
"kubernetes-dashboard")) {
                 if (LOGGER.isInfoEnabled()) {
-                    LOGGER.info(String.format("Dashboard service for the 
Kubernetes cluster %s is in running state", kubernetesCluster));
+                    LOGGER.info(String.format("Kubernetes Dashboard service 
for the Kubernetes cluster %s is in running state", kubernetesCluster));
                 }
                 running = true;
                 break;
diff --git 
a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml
 
b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml
index 70291dd1c35..4db349ac778 100644
--- 
a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml
+++ 
b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml
@@ -331,16 +331,29 @@ write_files:
         if [[ ${EXTERNAL_CNI_PLUGIN} == false ]]; then
           /opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/network.yaml
         fi
-        /opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml
+        if [ -f "${K8S_CONFIG_SCRIPTS_COPY_DIR}/headlamp.yaml" ]; then
+          echo "Installing Headlamp dashboard from ISO"
+          /opt/bin/kubectl apply -f 
${K8S_CONFIG_SCRIPTS_COPY_DIR}/headlamp.yaml
+        elif [ -f "${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml" ]; then
+          echo "Installing Kubernetes Dashboard from ISO"
+          /opt/bin/kubectl apply -f 
${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml
+          /opt/bin/kubectl create rolebinding admin-binding --role=admin 
--user=admin || true
+          /opt/bin/kubectl create clusterrolebinding cluster-admin-binding 
--clusterrole=cluster-admin --user=admin || true
+          /opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui 
--clusterrole=cluster-admin 
--serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true
+        else
+          echo "Warning: No dashboard YAML found in ISO (neither headlamp.yaml 
nor dashboard.yaml)"
+        fi
         rm -rf "${K8S_CONFIG_SCRIPTS_COPY_DIR}"
       else
+        ### Online installation - use Headlamp by default ###
         /opt/bin/kubectl apply -f 
"https://cloud.weave.works/k8s/net?k8s-version=$(/opt/bin/kubectl version | 
base64 | tr -d '\n')"
-        /opt/bin/kubectl apply -f 
https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml
+        /opt/bin/kubectl apply -f 
https://raw.githubusercontent.com/kubernetes-sigs/headlamp/v0.40.1/kubernetes-headlamp.yaml
+        /opt/bin/kubectl create serviceaccount headlamp-admin -n kube-system 
|| true
+        /opt/bin/kubectl create clusterrolebinding headlamp-admin 
--clusterrole=cluster-admin --serviceaccount=kube-system:headlamp-admin || true
       fi
 
       /opt/bin/kubectl create rolebinding admin-binding --role=admin 
--user=admin || true
       /opt/bin/kubectl create clusterrolebinding cluster-admin-binding 
--clusterrole=cluster-admin --user=admin || true
-      /opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui 
--clusterrole=cluster-admin 
--serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true
 
       sudo touch /home/cloud/success
       echo "true" > /home/cloud/success
diff --git a/scripts/util/create-kubernetes-binaries-iso.sh 
b/scripts/util/create-kubernetes-binaries-iso.sh
index ebaf072771c..9f781b47171 100755
--- a/scripts/util/create-kubernetes-binaries-iso.sh
+++ b/scripts/util/create-kubernetes-binaries-iso.sh
@@ -19,8 +19,8 @@
 set -e
 
 if [ $# -lt 6 ]; then
-    echo "Invalid input. Valid usage: ./create-kubernetes-binaries-iso.sh 
OUTPUT_PATH KUBERNETES_VERSION CNI_VERSION CRICTL_VERSION 
WEAVENET_NETWORK_YAML_CONFIG DASHBOARD_YAML_CONFIG BUILD_NAME [ARCH] 
[ETCD_VERSION]"
-    echo "eg: ./create-kubernetes-binaries-iso.sh ./ 1.11.4 0.7.1 1.11.1 
https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml
 
https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.0/src/deploy/recommended/kubernetes-dashboard.yaml
 setup-v1.11.4 amd64"
+    echo "Invalid input. Valid usage: ./create-kubernetes-binaries-iso.sh 
OUTPUT_PATH KUBERNETES_VERSION CNI_VERSION CRICTL_VERSION 
WEAVENET_NETWORK_YAML_CONFIG HEADLAMP_DASHBOARD_VERSION BUILD_NAME [ARCH] 
[ETCD_VERSION]"
+    echo "eg: ./create-kubernetes-binaries-iso.sh ./ 1.11.4 0.7.1 1.11.1 
https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml
 0.40.1 setup-v1.11.4 amd64"
     exit 1
 fi
 
@@ -96,10 +96,60 @@ echo "Downloading network config ${NETWORK_CONFIG_URL}"
 network_conf_file="${working_dir}/network.yaml"
 curl -sSL ${NETWORK_CONFIG_URL} -o ${network_conf_file}
 
-DASHBORAD_CONFIG_URL="${6}"
-echo "Downloading dashboard config ${DASHBORAD_CONFIG_URL}"
-dashboard_conf_file="${working_dir}/dashboard.yaml"
-curl -sSL ${DASHBORAD_CONFIG_URL} -o ${dashboard_conf_file}
+HEADLAMP_DASHBOARD_VERSION="${6}"
+HEADLAMP_DASHBOARD_URL="https://raw.githubusercontent.com/kubernetes-sigs/headlamp/v${HEADLAMP_DASHBOARD_VERSION}/kubernetes-headlamp.yaml";
+echo "Downloading Headlamp manifest from ${HEADLAMP_DASHBOARD_URL}"
+headlamp_conf_file="${working_dir}/headlamp.yaml"
+curl -sSL ${HEADLAMP_DASHBOARD_URL} -o ${headlamp_conf_file}
+
+# Patch the Headlamp manifest to add missing components
+echo "Patching Headlamp manifest with missing ServiceAccount and 
ClusterRoleBinding..."
+
+if ! grep -q "kind: ServiceAccount" ${headlamp_conf_file}; then
+  echo "Adding missing ServiceAccount to Headlamp manifest"
+  cat > ${headlamp_conf_file}.tmp << 'EOF'
+---
+# ServiceAccount for Headlamp (added by CloudStack)
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: headlamp-admin
+  namespace: kube-system
+---
+# ClusterRoleBinding to grant cluster-admin permissions to Headlamp (added by 
CloudStack)
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: headlamp-admin
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: cluster-admin
+subjects:
+  - kind: ServiceAccount
+    name: headlamp-admin
+    namespace: kube-system
+---
+EOF
+  cat ${headlamp_conf_file} >> ${headlamp_conf_file}.tmp
+  mv ${headlamp_conf_file}.tmp ${headlamp_conf_file}
+fi
+
+if grep -q "kind: Deployment" ${headlamp_conf_file} && ! grep -q 
"serviceAccountName:" ${headlamp_conf_file}; then
+  echo "Adding serviceAccountName to Headlamp Deployment"
+  awk '/kind: Deployment/,0 {
+    if (/^    spec:$/ && !found) {
+      print
+      print "      serviceAccountName: headlamp-admin"
+      found=1
+      next
+    }
+  }
+  {print}' ${headlamp_conf_file} > ${headlamp_conf_file}.tmp
+  mv ${headlamp_conf_file}.tmp ${headlamp_conf_file}
+fi
+
+echo "Headlamp manifest patched successfully"
 
 # TODO : Change the url once merged
 
AUTOSCALER_URL="https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/cloudstack/examples/cluster-autoscaler-standard.yaml";
@@ -135,7 +185,7 @@ mkdir -p "${working_dir}/docker"
 output=`${k8s_dir}/kubeadm config images list --kubernetes-version=${RELEASE}`
 
 # Don't forget about the yaml images !
-for i in ${network_conf_file} ${dashboard_conf_file}
+for i in ${network_conf_file} ${headlamp_conf_file}
 do
   images=`grep "image:" $i | cut -d ':' -f2- | tr -d ' ' | tr -d "'"`
   output=`printf "%s\n" ${output} ${images}`
diff --git a/ui/src/views/compute/KubernetesServiceTab.vue 
b/ui/src/views/compute/KubernetesServiceTab.vue
index fc8f9c60213..1d34a797417 100644
--- a/ui/src/views/compute/KubernetesServiceTab.vue
+++ b/ui/src/views/compute/KubernetesServiceTab.vue
@@ -87,7 +87,7 @@
             <a-timeline-item>
               <p>
                 {{ $t('label.token.for.dashboard.login') }}<br><br>
-                <code><b>kubectl --kubeconfig /custom/path/kube.conf describe 
secret $(kubectl --kubeconfig /custom/path/kube.conf get secrets -n 
kubernetes-dashboard | grep kubernetes-dashboard-token | awk '{print $1}') -n 
kubernetes-dashboard</b></code>
+                <code><b>kubectl --kubeconfig /custom/path/kube.conf describe 
secret $(kubectl --kubeconfig /custom/path/kube.conf get secrets -n kube-system 
| grep headlamp-admin | awk '{print $1}') -n kube-system</b></code>
               </p>
             </a-timeline-item>
           </a-timeline>

Reply via email to