helm initial  (#961)

diff --git a/deploy/helm/dubbo-admin/.helmignore b/deploy/helm/dubbo-admin/.helmignore
index 0e8a0eb..8cade13 100644
--- a/deploy/helm/dubbo-admin/.helmignore
+++ b/deploy/helm/dubbo-admin/.helmignore
@@ -14,10 +14,10 @@
 *.swp
 *.bak
 *.tmp
-*.orig
 *~
 # Various IDEs
+.vscode
 .project
 .idea/
 *.tmproj
-.vscode/
+OWNERS
diff --git a/deploy/helm/dubbo-admin/Chart.yaml b/deploy/helm/dubbo-admin/Chart.yaml
index 3d14511..7a7f5f4 100644
--- a/deploy/helm/dubbo-admin/Chart.yaml
+++ b/deploy/helm/dubbo-admin/Chart.yaml
@@ -1,24 +1,13 @@
 apiVersion: v2
+appVersion: 3.1.5
 name: dubbo-admin
-description: A Helm chart for Kubernetes
-
-# A chart can be either an 'application' or a 'library' chart.
-#
-# Application charts are a collection of templates that can be packaged into versioned archives
-# to be deployed.
-#
-# Library charts provide useful utilities or functions for the chart developer. They're included as
-# a dependency of application charts to inject those utilities and functions into the rendering
-# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+description: Distributed application monitoring and management platform.
+home: https://cn.dubbo.apache.org
+kubeVersion: '>=1.20.0-0'
+maintainers:
+  - email: mfordjody@gmail.com
+    name: mfordjody
+sources:
+  - https://github.com/apache/dubbo
 type: application
-
-# This is the chart version. This version number should be incremented each time you make changes
-# to the chart and its templates, including the app version.
-# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 0.1.0
-
-# This is the version number of the application being deployed. This version number should be
-# incremented each time you make changes to the application. Versions are not expected to
-# follow Semantic Versioning. They should reflect the version the application is using.
-# It is recommended to use it with quotes.
-appVersion: "1.16.0"
+version: 0.5.0
\ No newline at end of file
diff --git a/deploy/helm/dubbo-admin/README.md b/deploy/helm/dubbo-admin/README.md
new file mode 100644
index 0000000..250de97
--- /dev/null
+++ b/deploy/helm/dubbo-admin/README.md
@@ -0,0 +1,11 @@
+```
+git clone https://github.com/apache/dubbo-admin.git
+```
+
+```
+cd dubbo-admin/deploy/helm
+```
+
+```
+helm install dubbo-admin -f values.yaml .
+```
\ No newline at end of file
diff --git a/deploy/helm/dubbo-admin/templates/NOTES.txt b/deploy/helm/dubbo-admin/templates/NOTES.txt
index 693bd37..ca484a3 100644
--- a/deploy/helm/dubbo-admin/templates/NOTES.txt
+++ b/deploy/helm/dubbo-admin/templates/NOTES.txt
@@ -17,6 +17,6 @@
 {{- else if contains "ClusterIP" .Values.service.type }}
   export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "dubbo-admin.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
   export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
-  echo "Visit http://127.0.0.1:38080 to use your application"
-  kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 38080:$CONTAINER_PORT
+  echo "Visit http://127.0.0.1:8080 to use your application"
+  kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
 {{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/_helpers.tpl b/deploy/helm/dubbo-admin/templates/_helpers.tpl
index 004d964..b0a5331 100644
--- a/deploy/helm/dubbo-admin/templates/_helpers.tpl
+++ b/deploy/helm/dubbo-admin/templates/_helpers.tpl
@@ -1,9 +1,10 @@
+{{/* vim: set filetype=mustache: */}}
 {{/*
 Expand the name of the chart.
 */}}
 {{- define "dubbo-admin.name" -}}
-{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
-{{- end }}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
 
 {{/*
 Create a default fully qualified app name.
@@ -30,9 +31,22 @@
 {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
 {{- end }}
 
+
+{{/*
+Allow the release namespace to be overridden for multi-namespace deployments in combined charts
+*/}}
+{{- define "dubbo-admin.namespace" -}}
+{{- if .Values.namespaceOverride }}
+{{- .Values.namespaceOverride }}
+{{- else }}
+{{- .Release.Namespace }}
+{{- end }}
+{{- end }}
 {{/*
 Common labels
 */}}
+
+
 {{- define "dubbo-admin.labels" -}}
 helm.sh/chart: {{ include "dubbo-admin.chart" . }}
 {{ include "dubbo-admin.selectorLabels" . }}
@@ -43,6 +57,18 @@
 {{- end }}
 
 {{/*
+Return the appropriate apiVersion for rbac.
+*/}}
+{{- define "dubbo-admin.rbac.apiVersion" -}}
+{{- if $.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }}
+{{- print "rbac.authorization.k8s.io/v1" }}
+{{- else }}
+{{- print "rbac.authorization.k8s.io/v1beta1" }}
+{{- end }}
+{{- end }}
+
+
+{{/*
 Selector labels
 */}}
 {{- define "dubbo-admin.selectorLabels" -}}
@@ -60,3 +86,25 @@
 {{- default "default" .Values.serviceAccount.name }}
 {{- end }}
 {{- end }}
+
+{{- define "dubbo-admin.serviceAccountNameTest" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (print (include "dubbo-admin.fullname" .) "-test") .Values.serviceAccount.nameTest }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.nameTest }}
+{{- end }}
+{{- end }}
+
+{{/*
+Formats imagePullSecrets. Input is (dict "root" . "imagePullSecrets" .{specific imagePullSecrets})
+*/}}
+{{- define "dubbo-admin.imagePullSecrets" -}}
+{{- $root := .root }}
+{{- range (concat .root.Values.global.imagePullSecrets .imagePullSecrets) }}
+{{- if eq (typeOf .) "map[string]interface {}" }}
+- {{ toYaml (dict "name" (tpl .name $root)) | trim }}
+{{- else }}
+- name: {{ tpl . $root }}
+{{- end }}
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/deploy/helm/dubbo-admin/templates/clusterrole.yaml b/deploy/helm/dubbo-admin/templates/clusterrole.yaml
new file mode 100644
index 0000000..5cc6aa3
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/clusterrole.yaml
@@ -0,0 +1,42 @@
+{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }}
+apiVersion: {{ include "dubbo-admin.rbac.apiVersion" . }}
+kind: ClusterRole
+metadata:
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  {{- with .Values.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  name: {{ include "dubbo-admin.fullname" . }}-clusterrole
+rules:
+  - apiGroups: # "" indicates the core API group
+      - ""
+    resources:
+      - configmaps
+      - secrets
+      - pods
+    verbs:
+      - get
+      - watch
+      - list
+  - apiGroups:
+      - "extensions"
+    resources:
+      - ingresses
+    verbs:
+      - get
+  - apiGroups:
+      - "apps"
+    resources:
+      - configmaps
+      - deployments
+      - services
+    verbs:
+      - get
+      - list
+      - watch
+  {{- end }}
+  {{- with .Values.rbac.extraClusterRoleRules }}
+  {{- toYaml . | nindent 2 }}
+  {{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/clusterrolebinding.yaml b/deploy/helm/dubbo-admin/templates/clusterrolebinding.yaml
new file mode 100644
index 0000000..09f9966
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/clusterrolebinding.yaml
@@ -0,0 +1,24 @@
+{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }}
+apiVersion: {{ include "dubbo-admin.rbac.apiVersion" . }}
+kind: ClusterRoleBinding
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}-clusterrolebinding
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  {{- with .Values.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+subjects:
+  - kind: ServiceAccount
+    name: {{ include "dubbo-admin.serviceAccountName" . }}
+    namespace: {{ include "dubbo-admin.namespace" . }}
+roleRef:
+  kind: ClusterRole
+  {{- if .Values.rbac.useExistingRole }}
+  name: {{ .Values.rbac.useExistingRole }}
+  {{- else }}
+  name: {{ include "dubbo-admin.fullname" . }}-clusterrole
+  {{- end }}
+  apiGroup: rbac.authorization.k8s.io
+{{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/configmap.yaml b/deploy/helm/dubbo-admin/templates/configmap.yaml
deleted file mode 100644
index c853957..0000000
--- a/deploy/helm/dubbo-admin/templates/configmap.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
-  name: {{ .Chart.Name }}
-data:
-  application.properties: {{ .Values.properties | toYaml | indent 1 }}
diff --git a/deploy/helm/dubbo-admin/templates/deployment.yaml b/deploy/helm/dubbo-admin/templates/deployment.yaml
index 960f78c..d4fcbd1 100644
--- a/deploy/helm/dubbo-admin/templates/deployment.yaml
+++ b/deploy/helm/dubbo-admin/templates/deployment.yaml
@@ -1,39 +1,82 @@
 apiVersion: apps/v1
 kind: Deployment
 metadata:
+  name: {{ include "dubbo-admin.fullname" . }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
   labels:
-    app: {{ .Chart.Name }}
-  name: {{ .Chart.Name }}
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+    {{- with .Values.labels }}
+        {{- toYaml . | nindent 4 }}
+        {{- end }}
+      {{- with .Values.annotations }}
+    annotations:
+        {{- toYaml . | nindent 4 }}
+      {{- end }}
 spec:
-  replicas: {{ .Values.replicaCount }}
+  {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }}
+  replicas: {{ .Values.replicas }}
+  {{- end }}
+  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
+  minReadySeconds: {{ .Values.minReadySeconds }}
   selector:
     matchLabels:
-      app: {{ .Chart.Name }}
+      {{- include "dubbo-admin.selectorLabels" . | nindent 6 }}
+  {{- with .Values.deploymentStrategy }}
+  strategy:
+      {{- toYaml . | trim | nindent 4 }}
+  {{- end }}
   template:
     metadata:
       labels:
-        app: {{ .Chart.Name }}
+        {{- include "dubbo-admin.selectorLabels" . | nindent 8 }}
     spec:
+    {{- if .Values.imagePullSecrets }}
+      imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }}
+    {{- end }}
+    {{- if .Values.nodeSelector }}
+      nodeSelector: {{- toYaml .Values.nodeSelector | nindent 8 }}
+    {{- end }}
+    {{- if .Values.affinity }}
+      affinity: {{- toYaml .Values.affinity | nindent 8 }}
+    {{- end }}
+    {{- if .Values.tolerations }}
+      tolerations: {{- toYaml .Values.tolerations | nindent 8 }}
+    {{- end }}
+      serviceAccountName: {{ include "dubbo-admin.serviceAccountName" . }}
       containers:
         - name: {{ .Chart.Name }}
-          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.Version }}"
           imagePullPolicy: {{ .Values.image.pullPolicy }}
           ports:
-            - containerPort: 38080
-              protocol: TCP
-              name: http
+            - name: {{ .Values.service.name }}
+              containerPort: {{ .Values.service.containerPort }}
           volumeMounts:
-            - mountPath: /config
-              name: application-properties
+            - mountPath: {{ .Values.volumeMounts.mountPath }}
+              name: {{ .Values.volumeMounts.name }}
+              readOnly: {{ .Values.volumeMounts.readOnly }}
           livenessProbe:
             httpGet:
-              path: /
-              port: http
+              path: {{ .Values.livenessProbe.httpGet.path }}
+              port: {{ .Values.livenessProbe.httpGet.port }}
+            initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
+            timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
+            periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
+            successThreshold: {{ .Values.livenessProbe.successThreshold }}
+            failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
           readinessProbe:
             httpGet:
-              path: /
-              port: http
+              path: {{ .Values.livenessProbe.httpGet.path }}
+              port: {{ .Values.livenessProbe.httpGet.port }}
+            initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
+            timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
+            periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
+            successThreshold: {{ .Values.readinessProbe.successThreshold }}
+            failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
       volumes:
-        - name: application-properties
-          configMap:
-            name: dubbo-admin
+        - name: {{ .Values.volumes.name }}
+          secret:
+            secretName: {{ .Chart.Name }}
\ No newline at end of file
diff --git a/deploy/helm/dubbo-admin/templates/hpa.yaml b/deploy/helm/dubbo-admin/templates/hpa.yaml
new file mode 100644
index 0000000..6424890
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/hpa.yaml
@@ -0,0 +1,28 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+spec:
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: {{ include "dubbo-admin.fullname" . }}
+  minReplicas: {{ .Values.autoscaling.minReplicas }}
+  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+  metrics:
+    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+    - type: Resource
+      resource:
+        name: cpu
+        targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+    {{- end }}
+    {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+    - type: Resource
+      resource:
+        name: memory
+        targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+    {{- end }}
+{{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/role.yaml b/deploy/helm/dubbo-admin/templates/role.yaml
new file mode 100644
index 0000000..d1c1b48
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/role.yaml
@@ -0,0 +1,36 @@
+{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}}
+apiVersion: {{ include "dubbo-admin.rbac.apiVersion" . }}
+kind: Role
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  {{- with .Values.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+{{- if .Values.rbac.pspEnabled }}
+rules:
+  {{- if .Values.rbac.pspEnabled }}
+  - apiGroups:
+      - extensions
+    resources:
+      - podsecuritypolicies
+    verbs:
+      - use
+    resourceNames:
+      - {{ include "dubbo-admin.fullname" . }}
+  {{- end }}
+  {{- if .Values.rbac.namespaced }}
+  - apiGroups: [""] # "" indicates the core API group
+    resources: ["configmaps", "secrets"]
+    verbs: ["get", "watch", "list"]
+  {{- end }}
+  {{- with .Values.rbac.extraRoleRules }}
+  {{- toYaml . | nindent 2 }}
+  {{- end}}
+{{- else }}
+rules: []
+{{- end }}
+{{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/rolebinding.yaml b/deploy/helm/dubbo-admin/templates/rolebinding.yaml
new file mode 100644
index 0000000..6154260
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/rolebinding.yaml
@@ -0,0 +1,25 @@
+{{- if .Values.rbac.create }}
+apiVersion: {{ include "dubbo-admin.rbac.apiVersion" . }}
+kind: RoleBinding
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  {{- with .Values.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  {{- if .Values.rbac.useExistingRole }}
+  name: {{ .Values.rbac.useExistingRole }}
+  {{- else }}
+  name: {{ include "dubbo-admin.fullname" . }}
+  {{- end }}
+subjects:
+  - kind: ServiceAccount
+    name: {{ include "dubbo-admin.serviceAccountName" . }}
+    namespace: {{ include "dubbo-admin.namespace" . }}
+{{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/secret-env.yaml b/deploy/helm/dubbo-admin/templates/secret-env.yaml
new file mode 100644
index 0000000..7b1e1bb
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/secret-env.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.envRenderSecret }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}-env
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+type: Opaque
+data:
+{{- range $key, $val := .Values.envRenderSecret }}
+  {{ $key }}: {{ $val | b64enc | quote }}
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/deploy/helm/dubbo-admin/templates/secret.yaml b/deploy/helm/dubbo-admin/templates/secret.yaml
new file mode 100644
index 0000000..f296bee
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ .Chart.Name }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  type: Opaque
+data:
+  application.properties: {{ tpl (toYaml .Values.properties) . | b64enc }}
diff --git a/deploy/helm/dubbo-admin/templates/service.yaml b/deploy/helm/dubbo-admin/templates/service.yaml
deleted file mode 100644
index cee869a..0000000
--- a/deploy/helm/dubbo-admin/templates/service.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ include "dubbo-admin.fullname" . }}
-spec:
-  type: {{ .Values.service.type }}
-  ports:
-    - port: {{ .Values.service.port }}
-      targetPort: http
-      protocol: TCP
-      name: http
-  selector:
-   app: {{ .Chart.Name }}
diff --git a/deploy/helm/dubbo-admin/templates/serviceaccount.yaml b/deploy/helm/dubbo-admin/templates/serviceaccount.yaml
index 9986487..b493f32 100644
--- a/deploy/helm/dubbo-admin/templates/serviceaccount.yaml
+++ b/deploy/helm/dubbo-admin/templates/serviceaccount.yaml
@@ -1,12 +1,17 @@
-{{- if .Values.serviceAccount.create -}}
+{{- if .Values.serviceAccount.create }}
+{{- $admin := . -}}
 apiVersion: v1
 kind: ServiceAccount
 metadata:
-  name: {{ include "dubbo-admin.serviceAccountName" . }}
   labels:
     {{- include "dubbo-admin.labels" . | nindent 4 }}
+    {{- with .Values.serviceAccount.labels }}
+    {{- toYaml . | nindent 4 }}
+    {{- end }}
   {{- with .Values.serviceAccount.annotations }}
   annotations:
-    {{- toYaml . | nindent 4 }}
+    {{- tpl (toYaml . | nindent 4) $admin }}
   {{- end }}
-{{- end }}
+  name: {{ include "dubbo-admin.serviceAccountName" . }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  {{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/svc-headless.yaml b/deploy/helm/dubbo-admin/templates/svc-headless.yaml
new file mode 100644
index 0000000..224b05e
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/svc-headless.yaml
@@ -0,0 +1,42 @@
+{{- if .Values.service.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}-headless
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+spec:
+  {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }}
+  type: ClusterIP
+  clusterIP: None
+  {{- else if eq .Values.service.type "LoadBalancer" }}
+  type: {{ .Values.service.type }}
+  {{- with .Values.service.loadBalancerIP }}
+  loadBalancerIP: {{ . }}
+  {{- end }}
+  {{- with .Values.service.loadBalancerSourceRanges }}
+  loadBalancerSourceRanges:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- else }}
+  type: {{ .Values.service.type }}
+  {{- end }}
+  {{- with .Values.service.externalIPs }}
+  externalIPs:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  ports:
+    - name: {{ .Values.service.portName }}
+      port: {{ .Values.service.port }}
+      protocol: {{ .Values.service.protocol }}
+      targetPort: {{ .Values.service.targetPort }}
+        {{- with .Values.service.appProtocol }}
+      appProtocol: {{ . }}
+        {{- end }}
+        {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
+      nodePort: {{ .Values.service.nodePort }}
+        {{- end }}
+  selector:
+      {{- include "dubbo-admin.selectorLabels" . | nindent 4 }}
+  {{- end }}
\ No newline at end of file
diff --git a/deploy/helm/dubbo-admin/templates/svc.yaml b/deploy/helm/dubbo-admin/templates/svc.yaml
new file mode 100644
index 0000000..4697b68
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/svc.yaml
@@ -0,0 +1,46 @@
+{{- if .Values.service.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+spec:
+  {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }}
+  type: ClusterIP
+  {{- with .Values.service.clusterIP }}
+  clusterIP: {{ . }}
+  {{- end }}
+  {{- else if eq .Values.service.type "LoadBalancer" }}
+  type: {{ .Values.service.type }}
+  {{- with .Values.service.loadBalancerIP }}
+  loadBalancerIP: {{ . }}
+  {{- end }}
+  {{- with .Values.service.loadBalancerSourceRanges }}
+  loadBalancerSourceRanges:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- else }}
+  type: {{ .Values.service.type }}
+  {{- end }}
+  {{- with .Values.service.externalIPs }}
+  externalIPs:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  ports:
+    - name: {{ .Values.service.portName }}
+      port: {{ .Values.service.port }}
+      protocol: {{ .Values.service.protocol }}
+      targetPort: {{ .Values.service.targetPort }}
+        {{- with .Values.service.appProtocol }}
+      appProtocol: {{ . }}
+        {{- end }}
+        {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
+      nodePort: {{ .Values.service.nodePort }}
+        {{- end }}
+  selector:
+      {{- include "dubbo-admin.selectorLabels" . | nindent 4 }}
+  {{- end }}
+
+
diff --git a/deploy/helm/dubbo-admin/templates/tests/test-connection.yaml b/deploy/helm/dubbo-admin/templates/tests/test-connection.yaml
deleted file mode 100644
index ce40f40..0000000
--- a/deploy/helm/dubbo-admin/templates/tests/test-connection.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-apiVersion: v1
-kind: Pod
-metadata:
-  name: "{{ include "dubbo-admin.fullname" . }}-test-connection"
-  labels:
-    {{- include "dubbo-admin.labels" . | nindent 4 }}
-  annotations:
-    "helm.sh/hook": test
-spec:
-  containers:
-    - name: wget
-      image: busybox
-      command: ['wget']
-      args: ['{{ include "dubbo-admin.fullname" . }}:{{ .Values.service.port }}']
-  restartPolicy: Never
diff --git a/deploy/helm/dubbo-admin/templates/tests/test-serviceaccount.yaml b/deploy/helm/dubbo-admin/templates/tests/test-serviceaccount.yaml
new file mode 100644
index 0000000..681d30b
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/tests/test-serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  name: {{ include "dubbo-admin.serviceAccountNameTest" . }}
+  namespace: {{ include "dubbo-admin.namespace" . }}
+  annotations:
+    "helm.sh/hook": test-success
+    "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
+{{- end }}
diff --git a/deploy/helm/dubbo-admin/templates/tests/test.yaml b/deploy/helm/dubbo-admin/templates/tests/test.yaml
new file mode 100644
index 0000000..dd44ee8
--- /dev/null
+++ b/deploy/helm/dubbo-admin/templates/tests/test.yaml
@@ -0,0 +1,49 @@
+{{- if .Values.testFramework.enabled }}
+{{- $root := . }}
+apiVersion: v1
+kind: Pod
+metadata:
+  name: {{ include "dubbo-admin.fullname" . }}-test
+  labels:
+    {{- include "dubbo-admin.labels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": test-success
+    "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
+  namespace: {{ include "dubbo-admin.namespace" . }}
+spec:
+  serviceAccountName: {{ include "dubbo-admin.serviceAccountName" . }}
+  {{- with .Values.testFramework.securityContext }}
+  securityContext:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }}
+  imagePullSecrets:
+    {{- include "dubbo-admin.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 4 }}
+  {{- end }}
+  {{- with .Values.nodeSelector }}
+  nodeSelector:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- with .Values.affinity }}
+  affinity:
+    {{- tpl (toYaml .) $root | nindent 4 }}
+  {{- end }}
+  {{- with .Values.tolerations }}
+  tolerations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+  containers:
+    - name: {{ .Release.Name }}-test
+      image: "{{ .Values.testFramework.image}}"
+      imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}"
+      command: ["wget"]
+      volumeMounts:
+        - mountPath: /tests
+          name: tests
+          readOnly: true
+  volumes:
+    - name: tests
+      configMap:
+        name: {{ include "dubbo-admin.fullname" . }}-test
+  restartPolicy: Never
+{{- end }}
diff --git a/deploy/helm/dubbo-admin/values.yaml b/deploy/helm/dubbo-admin/values.yaml
index 0a43bf9..cfd80ff 100644
--- a/deploy/helm/dubbo-admin/values.yaml
+++ b/deploy/helm/dubbo-admin/values.yaml
@@ -1,69 +1,526 @@
-# Default values for dubbo-admin.
-# This is a YAML-formatted file.
-# Declare variables to be passed into your templates.
+global:
+  # To help compatibility with other charts which use global.imagePullSecrets.
+  # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style).
+  # Can be tempalted.
+  # global:
+  #   imagePullSecrets:
+  #   - name: pullSecret1
+  #   - name: pullSecret2
+  # or
+  # global:
+  #   imagePullSecrets:
+  #   - pullSecret1
+  #   - pullSecret2
+  imagePullSecrets: []
 
-replicaCount: 2
+
+fullnameOverride: {}
+
+
+nameOverride: {}
+
+
+namespaceOverride: {}
+
+
+labels: {}
+
+
+annotations: {}
+
+volumes:
+  name: application-properties
+
+
+volumeMounts:
+  mountPath: /config
+  name: application-properties
+  readOnly: true
+
+
+rbac:
+  create: true
+  # Use an existing ClusterRole/Role (depending on rbac.namespaced false/true)
+  pspEnabled: true
+  pspUseAppArmor: true
+  namespaced: false
+  extraRoleRules: []
+  useExistingRole: []
+  # - apiGroups: []
+  #   resources: []
+  #   verbs: []
+  extraClusterRoleRules: []
+  # - apiGroups: []
+  #   resources: []
+  #   verbs: []
+
+## serviceAccount
+serviceAccount:
+  create: true
+  name:
+  ## ServiceAccount labels.
+  labels: {}
+  annotations: {}
+
+
+## Number of copies
+replicas: 1
+
+# -- Optional array of imagePullSecrets containing private registry credentials
+## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+imagePullSecrets: []
+# - name: secretName
+
+
+## Create a headless service for the deployment
+headlessService: false
+
+
+## Create HorizontalPodAutoscaler object for deployment type
+autoscaling:
+  enabled: false
+  minReplicas: 1
+  maxReplicas: 5
+  targetCPU: "60"
+  targetMemory: ""
+  behavior: {}
+
+## Number of old ReplicaSets to retain
+##
+revisionHistoryLimit: 10
+
+
+## See `kubectl explain poddisruptionbudget.spec` for more
+## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
+podDisruptionBudget: {}
+#  minAvailable: 1
+#  maxUnavailable: 1
+
+
+## See `kubectl explain deployment.spec.strategy` for more
+## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
+deploymentStrategy:
+  type: RollingUpdate
+
+
+readinessProbe:
+  httpGet:
+    path: /
+    port: 8080
+  initialDelaySeconds: 60
+  timeoutSeconds: 30
+  periodSeconds: 10
+  successThreshold: 1
+  failureThreshold: 3
+
+
+livenessProbe:
+  httpGet:
+    path: /
+    port: 8080
+  initialDelaySeconds: 60
+  timeoutSeconds: 30
+  periodSeconds: 10
+  successThreshold: 1
+  failureThreshold: 3
+
 
 image:
   repository: apache/dubbo-admin
+  tag: "0.5.0"
   pullPolicy: IfNotPresent
-  # Overrides the image tag whose default is the chart appVersion.
-  tag: "0.5.0-SNAPSHOT"
 
-imagePullSecrets: []
-nameOverride: ""
-fullnameOverride: ""
-
-serviceAccount:
-  # Specifies whether a service account should be created
-  create: true
-  # Annotations to add to the service account
-  annotations: {}
-  # The name of the service account to use.
-  # If not set and create is true, a name is generated using the fullname template
-  name: ""
+  ## Optionally specify an array of imagePullSecrets.
+  ## Secrets must be manually created in the namespace.
+  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+  ## Can be templated.
+  ##
+  pullSecrets: []
+  #   - RegisterKeySecretName
 
 
-podAnnotations: {}
+securityContext:
+  # runAsUser: 570
+  # runAsGroup: 570
+  # fsGroup: 570
 
-podSecurityContext: {}
-  # fsGroup: 2000
+testFramework:
+  enabled: true
+  image: busybox
+  tag: ""
+  imagePullPolicy: IfNotPresent
+  securityContext: {}
 
-securityContext: {}
-  # capabilities:
-  #   drop:
-  #   - ALL
-  # readOnlyRootFilesystem: true
-  # runAsNonRoot: true
-  # runAsUser: 1000
 
+containerSecurityContext: {}
+
+
+## Sensible environment variables that will be rendered as new secret object
+## This can be useful for auth tokens, etc
+envRenderSecret: {}
+
+# -- `minReadySeconds` to avoid killing pods before we are ready
+##
+minReadySeconds: 0
+# -- Node tolerations for server scheduling to nodes with taints
+## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
+##
+
+
+createConfigmap: true
+
+
+ConfigmapMounts: []
+  # - name: configMap-file
+  #   mountPath: /config
+  #   configMap: configMap-file
+  #   readOnly: true
+
+
+SecretMounts:
+#  - name: secret-file
+#    secret:
+#      secretName: secret-file
+
+
+##
+extraSecretMounts: []
+  # - name: secret-files
+  #   mountPath: /etc/secrets
+  #   secretName: secret-files
+  #   readOnly: true
+  #   subPath: ""
+
+
+##
+EmptyDirMounts: []
+# - name: ""
+#   mountPath: /
+
+
+##
+# Apply extra labels to common labels.
+extraLabels: {}
+
+
+## Assign a PriorityClassName to pods if set
+# priorityClassName:
+
+
+## Pod Annotations
+# podAnnotations: {}
+
+
+## Pod Labels
+# podLabels: {}
+
+
+## Expose the dubbo-admin service to be accessed from outside the cluster (LoadBalancer service).
+## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it.
+## ref: http://kubernetes.io/docs/user-guide/services/
+##
 service:
+  name: http
+  ##
+  ##
+  ##
+  enabled: true
+  ##
+  ##
+  ##
   type: ClusterIP
+  ##
+  ##
+  ##
+  clusterIP: []
+  ##
+  ##
+  ##
+  loadBalancerIP: []
+  ##
+  ##
+  ##
+  loadBalancerSourceRanges: []
+  ##
+  ##
+  ##
+  externalIPs: []
+  ##
+  ##
+  ##
+  nodePort: []
+  ##
+  ##
+  ##
+  path: /
+  ##
+  ##
+  ##
   port: 38080
+  ##
+  ##
+  ##
+  targetPort: http
+  ##
+  ##
+  ##
+  containerPort: 8080
+  ##
+  ##
+  ##
+  protocol: TCP
+  ##
+  ##
+  ##
+  ## Service annotations. Can be templated.
+  annotations: {}
+  labels: {}
+  portName: service
+  appProtocol: ""
+
 
 ingress:
   enabled: false
-  className: ""
+  # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName
+  # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress
+  # ingressClassName: nginx
+  # Values can be templated
   annotations: {}
     # kubernetes.io/ingress.class: nginx
   # kubernetes.io/tls-acme: "true"
+  labels: {}
+  path: /
+
+
+  # pathType is only for k8s >= 1.1=
+  pathType: Prefix
+
+
   hosts:
-    - host: dubbo.local
-      paths:
-        - path: /
-          pathType: ImplementationSpecific
+    - chart-example.local
+  ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services.
+  extraPaths: []
+  # - path: /*
+  #   backend:
+  #     serviceName: ssl-redirect
+  #     servicePort: use-annotation
+  ## Or for k8s > 1.19
+  # - path: /*
+  #   pathType: Prefix
+  #   backend:
+  #     service:
+  #       name: ssl-redirect
+  #       port:
+  #         name: use-annotation
+
+
   tls: []
   #  - secretName: chart-example-tls
   #    hosts:
   #      - chart-example.local
 
-autoscaling:
+resources: {}
+#  limits:
+#    cpu: 100m
+#    memory: 128Mi
+#  requests:
+#    cpu: 100m
+#    memory: 128Mi
+
+## Node labels for pod assignment
+## ref: https://kubernetes.io/docs/user-guide/node-selection/
+#
+nodeSelector: {}
+
+## Tolerations for pod assignment
+## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
+##
+tolerations: []
+
+## Affinity for pod assignment (evaluated as template)
+## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
+##
+affinity: {}
+
+## Topology Spread Constraints
+## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
+##
+topologySpreadConstraints: []
+
+## Additional init containers (evaluated as template)
+## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
+##
+InitContainers: []
+
+
+## Enable persistence using Persistent Volume Claims
+## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
+##
+persistence:
   enabled: false
-  minReplicas: 1
-  maxReplicas: 100
-  targetCPUUtilizationPercentage: 80
-  # targetMemoryUtilizationPercentage: 80
+  type: pvc
+  # storageClassName: default
+  accessModes:
+    - ReadWriteOnce
+  size: 10Gi
+  # annotations: {}
+  finalizers:
+    - kubernetes.io/pvc-protection
+  # selectorLabels: {}
+  ## Sub-directory of the PV to mount. Can be templated.
+  # subPath: ""
+  ## Name of an existing PVC. Can be templated.
+  # existingClaim:
+  ## Extra labels to apply to a PVC.
+  extraPvcLabels: {}
 
-properties: |
-  dubbo.application.name=dubbo-admin
+  ## If persistence is not enabled, this allows to mount the
+  ## local storage in-memory to improve performance
+  ##
+  inMemory:
+    enabled: false
+    ## The maximum usage on memory medium EmptyDir would be
+    ## the minimum value between the SizeLimit specified
+    ## here and the sum of memory limits of all containers in a pod
+    ##
+    # sizeLimit: 300Mi
 
+initChownData:
+  ## If false, data ownership will not be reset at startup
+  ## This allows the dubbo-admin-server to be run with an arbitrary user
+  ##
+  ##
+  ##
+  enabled: true
+  ##
+  ##
+  ## initChownData container image
+  ##
+  ##
+  image:
+    repository: busybox
+    tag: "1.31.1"
+    sha: ""
+    pullPolicy: IfNotPresent
+  ##
+  ##
+  ##
+  ##
+  ## initChownData resource requests and limits
+  ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/
+  ##
+  resources: {}
+  #  limits:
+  #    cpu: 100m
+  #    memory: 128Mi
+  #  requests:
+  #    cpu: 100m
+  #    memory: 128Mi
+  securityContext:
+    runAsNonRoot: false
+    runAsUser: 0
+
+
+## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request
+lifecycleHooks: {}
+  # postStart:
+  #   exec:
+#     command: []
+
+
+networkPolicy:
+  ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now.
+  ##
+  enabled: false
+  ## @param networkPolicy.allowExternal Don't require client label for connections
+  ## The Policy model to apply. When set to false, only pods with the correct
+  ## client label will have network access to  dubbo-admin port defined.
+  ## When true, dubbo-admin will accept connections from any source
+  ## (with the correct destination port).
+  ##
+  ingress: true
+  ## @param networkPolicy.ingress When true enables the creation
+  ## an ingress network policy
+  ##
+  allowExternal: true
+  ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed
+  ## If explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace
+  ## and that match other criteria, the ones that have the good label, can reach the dubbo-admin.
+  ## But sometimes, we want the dubbo-admin to be accessible to clients from other namespaces, in this case, we can use this
+  ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added.
+  ##
+  ## Example:
+  ## explicitNamespacesSelector:
+  ##   matchLabels:
+  ##     role: frontend
+  ##   matchExpressions:
+  ##    - {key: role, operator: In, values: [frontend]}
+  ##
+  explicitNamespacesSelector: {}
+  ##
+  ##
+  ##
+  ##
+  ##
+  ##
+  egress:
+    ## @param networkPolicy.egress.enabled When enabled, an egress network policy will be
+    ## created allowing dubbo-admin to connect to external data sources from kubernetes cluster.
+    enabled: false
+    ##
+    ## @param networkPolicy.egress.ports Add individual ports to be allowed by the egress
+    ports: []
+      ## Add ports to the egress by specifying - port: <port number>
+      ## E.X.
+      ## ports:
+      ## - port: 80
+      ## - port: 443
+
+properties:
+  admin.registry.address: zookeeper://zookeeper:2181
+  admin.config-center: zookeeper://zookeeper:2181
+  admin.metadata-report.address: zookeeper://zookeeper:2181
+  admin.root.user.name: root
+  admin.root.user.password: root
+  admin.check.sessionTimeoutMilli: 3600000
+  server.compression.enabled: true
+  server.compression.mime-types: text/css,text/javascript,application/javascript
+  server.compression.min-response-size: 10240
+  admin.check.tokenTimeoutMilli: 3600000
+  admin.check.signSecret: 86295dd0c4ef69a1036b0b0c15158d77
+  dubbo.application.name: dubbo-admin
+  dubbo.registry.address: ${admin.registry.address}
+  spring.datasource.url: jdbc:h2:mem:~/dubbo-admin;MODE=MYSQL;
+  spring.datasource.username: sa
+  spring.datasource.password:
+  mybatis-plus.global-config.db-config.id-type: none
+  dubbo.application.logger: slf4j
+  
+  # nacos config, add parameters to url like username=nacos&password=nacos
+  # admin.registry.address: nacos://127.0.0.1:8848?group=DEFAULT_GROUP&namespace=public
+  # admin.config-center: nacos://127.0.0.1:8848?group=dubbo
+  # admin.metadata-report.address: nacos://127.0.0.1:8848?group=dubbo
+  
+  
+  # group (Deprecated it is recommended to use URL to add parameters,will be removed in the future)
+  # admin.registry.group: dubbo
+  # admin.config-center.group: dubbo
+  # admin.metadata-report.group: dubbo
+  
+  # namespace used by nacos.(Deprecated it is recommended to use URL to add parameters,will be removed in the future)
+  # admin.registry.namespace: public
+  # admin.config-center.namespace: public
+  # admin.metadata-report.namespace: public
+  
+  # apollo config
+  # admin.config-center: apollo://localhost:8070?token=e16e5cd903fd0c97a116c873b448544b9d086de9&app.id=test&env=dev&cluster=default&namespace=dubbo
+  # admin.apollo.token: e16e5cd903fd0c97a116c873b448544b9d086de9
+  # admin.apollo.appId: test
+  # admin.apollo.env: dev
+  # admin.apollo.cluster: default
+  
+  # mysql
+  # spring.datasource.driver-class-name: com.mysql.jdbc.Driver
+  # spring.datasource.url: jdbc:mysql://localhost:3306/dubbo-admin?characterEncoding=utf8&connectTimeout=1000&socketTimeout=10000&autoReconnect=true
+  # spring.datasource.username: root
+  # spring.datasource.password: mysql
\ No newline at end of file