Fix issues for releasing 0.4.0 (#41)

* Several improvments for 0.4.0 release

  * Bump up SkyWalking OAP to 8.8.1(latest)
  * Update README.md laid in the binary package
  * Add a docker build tool to the binary package where users can
    build the docker image from binaries in the bin folder
  * Update release document and bash script to insert "v" into
    the git release tag.

Signed-off-by: Gao Hongtao <hanahmily@gmail.com>

* Fix issues found in testing

Storage controller:

  * Introduce readiness probe to statefulset
  * Apply authorization to controller
  * Opt to parrelle pod management strategy
  * Add init container to increase "vm.max_map_count"
  * Add password to pks12 key/cert

Java agent injector:

  * Fix backend services validation

UI:

 * Add "http" schema to the backend service url
diff --git a/apis/operator/v1alpha1/common.go b/apis/operator/v1alpha1/common.go
index d9cf058..9c91294 100644
--- a/apis/operator/v1alpha1/common.go
+++ b/apis/operator/v1alpha1/common.go
@@ -68,7 +68,7 @@
 	LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`
 }
 
-// Service Type string describes ingress methods for a service
+// ServiceType string describes ingress methods for a service
 type ServiceType string
 
 const (
diff --git a/apis/operator/v1alpha1/storage_types.go b/apis/operator/v1alpha1/storage_types.go
index dc54b4e..00605a0 100644
--- a/apis/operator/v1alpha1/storage_types.go
+++ b/apis/operator/v1alpha1/storage_types.go
@@ -86,7 +86,7 @@
 // +kubebuilder:object:root=true
 // +kubebuilder:subresource:status
 // +kubebuilder:printcolumn:name="Instances",type="string",JSONPath=".spec.instances",description="The number of expected instance"
-// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".spec.type",description="The type of strorage"
+// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".spec.type",description="The type of storage"
 // +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.version",description="The version"
 // +kubebuilder:printcolumn:name="ConnectType",type="string",JSONPath=".spec.connectType",description="the way to connect storage"
 
diff --git a/apis/operator/v1alpha1/storage_webhook.go b/apis/operator/v1alpha1/storage_webhook.go
index 2275d96..d3ff66a 100644
--- a/apis/operator/v1alpha1/storage_webhook.go
+++ b/apis/operator/v1alpha1/storage_webhook.go
@@ -79,11 +79,11 @@
 
 func (r *Storage) valid() error {
 	var allErrs field.ErrorList
-	if r.Spec.Type != "elasticsearch7" {
+	if r.Spec.Type != "elasticsearch" {
 		storagelog.Info("Invalid Storage Type")
 		err := field.Invalid(field.NewPath("spec").Child("type"),
 			r.Spec.Type,
-			"d. must be elasticsearch or elasticsearch7")
+			"d. must be elasticsearch")
 		allErrs = append(allErrs, err)
 	}
 	if r.Spec.ConnectType != "internal" && r.Spec.ConnectType != "external" {
diff --git a/apis/operator/v1alpha1/ui_webhook.go b/apis/operator/v1alpha1/ui_webhook.go
index 5901091..41f46ff 100644
--- a/apis/operator/v1alpha1/ui_webhook.go
+++ b/apis/operator/v1alpha1/ui_webhook.go
@@ -50,7 +50,7 @@
 
 	r.Spec.Service.Template.Default()
 	if r.Spec.OAPServerAddress == "" {
-		r.Spec.OAPServerAddress = fmt.Sprintf("%s-oap.%s:12800", r.Name, r.Namespace)
+		r.Spec.OAPServerAddress = fmt.Sprintf("http://%s-oap.%s:12800", r.Name, r.Namespace)
 	}
 }
 
diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go
index 2a29ca3..34cc02b 100644
--- a/cmd/manager/manager.go
+++ b/cmd/manager/manager.go
@@ -105,11 +105,11 @@
 	}
 
 	if err = (&operatorcontroller.StorageReconciler{
-		Client:   mgr.GetClient(),
-		Log:      ctrl.Log.WithName("controllers").WithName("Storage"),
-		Scheme:   mgr.GetScheme(),
-		FileRepo: repo.NewRepo("storage"),
-		Recorder: mgr.GetEventRecorderFor("storage-controller"),
+		Client:     mgr.GetClient(),
+		Log:        ctrl.Log.WithName("controllers").WithName("Storage"),
+		Scheme:     mgr.GetScheme(),
+		FileRepo:   repo.NewRepo("storage"),
+		RestConfig: mgr.GetConfig(),
 	}).SetupWithManager(mgr); err != nil {
 		setupLog.Error(err, "unable to create controller", "controller", "Storage")
 		os.Exit(1)
diff --git a/config/adapter/namespaced/adapter/kustomization.yaml b/config/adapter/namespaced/adapter/kustomization.yaml
index 3bf3904..a6f53ec 100644
--- a/config/adapter/namespaced/adapter/kustomization.yaml
+++ b/config/adapter/namespaced/adapter/kustomization.yaml
@@ -22,4 +22,4 @@
 images:
 - name: metrics-adapter
   newName: apache/skywalking-swck
-  newTag: 0.3.0
+  newTag: v0.4.0
diff --git a/config/dev/operator/crd/bases/operator.skywalking.apache.org_storages.yaml b/config/dev/operator/crd/bases/operator.skywalking.apache.org_storages.yaml
index 22c09a8..0514b67 100644
--- a/config/dev/operator/crd/bases/operator.skywalking.apache.org_storages.yaml
+++ b/config/dev/operator/crd/bases/operator.skywalking.apache.org_storages.yaml
@@ -31,7 +31,7 @@
     name: Instances
     type: string
   - JSONPath: .spec.type
-    description: The type of strorage
+    description: The type of storage
     name: Type
     type: string
   - JSONPath: .spec.version
diff --git a/config/operator/crd/bases/operator.skywalking.apache.org_storages.yaml b/config/operator/crd/bases/operator.skywalking.apache.org_storages.yaml
index 22c09a8..0514b67 100644
--- a/config/operator/crd/bases/operator.skywalking.apache.org_storages.yaml
+++ b/config/operator/crd/bases/operator.skywalking.apache.org_storages.yaml
@@ -31,7 +31,7 @@
     name: Instances
     type: string
   - JSONPath: .spec.type
-    description: The type of strorage
+    description: The type of storage
     name: Type
     type: string
   - JSONPath: .spec.version
diff --git a/config/operator/manager/kustomization.yaml b/config/operator/manager/kustomization.yaml
index 252fbba..6883ded 100644
--- a/config/operator/manager/kustomization.yaml
+++ b/config/operator/manager/kustomization.yaml
@@ -22,4 +22,4 @@
 images:
 - name: controller
   newName: apache/skywalking-swck
-  newTag: 0.3.0
+  newTag: v0.4.0
diff --git a/config/operator/rbac/kustomization.yaml b/config/operator/rbac/kustomization.yaml
index 071434e..3983b35 100644
--- a/config/operator/rbac/kustomization.yaml
+++ b/config/operator/rbac/kustomization.yaml
@@ -27,3 +27,7 @@
 - auth_proxy_role.yaml
 - auth_proxy_role_binding.yaml
 - auth_proxy_client_clusterrole.yaml
+
+patchesStrategicMerge:
+- role_patch.yaml
+  
\ No newline at end of file
diff --git a/config/operator/rbac/role.yaml b/config/operator/rbac/role.yaml
index 0ba8a84..67415ca 100644
--- a/config/operator/rbac/role.yaml
+++ b/config/operator/rbac/role.yaml
@@ -64,6 +64,20 @@
 - apiGroups:
   - ""
   resources:
+  - secrets
+  - serviceaccounts
+  - services
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - ""
+  resources:
   - serviceaccounts
   - services
   verbs:
@@ -89,7 +103,7 @@
 - apiGroups:
   - apps
   resources:
-  - statefulset
+  - statefulsets
   verbs:
   - create
   - delete
@@ -99,6 +113,22 @@
   - update
   - watch
 - apiGroups:
+  - certificates.k8s.io
+  resources:
+  - certificatesigningrequests
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - watch
+- apiGroups:
+  - certificates.k8s.io
+  resources:
+  - certificatesigningrequests/approval
+  verbs:
+  - update
+- apiGroups:
   - coordination.k8s.io
   resources:
   - leases
diff --git a/pkg/operator/manifests/storage/elasticsearch7/templates/service_account.yaml b/config/operator/rbac/role_patch.yaml
similarity index 73%
copy from pkg/operator/manifests/storage/elasticsearch7/templates/service_account.yaml
copy to config/operator/rbac/role_patch.yaml
index 627a4e4..7a43b52 100644
--- a/pkg/operator/manifests/storage/elasticsearch7/templates/service_account.yaml
+++ b/config/operator/rbac/role_patch.yaml
@@ -15,12 +15,17 @@
 # specific language governing permissions and limitations
 # under the License.
 
-apiVersion: v1
-kind: ServiceAccount
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
 metadata:
-  name: {{ .Name }}-elasticsearch7
-  namespace: {{ .Namespace }}
-  labels:
-    operator.skywalking.apache.org/es-name: {{ .Name }}
-    operator.skywalking.apache.org/application: elasticsearch
-    operator.skywalking.apache.org/component: rbac
+  name: manager-role
+rules:
+  - apiGroups:
+      - certificates.k8s.io
+    resources:
+      - signers
+    resourceNames:
+      - kubernetes.io/*
+    verbs:
+      - approve
diff --git a/config/operator/samples/default.yaml b/config/operator/samples/default.yaml
index f8435f5..9e5feb8 100644
--- a/config/operator/samples/default.yaml
+++ b/config/operator/samples/default.yaml
@@ -36,7 +36,7 @@
   version: 8.8.1
   instances: 1
   image: apache/skywalking-ui:8.8.1
-  OAPServerAddress: default-oap:12800
+  OAPServerAddress: http://default-oap:12800
   service:
     template:
       type: ClusterIP
diff --git a/controllers/operator/oapserver_controller.go b/controllers/operator/oapserver_controller.go
index 812ac5e..e325c3a 100644
--- a/controllers/operator/oapserver_controller.go
+++ b/controllers/operator/oapserver_controller.go
@@ -129,6 +129,9 @@
 
 //InjectStorage Inject Storage
 func (r *OAPServerReconciler) InjectStorage(ctx context.Context, log logr.Logger, oapServer *operatorv1alpha1.OAPServer) {
+	if oapServer.Spec.StorageConfig.Name == "" {
+		return
+	}
 	storage := &operatorv1alpha1.Storage{}
 	err := r.Client.Get(ctx, client.ObjectKey{Namespace: oapServer.Namespace, Name: oapServer.Spec.StorageConfig.Name}, storage)
 	if err == nil {
@@ -145,7 +148,7 @@
 	SwEsUser := ""
 	SwEsPassword := ""
 	SwStorageEsSslJksPath := ""
-	SwStorageEsSslJksPass := ""
+	SwStorageEsSslJksPass := "skywalking"
 	SwStorageEsClusterNodes := ""
 	o.Spec.StorageConfig.Storage = *s
 	if user.SecretName != "" {
diff --git a/controllers/operator/storage_controller.go b/controllers/operator/storage_controller.go
index 7c5b602..999970f 100644
--- a/controllers/operator/storage_controller.go
+++ b/controllers/operator/storage_controller.go
@@ -27,6 +27,8 @@
 	"encoding/asn1"
 	"encoding/pem"
 	"fmt"
+	"strconv"
+	"strings"
 	"time"
 
 	"github.com/go-logr/logr"
@@ -60,10 +62,10 @@
 
 // +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=storages,verbs=get;list;watch;create;update;patch;delete
 // +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=storages/status,verbs=get;update;patch
-// +kubebuilder:rbac:groups=apps,resources=statefulset,verbs=get;list;watch;create;update;patch;delete
-// +kubebuilder:rbac:groups="",resources=services;serviceaccounts,verbs=get;list;watch;create;update;patch;delete
-// +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;create;update
-// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterroles;clusterrolebindings,verbs=*
+// +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups="",resources=services;serviceaccounts;secrets,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=certificates.k8s.io,resources=certificatesigningrequests,verbs=get;list;watch;create;delete
+// +kubebuilder:rbac:groups=certificates.k8s.io,resources=certificatesigningrequests/approval,verbs=update
 
 func (r *StorageReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 	log := r.Log.WithValues("Storage", req.NamespacedName)
@@ -91,6 +93,7 @@
 		CR:       &storage,
 		GVK:      operatorv1alpha1.GroupVersion.WithKind("Storage"),
 		Recorder: r.Recorder,
+		TmplFunc: tmplFunc(),
 	}
 	if err := app.ApplyAll(ctx, ff, log); err != nil {
 		return ctrl.Result{}, err
@@ -103,6 +106,17 @@
 	return ctrl.Result{RequeueAfter: schedDuration}, nil
 }
 
+func tmplFunc() map[string]interface{} {
+	return map[string]interface{}{"getProtocol": getProtocol}
+}
+
+func getProtocol(tls bool) string {
+	if tls {
+		return "https"
+	}
+	return "http"
+}
+
 func (r *StorageReconciler) checkState(ctx context.Context, log logr.Logger, storage *operatorv1alpha1.Storage) error {
 	overlay := operatorv1alpha1.StorageStatus{}
 	statefulset := apps.StatefulSet{}
@@ -158,11 +172,22 @@
 	if s.Spec.ResourceCnfig.Limit == "" && s.Spec.ResourceCnfig.Requests == "" {
 		s.Spec.ResourceCnfig.Limit, s.Spec.ResourceCnfig.Requests = "1000m", "100m"
 	}
-	clusterInitialMasterNodes := s.Name + "-elasticsearch7-0" + "," + s.Name + "-elasticsearch7-1"
-	esJavaOptsValue := "-Xms512m -Xmx512m"
+
+	setDefaultJavaOpts := true
+	for _, envVar := range s.Spec.Config {
+		if envVar.Name == "ES_JAVA_OPTS" {
+			setDefaultJavaOpts = false
+		}
+	}
+	if setDefaultJavaOpts {
+		s.Spec.Config = append(s.Spec.Config, core.EnvVar{Name: "ES_JAVA_OPTS", Value: "-Xms1g -Xmx1g"})
+	}
 	s.Spec.Config = append(s.Spec.Config, core.EnvVar{Name: "discovery.seed_hosts", Value: s.Spec.ServiceName})
-	s.Spec.Config = append(s.Spec.Config, core.EnvVar{Name: "cluster.initial_master_nodes", Value: clusterInitialMasterNodes})
-	s.Spec.Config = append(s.Spec.Config, core.EnvVar{Name: "ES_JAVA_OPTS", Value: esJavaOptsValue})
+	clusterInitialMasterNodes := make([]string, s.Spec.Instances)
+	for i := 0; i < int(s.Spec.Instances); i++ {
+		clusterInitialMasterNodes[i] = s.Name + "-elasticsearch-" + strconv.Itoa(i)
+	}
+	s.Spec.Config = append(s.Spec.Config, core.EnvVar{Name: "cluster.initial_master_nodes", Value: strings.Join(clusterInitialMasterNodes, ",")})
 }
 
 func (r *StorageReconciler) createCert(ctx context.Context, log logr.Logger, s *operatorv1alpha1.Storage) {
@@ -219,7 +244,7 @@
 		log.Info("fail encode CERTIFICATE REQUEST")
 		return
 	}
-	singername := "kubernetes.io/kube-apiserver-client"
+	singername := "kubernetes.io/kubelet-serving"
 	request := certv1beta1.CertificateSigningRequest{
 		TypeMeta: metav1.TypeMeta{
 			Kind:       "CertificateSigningRequest",
@@ -273,7 +298,7 @@
 		log.Info("fail parse certificate")
 		return
 	}
-	p12, err := pkcs12.Encode(rand.Reader, key, cert, nil, "")
+	p12, err := pkcs12.Encode(rand.Reader, key, cert, nil, "skywalking")
 
 	if err != nil {
 		log.Info("fail encode pkcs12")
diff --git a/docs/examples/java-agent-injector-usage.md b/docs/examples/java-agent-injector-usage.md
index b045989..bf14c6c 100644
--- a/docs/examples/java-agent-injector-usage.md
+++ b/docs/examples/java-agent-injector-usage.md
@@ -34,7 +34,7 @@
     spec:
       containers:
       - name: demo1
-        image: dashanji/swck-spring-demo:v0.0.3
+        image: ghcr.io/apache/skywalking-swck-spring-demo:v0.0.1
         command: ["java"]
         args: ["-jar","$(AGENT_OPTS)","-jar","/app.jar"]
    
@@ -55,7 +55,7 @@
     env:
     - name: AGENT_OPTS
       value: -javaagent:/sky/agent/skywalking-agent.jar
-    image: dashanji/swck-spring-demo:v0.0.3
+    image: ghcr.io/apache/skywalking-swck-spring-demo:v0.0.1
     name: demo1
     - mountPath: /sky/agent
       name: sky-agent
@@ -170,7 +170,7 @@
     spec:
       containers:
       - name: demo2
-        image: dashanji/swck-spring-demo:v0.0.3
+        image: ghcr.io/apache/skywalking-swck-spring-demo:v0.0.1
         command: ["java"]
         args: ["-jar","$(AGENT_OPTS)","-jar","/app.jar"]
 ```
@@ -190,7 +190,7 @@
     env:
     - name: AGENT_OPTS
       value: -javaagent:/skytest/agent/skywalking-agent.jar
-    image: dashanji/swck-spring-demo:v0.0.3
+    image: ghcr.io/apache/skywalking-swck-spring-demo:v0.0.1
     name: demo2
     - mountPath: /skytest/agent
       name: sky-agent
@@ -311,7 +311,7 @@
     spec:
       containers:
       - name: demo3
-        image: dashanji/swck-spring-demo:v0.0.3
+        image: ghcr.io/apache/skywalking-swck-spring-demo:v0.0.1
         command: ["java"]
         args: ["-jar","$(AGENT_OPTS)","-jar","/app.jar"]
 ```
@@ -334,7 +334,7 @@
     env:
     - name: AGENT_OPTS
       value: -javaagent:/sky/agent/skywalking-agent.jar=agent.ignore_suffix='jpg,.jpeg',agent.class_cache_mode=MEMORY,agent.sample_n_per_3_secs=6,agent.service_name=app,plugin.mount='plugins,activations',plugin.influxdb.trace_influxql=false,plugin.mongodb.trace_param=true
-    image: dashanji/swck-spring-demo:v0.0.3
+    image: ghcr.io/apache/skywalking-swck-spring-demo:v0.0.1
     name: demo3
     - mountPath: /sky/agent
       name: sky-agent
diff --git a/docs/examples/storage.md b/docs/examples/storage.md
index 922cfc3..7a685aa 100644
--- a/docs/examples/storage.md
+++ b/docs/examples/storage.md
@@ -15,7 +15,7 @@
 metadata:
   name: sample
 spec:
-  type: elasticsearch7
+  type: elasticsearch
   connectType: internal
   version: 7.5.1
   instances: 3
@@ -32,7 +32,7 @@
 metadata:
   name: sample
 spec:
-  type: elasticsearch7
+  type: elasticsearch
   connectType: external
   address: "https://elasticsearch"
   security:
@@ -55,7 +55,7 @@
 ```shell
 $ kubectl get storage
 NAME     INSTANCES      TYPE             VERSION   CONNECTTYPE
-sample   3              elasticsearch7   7.5.1     internal
+sample   3              elasticsearch   7.5.1     internal
 ```
 
 * If you deploy the storage with the external type:
@@ -63,7 +63,7 @@
 ```shell
 $ kubectl get storage
 NAME     INSTANCES      TYPE             VERSION   CONNECTTYPE
-sample                  elasticsearch7   7.5.1     external
+sample                  elasticsearch   7.5.1     external
 ```
 
 3. Check the Statefulset in Kubernetes:
@@ -71,7 +71,7 @@
 ```shell
 $ kubectl get statefulset   
 NAME                    READY   AGE
-sample-elasticsearch7   3/3     7s
+sample-elasticsearch   3/3     7s
 ```
 
 ## Specify Storage Name in OAP server
diff --git a/pkg/kubernetes/apply.go b/pkg/kubernetes/apply.go
index a877dce..2ae1e87 100644
--- a/pkg/kubernetes/apply.go
+++ b/pkg/kubernetes/apply.go
@@ -78,13 +78,13 @@
 		return false, err
 	}
 	proto := &unstructured.Unstructured{}
-	err = LoadTemplate(string(manifests), a.CR, a.TmplFunc, proto)
+	yaml, err := LoadTemplate(string(manifests), a.CR, a.TmplFunc, proto)
 	if err == ErrNothingLoaded {
 		log.Info("nothing is loaded")
 		return false, nil
 	}
 	if err != nil {
-		return false, fmt.Errorf("failed to load %s template: %w", manifest, err)
+		return false, fmt.Errorf("failed to load %s template: %w yaml: %v", manifest, err, string(yaml))
 	}
 	return a.apply(ctx, proto, log, needCompose)
 }
diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go
index 29226c8..3f031e9 100644
--- a/pkg/kubernetes/kubernetes.go
+++ b/pkg/kubernetes/kubernetes.go
@@ -53,12 +53,12 @@
 }
 
 // LoadTemplate loads a YAML file to a component
-func LoadTemplate(manifest string, values interface{}, funcMap template.FuncMap, spec interface{}) error {
+func LoadTemplate(manifest string, values interface{}, funcMap template.FuncMap, spec interface{}) ([]byte, error) {
 	bb, err := GenerateManifests(manifest, values, funcMap)
 	if err != nil {
-		return err
+		return nil, err
 	}
-	return yaml.Unmarshal(bb, spec)
+	return bb, yaml.Unmarshal(bb, spec)
 }
 
 // GenerateManifests generate manifests from templates, CR and values
diff --git a/pkg/operator/injector/validate.go b/pkg/operator/injector/validate.go
index c6f9e48..cd8b8cc 100644
--- a/pkg/operator/injector/validate.go
+++ b/pkg/operator/injector/validate.go
@@ -19,6 +19,7 @@
 
 import (
 	"fmt"
+	"net"
 	"reflect"
 	"regexp"
 	"runtime"
@@ -32,7 +33,8 @@
 	//AnnotationValidateFuncs define all validate functions
 	AnnotationValidateFuncs = []AnnotationValidateFunc{
 		ValidateServiceName,
-		ValidateIpandPort,
+		ValidateBackendServices,
+		ValidateIPv4OrHostname,
 	}
 )
 
@@ -61,20 +63,54 @@
 	return nil
 }
 
-//ValidateIpandPort validates an annotation's value is valid ip and port
-func ValidateIpandPort(annotation, value string) error {
-	match, err := regexp.MatchString(`(^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.`+
-		`(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.`+
-		`(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.`+
-		`(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])|`+
-		`localhost)\:`+
-		`([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$`, value)
+//ValidateBackendServices validates an annotation's value is valid backend services
+func ValidateBackendServices(annotation, value string) error {
+	services := []string{value}
+	if strings.Contains(value, ",") {
+		services = strings.Split(value, ",")
+	}
+	allEmpty := true
+	for _, service := range services {
+		service = strings.TrimSpace(service)
+		if service == "" {
+			continue
+		}
+		allEmpty = false
+		err := ValidateIPv4OrHostname(annotation, service)
+		if err != nil {
+			return err
+		}
+	}
+	if allEmpty {
+		return fmt.Errorf("%s error:every service is nil", annotation)
+	}
+	return nil
+}
 
+//ValidateIPv4OrHostname validates an annotation's value is valid ipv4 or hostname
+func ValidateIPv4OrHostname(annotation, service string) error {
+	service = strings.TrimSpace(service)
+	colonIndex := strings.LastIndex(service, ":")
+	host := service
+	if colonIndex != -1 {
+		host = service[:colonIndex]
+	}
+	if host == "" {
+		return fmt.Errorf("%s error:the service name is nil", annotation)
+	}
+	ip := net.ParseIP(host)
+	if ip != nil && ip.To4() != nil {
+		return nil
+	}
+
+	match, err := regexp.MatchString(`^([a-zA-Z0-9][a-zA-Z0-9_-]{0,62})(\.[a-zA-Z0-9_][a-zA-Z0-9_-]{0,62})*?$`,
+		host)
 	if err != nil {
 		return fmt.Errorf("%s error:%s", annotation, err.Error())
 	}
 	if !match {
-		return fmt.Errorf("%s error:not a valid ip and port", annotation)
+		return fmt.Errorf("%s=%s error:not a valid ipv4 or hostname", annotation, host)
 	}
+
 	return nil
 }
diff --git a/pkg/operator/manifests/injector/templates/annotations.yaml b/pkg/operator/manifests/injector/templates/annotations.yaml
index adad9d5..57b0ed5 100644
--- a/pkg/operator/manifests/injector/templates/annotations.yaml
+++ b/pkg/operator/manifests/injector/templates/annotations.yaml
@@ -92,5 +92,5 @@
 
   - name: agent.skywalking.apache.org/collector.backend_service
     defaultValue: 127.0.0.1:11800
-    validateFunc: ValidateIpandPort
+    validateFunc: ValidateBackendServices
     envName: SW_AGENT_COLLECTOR_BACKEND_SERVICES
\ No newline at end of file
diff --git a/pkg/operator/manifests/oapserver/templates/deployment.yaml b/pkg/operator/manifests/oapserver/templates/deployment.yaml
index 1589619..9c430cf 100644
--- a/pkg/operator/manifests/oapserver/templates/deployment.yaml
+++ b/pkg/operator/manifests/oapserver/templates/deployment.yaml
@@ -106,8 +106,8 @@
             - name: SW_HEALTH_CHECKER
               value: default
           {{range .Spec.Config}}
-          - name: {{ .Name }}
-            value: {{ .Value }}
+            - name: {{ .Name }}
+              value: {{ .Value }}
           {{end}}
       {{if .Spec.StorageConfig.Storage.Spec.Security.TLS}}
       volumes:
diff --git a/pkg/operator/manifests/storage/elasticsearch7/templates/configmap.yaml b/pkg/operator/manifests/storage/elasticsearch/templates/configmap.yaml
similarity index 85%
rename from pkg/operator/manifests/storage/elasticsearch7/templates/configmap.yaml
rename to pkg/operator/manifests/storage/elasticsearch/templates/configmap.yaml
index 664ca82..ffd8c32 100644
--- a/pkg/operator/manifests/storage/elasticsearch7/templates/configmap.yaml
+++ b/pkg/operator/manifests/storage/elasticsearch/templates/configmap.yaml
@@ -28,13 +28,17 @@
       xpack.security.transport.ssl.enabled: true
       xpack.security.transport.ssl.verification_mode: certificate
       xpack.security.transport.ssl.keystore.path: storage.p12
+      xpack.security.transport.ssl.keystore.password: skywalking
       xpack.security.transport.ssl.truststore.path: storage.p12
+      xpack.security.transport.ssl.truststore.password: skywalking
       {{end}}
       {{ if .Spec.Security.TLS }}
       xpack.security.http.ssl.enabled: true
       xpack.security.http.ssl.verification_mode: certificate
       xpack.security.http.ssl.keystore.path: storage.p12
+      xpack.security.http.ssl.keystore.password: skywalking
       xpack.security.http.ssl.truststore.path: storage.p12
+      xpack.security.http.ssl.truststore.password: skywalking
       {{end}}
 
 
diff --git a/pkg/operator/manifests/storage/elasticsearch7/templates/service.yaml b/pkg/operator/manifests/storage/elasticsearch/templates/service.yaml
similarity index 94%
rename from pkg/operator/manifests/storage/elasticsearch7/templates/service.yaml
rename to pkg/operator/manifests/storage/elasticsearch/templates/service.yaml
index ea83d23..7b39ff0 100644
--- a/pkg/operator/manifests/storage/elasticsearch7/templates/service.yaml
+++ b/pkg/operator/manifests/storage/elasticsearch/templates/service.yaml
@@ -30,9 +30,10 @@
   selector:
     app: es
     operator.skywalking.apache.org/es-name: {{ .Name }}
+  publishNotReadyAddresses: true
   ports:
-    - name: rest
+    - name: http
       port: 9200
-    - name: inter-node
+    - name: transport
       port: 9300
 
diff --git a/pkg/operator/manifests/storage/elasticsearch7/templates/service_account.yaml b/pkg/operator/manifests/storage/elasticsearch/templates/service_account.yaml
similarity index 96%
rename from pkg/operator/manifests/storage/elasticsearch7/templates/service_account.yaml
rename to pkg/operator/manifests/storage/elasticsearch/templates/service_account.yaml
index 627a4e4..5764287 100644
--- a/pkg/operator/manifests/storage/elasticsearch7/templates/service_account.yaml
+++ b/pkg/operator/manifests/storage/elasticsearch/templates/service_account.yaml
@@ -18,7 +18,7 @@
 apiVersion: v1
 kind: ServiceAccount
 metadata:
-  name: {{ .Name }}-elasticsearch7
+  name: {{ .Name }}-elasticsearch
   namespace: {{ .Namespace }}
   labels:
     operator.skywalking.apache.org/es-name: {{ .Name }}
diff --git a/pkg/operator/manifests/storage/elasticsearch/templates/statefulset.yaml b/pkg/operator/manifests/storage/elasticsearch/templates/statefulset.yaml
new file mode 100644
index 0000000..9dee487
--- /dev/null
+++ b/pkg/operator/manifests/storage/elasticsearch/templates/statefulset.yaml
@@ -0,0 +1,169 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you under
+# the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: {{ .Name }}-elasticsearch
+  namespace: {{ .Namespace }}
+  labels:
+    app: es
+    operator.skywalking.apache.org/es-name: {{ .Name }}
+    operator.skywalking.apache.org/application: elasticsearch
+    operator.skywalking.apache.org/component: statefulset
+spec:
+  serviceName:  {{ .Spec.ServiceName }}
+  replicas: {{ .Spec.Instances }}
+  selector:
+    matchLabels:
+      app: es
+      operator.skywalking.apache.org/es-name: {{ .Name }}
+  podManagementPolicy: Parallel
+  updateStrategy:
+    type: RollingUpdate
+  template:
+    metadata:
+      labels:
+        app: es
+        operator.skywalking.apache.org/es-name: {{ .Name }}
+        operator.skywalking.apache.org/application: elasticsearch
+        operator.skywalking.apache.org/component: statefulset
+    spec:
+      serviceAccountName: {{ .Name }}-elasticsearch
+      affinity:
+        podAntiAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+              - labelSelector:
+                matchExpressions:
+                  - key: app
+                    operator: In
+                    values:
+                      - "es"
+                topologyKey: kubernetes.io/hostname
+      initContainers:
+        - name: configure-sysctl
+          securityContext:
+            runAsUser: 0
+            privileged: true
+          image: "{{ .Spec.Image }}"
+          imagePullPolicy: IfNotPresent
+          command: [ "sysctl", "-w", "vm.max_map_count=262144" ]
+      containers:
+        - name: elasticsearch
+          image: {{ .Spec.Image }}
+          resources:
+            limits:
+              cpu: {{ .Spec.ResourceCnfig.Limit }}
+            requests:
+              cpu: {{ .Spec.ResourceCnfig.Requests }}
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 9200
+              name: http
+              protocol: TCP
+            - containerPort: 9300
+              name: transport
+              protocol: TCP
+          volumeMounts:
+            - name: config
+              mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
+              subPath: elasticsearch.yml
+            {{ if .Spec.Security.User.SecretName }}
+            - name: cert
+              mountPath: "/usr/share/elasticsearch/config/storage.p12"
+              subPath: storage.p12
+            {{end}}
+          env:
+            - name: cluster.name
+              value: "{{ .Name }}-skywalking-es"
+            - name: node.name
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.name
+            - name: thread_pool.write.queue_size
+              value: "1000"
+            {{ range .Spec.Config }}
+            - name: {{ .Name }}
+              value: {{ .Value }}
+            {{end}}
+          readinessProbe:
+            exec:
+              command:
+                - sh
+                - -c
+                - |
+                  #!/usr/bin/env bash -e
+                  # Exit if ELASTIC_PASSWORD in unset
+                  if [ -z "${ELASTIC_PASSWORD}" ]; then
+                    echo "ELASTIC_PASSWORD variable is missing, exiting"
+                    exit 1
+                  fi
+                  # If the node is starting up wait for the cluster to be ready (request params: "wait_for_status=green&timeout=1s" )
+                  # Once it has started only check that the node itself is responding
+                  START_FILE=/tmp/.es_start_file
+                  http () {
+                    local path="${1}"
+                    local args="${2}"
+                    set -- -XGET -s
+                    if [ "$args" != "" ]; then
+                      set -- "$@" $args
+                    fi
+                    set -- "$@" -u "elastic:${ELASTIC_PASSWORD}"
+                    curl --output /dev/null -k "$@" "{{ getProtocol .Spec.Security.TLS }}://127.0.0.1:9200${path}"
+                  }
+                  if [ -f "${START_FILE}" ]; then
+                    echo 'Elasticsearch is already running, lets check the node is healthy'
+                    HTTP_CODE=$(http "/" "-w %{http_code}")
+                    RC=$?
+                    if [[ ${RC} -ne 0 ]]; then
+                      echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ getProtocol .Spec.Security.TLS }}://127.0.0.1:9200/ failed with RC ${RC}"
+                      exit ${RC}
+                    fi
+                    # ready if HTTP code 200
+                    if [[ ${HTTP_CODE} == "200" ]]; then
+                      exit 0
+                    else
+                      echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ getProtocol .Spec.Security.TLS }}://127.0.0.1:9200/ failed with HTTP code ${HTTP_CODE}"
+                      exit 1
+                    fi
+                  else
+                    echo 'Waiting for elasticsearch cluster to become ready (request params: "wait_for_status=green&timeout=1s" )'
+                    if http "/_cluster/health?wait_for_status=green&timeout=1s" "--fail" ; then
+                      touch ${START_FILE}
+                      exit 0
+                    else
+                      echo 'Cluster is not yet ready (request params: "wait_for_status=green&timeout=1s" )'
+                      exit 1
+                    fi
+                  fi
+            failureThreshold: 10
+            initialDelaySeconds: 10
+            periodSeconds: 12
+            successThreshold: 1
+            timeoutSeconds: 12
+      volumes:
+        - name: config
+          configMap:
+            name: {{ .Name }}-config
+            items:
+                - key: elasticsearch.yml
+                  path: elasticsearch.yml
+        {{ if .Spec.Security.User.SecretName }}
+        - name: cert
+          secret:
+            secretName:  "skywalking-storage"
+        {{end}}
\ No newline at end of file
diff --git a/pkg/operator/manifests/storage/elasticsearch7/templates/statefulset.yaml b/pkg/operator/manifests/storage/elasticsearch7/templates/statefulset.yaml
deleted file mode 100644
index 1712bc4..0000000
--- a/pkg/operator/manifests/storage/elasticsearch7/templates/statefulset.yaml
+++ /dev/null
@@ -1,107 +0,0 @@
-# Licensed to Apache Software Foundation (ASF) under one or more contributor
-# license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright
-# ownership. Apache Software Foundation (ASF) licenses this file to you under
-# the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: {{ .Name }}-elasticsearch7
-  namespace: {{ .Namespace }}
-  labels:
-    app: es
-    operator.skywalking.apache.org/es-name: {{ .Name }}
-    operator.skywalking.apache.org/application: elasticsearch
-    operator.skywalking.apache.org/component: statefulset
-spec:
-  serviceName:  {{ .Spec.ServiceName }}
-  replicas: {{ .Spec.Instances }}
-  selector:
-    matchLabels:
-      app: es
-      operator.skywalking.apache.org/es-name: {{ .Name }}
-  template:
-    metadata:
-      labels:
-        app: es
-        operator.skywalking.apache.org/es-name: {{ .Name }}
-        operator.skywalking.apache.org/application: elasticsearch
-        operator.skywalking.apache.org/component: statefulset
-    spec:
-      serviceAccountName: {{ .Name }}-elasticsearch7
-      affinity:
-        podAntiAffinity:
-          requiredDuringSchedulingIgnoredDuringExecution:
-              - labelSelector:
-                matchExpressions:
-                  - key: app
-                    operator: In
-                    values:
-                      - "es"
-                topologyKey: kubernetes.io/hostname
-      containers:
-        - name: elasticsearch
-          image: {{ .Spec.Image }}
-          resources:
-            limits:
-              cpu: {{ .Spec.ResourceCnfig.Limit }}
-            requests:
-              cpu: {{ .Spec.ResourceCnfig.Requests }}
-          imagePullPolicy: IfNotPresent
-          ports:
-            - containerPort: 9200
-              name: rest
-              protocol: TCP
-            - containerPort: 9300
-              name: inter-node
-              protocol: TCP
-          volumeMounts:
-            - name: config
-              mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
-              subPath: elasticsearch.yml
-            {{ if .Spec.Security.User.SecretName }}
-            - name: cert
-              mountPath: "/usr/share/elasticsearch/config/storage.p12"
-              subPath: storage.p12
-            {{end}}
-          env:
-            - name: cluster.name
-              value: "{{ .Name }}-skywalking-es"
-            - name: node.name
-              valueFrom:
-                fieldRef:
-                  fieldPath: metadata.name
-            - name: thread_pool.write.queue_size
-              value: "1000"
-            {{ range .Spec.Config }}
-            - name: {{ .Name }}
-              value: {{ .Value }}
-            {{end}}
-          livenessProbe:
-            httpGet:
-              path: /_cluster/health
-              port: http
-      volumes:
-        - name: config
-          configMap:
-            name: {{ .Name }}-config
-            items:
-                - key: elasticsearch.yml
-                  path: elasticsearch.yml
-        {{ if .Spec.Security.User.SecretName }}
-        - name: cert
-          secret:
-            secretName:  "skywalking-storage"
-        {{end}}
\ No newline at end of file
diff --git a/pkg/operator/repo/assets.gen.go b/pkg/operator/repo/assets.gen.go
index ec79c8f..63dbe68 100644
--- a/pkg/operator/repo/assets.gen.go
+++ b/pkg/operator/repo/assets.gen.go
@@ -21,19 +21,19 @@
 // fetcher/templates/configmap.yaml (3.082kB)
 // fetcher/templates/deployment.yaml (2.084kB)
 // fetcher/templates/service_account.yaml (1.088kB)
-// injector/templates/annotations.yaml (3.355kB)
+// injector/templates/annotations.yaml (3.361kB)
 // injector/templates/configmap.yaml (1.2kB)
 // injector/templates/javaagent.yaml (1.462kB)
 // oapserver/templates/cluster_role.yaml (1.241kB)
 // oapserver/templates/cluster_role_binding.yaml (1.207kB)
-// oapserver/templates/deployment.yaml (3.933kB)
+// oapserver/templates/deployment.yaml (3.937kB)
 // oapserver/templates/ingress.yaml (1.672kB)
 // oapserver/templates/service.yaml (1.782kB)
 // oapserver/templates/service_account.yaml (1.09kB)
-// storage/elasticsearch7/templates/configmap.yaml (1.568kB)
-// storage/elasticsearch7/templates/service.yaml (1.29kB)
-// storage/elasticsearch7/templates/service_account.yaml (1.096kB)
-// storage/elasticsearch7/templates/statefulset.yaml (3.673kB)
+// storage/elasticsearch/templates/configmap.yaml (1.822kB)
+// storage/elasticsearch/templates/service.yaml (1.322kB)
+// storage/elasticsearch/templates/service_account.yaml (1.095kB)
+// storage/elasticsearch/templates/statefulset.yaml (6.624kB)
 // ui/templates/deployment.yaml (2.604kB)
 // ui/templates/ingress.yaml (1.668kB)
 // ui/templates/service.yaml (1.681kB)
@@ -497,7 +497,7 @@
 
   - name: agent.skywalking.apache.org/collector.backend_service
     defaultValue: 127.0.0.1:11800
-    validateFunc: ValidateIpandPort
+    validateFunc: ValidateBackendServices
     envName: SW_AGENT_COLLECTOR_BACKEND_SERVICES`)
 
 func injectorTemplatesAnnotationsYamlBytes() ([]byte, error) {
@@ -511,7 +511,7 @@
 	}
 
 	info := bindataFileInfo{name: "injector/templates/annotations.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd7, 0x31, 0xc8, 0xb3, 0x2b, 0x73, 0xfc, 0x8f, 0x8, 0x60, 0xe9, 0xe6, 0xb, 0xa4, 0x1c, 0x86, 0x50, 0xc2, 0x14, 0xb6, 0x4d, 0x64, 0x4e, 0xc0, 0x51, 0x8f, 0xdc, 0x4a, 0x33, 0xe, 0xe5, 0x39}}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x29, 0x36, 0xc1, 0x23, 0x27, 0xb2, 0x7a, 0x2, 0xed, 0x56, 0x6f, 0x83, 0x49, 0x8, 0x1c, 0x78, 0xf7, 0xfa, 0x7b, 0xe3, 0xa3, 0xc2, 0x7a, 0xb0, 0x5b, 0x5b, 0xd0, 0x7c, 0xb5, 0xe3, 0x1e, 0x85}}
 	return a, nil
 }
 
@@ -822,8 +822,8 @@
             - name: SW_HEALTH_CHECKER
               value: default
           {{range .Spec.Config}}
-          - name: {{ .Name }}
-            value: {{ .Value }}
+            - name: {{ .Name }}
+              value: {{ .Value }}
           {{end}}
       {{if .Spec.StorageConfig.Storage.Spec.Security.TLS}}
       volumes:
@@ -844,7 +844,7 @@
 	}
 
 	info := bindataFileInfo{name: "oapserver/templates/deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x7a, 0x69, 0xf2, 0xdb, 0x58, 0x23, 0x88, 0xba, 0x1b, 0x8f, 0xa8, 0xb4, 0x6c, 0xc7, 0x2e, 0x93, 0xb3, 0x4b, 0x44, 0xfa, 0x74, 0x13, 0xe9, 0x68, 0x99, 0x45, 0x1a, 0x9f, 0x3b, 0xf4, 0x7}}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcf, 0x8a, 0xdc, 0x5b, 0xc4, 0x54, 0x0, 0xa7, 0xe0, 0x7d, 0xb1, 0x27, 0x71, 0x22, 0xf5, 0xfd, 0x8a, 0x64, 0x6b, 0xa, 0x70, 0x4b, 0x37, 0x3d, 0x9a, 0x14, 0xa8, 0x3d, 0x29, 0x59, 0xe2, 0xc2}}
 	return a, nil
 }
 
@@ -1032,7 +1032,7 @@
 	return a, nil
 }
 
-var _storageElasticsearch7TemplatesConfigmapYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
+var _storageElasticsearchTemplatesConfigmapYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
 # license agreements. See the NOTICE file distributed with
 # this work for additional information regarding copyright
 # ownership. Apache Software Foundation (ASF) licenses this file to you under
@@ -1062,34 +1062,38 @@
       xpack.security.transport.ssl.enabled: true
       xpack.security.transport.ssl.verification_mode: certificate
       xpack.security.transport.ssl.keystore.path: storage.p12
+      xpack.security.transport.ssl.keystore.password: skywalking
       xpack.security.transport.ssl.truststore.path: storage.p12
+      xpack.security.transport.ssl.truststore.password: skywalking
       {{end}}
       {{ if .Spec.Security.TLS }}
       xpack.security.http.ssl.enabled: true
       xpack.security.http.ssl.verification_mode: certificate
       xpack.security.http.ssl.keystore.path: storage.p12
+      xpack.security.http.ssl.keystore.password: skywalking
       xpack.security.http.ssl.truststore.path: storage.p12
+      xpack.security.http.ssl.truststore.password: skywalking
       {{end}}
 
 
 `)
 
-func storageElasticsearch7TemplatesConfigmapYamlBytes() ([]byte, error) {
-	return _storageElasticsearch7TemplatesConfigmapYaml, nil
+func storageElasticsearchTemplatesConfigmapYamlBytes() ([]byte, error) {
+	return _storageElasticsearchTemplatesConfigmapYaml, nil
 }
 
-func storageElasticsearch7TemplatesConfigmapYaml() (*asset, error) {
-	bytes, err := storageElasticsearch7TemplatesConfigmapYamlBytes()
+func storageElasticsearchTemplatesConfigmapYaml() (*asset, error) {
+	bytes, err := storageElasticsearchTemplatesConfigmapYamlBytes()
 	if err != nil {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "storage/elasticsearch7/templates/configmap.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x66, 0x55, 0xb6, 0xb, 0xa3, 0x32, 0xf8, 0xf1, 0xce, 0xa, 0x98, 0x3c, 0x9e, 0xaa, 0x54, 0x5e, 0x77, 0x33, 0x7d, 0xf8, 0x40, 0xea, 0xd8, 0xfe, 0x83, 0x1e, 0x39, 0xd, 0xf5, 0xbf, 0x91, 0x96}}
+	info := bindataFileInfo{name: "storage/elasticsearch/templates/configmap.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x88, 0x69, 0x87, 0xef, 0x9a, 0xcc, 0xe6, 0x9b, 0x4e, 0x2b, 0xcc, 0x55, 0x75, 0x78, 0x9d, 0x59, 0x5f, 0x6b, 0xc0, 0x27, 0xa0, 0x8, 0x10, 0xff, 0xb8, 0x38, 0xba, 0xcf, 0xed, 0x1d, 0x9d}}
 	return a, nil
 }
 
-var _storageElasticsearch7TemplatesServiceYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
+var _storageElasticsearchTemplatesServiceYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
 # license agreements. See the NOTICE file distributed with
 # this work for additional information regarding copyright
 # ownership. Apache Software Foundation (ASF) licenses this file to you under
@@ -1121,30 +1125,31 @@
   selector:
     app: es
     operator.skywalking.apache.org/es-name: {{ .Name }}
+  publishNotReadyAddresses: true
   ports:
-    - name: rest
+    - name: http
       port: 9200
-    - name: inter-node
+    - name: transport
       port: 9300
 
 `)
 
-func storageElasticsearch7TemplatesServiceYamlBytes() ([]byte, error) {
-	return _storageElasticsearch7TemplatesServiceYaml, nil
+func storageElasticsearchTemplatesServiceYamlBytes() ([]byte, error) {
+	return _storageElasticsearchTemplatesServiceYaml, nil
 }
 
-func storageElasticsearch7TemplatesServiceYaml() (*asset, error) {
-	bytes, err := storageElasticsearch7TemplatesServiceYamlBytes()
+func storageElasticsearchTemplatesServiceYaml() (*asset, error) {
+	bytes, err := storageElasticsearchTemplatesServiceYamlBytes()
 	if err != nil {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "storage/elasticsearch7/templates/service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd7, 0x4b, 0x25, 0x25, 0xfa, 0xc0, 0x67, 0x42, 0x44, 0x3c, 0x6e, 0x33, 0xdd, 0x36, 0x96, 0xca, 0x8d, 0x2b, 0xb4, 0xc8, 0x5b, 0x36, 0x51, 0x80, 0x57, 0x53, 0xc8, 0x38, 0x52, 0x9f, 0x52, 0x5e}}
+	info := bindataFileInfo{name: "storage/elasticsearch/templates/service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x73, 0xfc, 0xe1, 0x33, 0x2e, 0xc2, 0x4, 0x23, 0x44, 0x26, 0xe5, 0x85, 0x9d, 0x58, 0xe7, 0xe5, 0x2a, 0xee, 0x7e, 0x6c, 0x39, 0xbf, 0x31, 0x4a, 0x49, 0xb9, 0xf7, 0x6b, 0xa8, 0x38, 0x79, 0x82}}
 	return a, nil
 }
 
-var _storageElasticsearch7TemplatesService_accountYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
+var _storageElasticsearchTemplatesService_accountYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
 # license agreements. See the NOTICE file distributed with
 # this work for additional information regarding copyright
 # ownership. Apache Software Foundation (ASF) licenses this file to you under
@@ -1164,7 +1169,7 @@
 apiVersion: v1
 kind: ServiceAccount
 metadata:
-  name: {{ .Name }}-elasticsearch7
+  name: {{ .Name }}-elasticsearch
   namespace: {{ .Namespace }}
   labels:
     operator.skywalking.apache.org/es-name: {{ .Name }}
@@ -1172,22 +1177,22 @@
     operator.skywalking.apache.org/component: rbac
 `)
 
-func storageElasticsearch7TemplatesService_accountYamlBytes() ([]byte, error) {
-	return _storageElasticsearch7TemplatesService_accountYaml, nil
+func storageElasticsearchTemplatesService_accountYamlBytes() ([]byte, error) {
+	return _storageElasticsearchTemplatesService_accountYaml, nil
 }
 
-func storageElasticsearch7TemplatesService_accountYaml() (*asset, error) {
-	bytes, err := storageElasticsearch7TemplatesService_accountYamlBytes()
+func storageElasticsearchTemplatesService_accountYaml() (*asset, error) {
+	bytes, err := storageElasticsearchTemplatesService_accountYamlBytes()
 	if err != nil {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "storage/elasticsearch7/templates/service_account.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0xef, 0xa4, 0x39, 0xae, 0xc8, 0xc4, 0xbb, 0xad, 0xc2, 0x3e, 0x3f, 0xfe, 0x49, 0x58, 0x86, 0xf2, 0x6, 0x5f, 0x56, 0xfa, 0x43, 0x35, 0x51, 0x4f, 0x87, 0xe1, 0xbb, 0xf0, 0x89, 0x71, 0x1a}}
+	info := bindataFileInfo{name: "storage/elasticsearch/templates/service_account.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe6, 0xe2, 0x5d, 0x98, 0xe2, 0xbb, 0x1, 0xf0, 0x92, 0x2e, 0x76, 0x6f, 0xc2, 0x7d, 0x95, 0x7, 0xd4, 0x74, 0xa7, 0x40, 0x55, 0x1f, 0x9f, 0xf9, 0x25, 0x92, 0x9f, 0xea, 0x13, 0x49, 0xca, 0x43}}
 	return a, nil
 }
 
-var _storageElasticsearch7TemplatesStatefulsetYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
+var _storageElasticsearchTemplatesStatefulsetYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
 # license agreements. See the NOTICE file distributed with
 # this work for additional information regarding copyright
 # ownership. Apache Software Foundation (ASF) licenses this file to you under
@@ -1207,7 +1212,7 @@
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
-  name: {{ .Name }}-elasticsearch7
+  name: {{ .Name }}-elasticsearch
   namespace: {{ .Namespace }}
   labels:
     app: es
@@ -1221,6 +1226,9 @@
     matchLabels:
       app: es
       operator.skywalking.apache.org/es-name: {{ .Name }}
+  podManagementPolicy: Parallel
+  updateStrategy:
+    type: RollingUpdate
   template:
     metadata:
       labels:
@@ -1229,7 +1237,7 @@
         operator.skywalking.apache.org/application: elasticsearch
         operator.skywalking.apache.org/component: statefulset
     spec:
-      serviceAccountName: {{ .Name }}-elasticsearch7
+      serviceAccountName: {{ .Name }}-elasticsearch
       affinity:
         podAntiAffinity:
           requiredDuringSchedulingIgnoredDuringExecution:
@@ -1240,6 +1248,14 @@
                     values:
                       - "es"
                 topologyKey: kubernetes.io/hostname
+      initContainers:
+        - name: configure-sysctl
+          securityContext:
+            runAsUser: 0
+            privileged: true
+          image: "{{ .Spec.Image }}"
+          imagePullPolicy: IfNotPresent
+          command: [ "sysctl", "-w", "vm.max_map_count=262144" ]
       containers:
         - name: elasticsearch
           image: {{ .Spec.Image }}
@@ -1251,10 +1267,10 @@
           imagePullPolicy: IfNotPresent
           ports:
             - containerPort: 9200
-              name: rest
+              name: http
               protocol: TCP
             - containerPort: 9300
-              name: inter-node
+              name: transport
               protocol: TCP
           volumeMounts:
             - name: config
@@ -1278,10 +1294,61 @@
             - name: {{ .Name }}
               value: {{ .Value }}
             {{end}}
-          livenessProbe:
-            httpGet:
-              path: /_cluster/health
-              port: http
+          readinessProbe:
+            exec:
+              command:
+                - sh
+                - -c
+                - |
+                  #!/usr/bin/env bash -e
+                  # Exit if ELASTIC_PASSWORD in unset
+                  if [ -z "${ELASTIC_PASSWORD}" ]; then
+                    echo "ELASTIC_PASSWORD variable is missing, exiting"
+                    exit 1
+                  fi
+                  # If the node is starting up wait for the cluster to be ready (request params: "wait_for_status=green&timeout=1s" )
+                  # Once it has started only check that the node itself is responding
+                  START_FILE=/tmp/.es_start_file
+                  http () {
+                    local path="${1}"
+                    local args="${2}"
+                    set -- -XGET -s
+                    if [ "$args" != "" ]; then
+                      set -- "$@" $args
+                    fi
+                    set -- "$@" -u "elastic:${ELASTIC_PASSWORD}"
+                    curl --output /dev/null -k "$@" "{{ getProtocol .Spec.Security.TLS }}://127.0.0.1:9200${path}"
+                  }
+                  if [ -f "${START_FILE}" ]; then
+                    echo 'Elasticsearch is already running, lets check the node is healthy'
+                    HTTP_CODE=$(http "/" "-w %{http_code}")
+                    RC=$?
+                    if [[ ${RC} -ne 0 ]]; then
+                      echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ getProtocol .Spec.Security.TLS }}://127.0.0.1:9200/ failed with RC ${RC}"
+                      exit ${RC}
+                    fi
+                    # ready if HTTP code 200
+                    if [[ ${HTTP_CODE} == "200" ]]; then
+                      exit 0
+                    else
+                      echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ getProtocol .Spec.Security.TLS }}://127.0.0.1:9200/ failed with HTTP code ${HTTP_CODE}"
+                      exit 1
+                    fi
+                  else
+                    echo 'Waiting for elasticsearch cluster to become ready (request params: "wait_for_status=green&timeout=1s" )'
+                    if http "/_cluster/health?wait_for_status=green&timeout=1s" "--fail" ; then
+                      touch ${START_FILE}
+                      exit 0
+                    else
+                      echo 'Cluster is not yet ready (request params: "wait_for_status=green&timeout=1s" )'
+                      exit 1
+                    fi
+                  fi
+            failureThreshold: 10
+            initialDelaySeconds: 10
+            periodSeconds: 12
+            successThreshold: 1
+            timeoutSeconds: 12
       volumes:
         - name: config
           configMap:
@@ -1295,18 +1362,18 @@
             secretName:  "skywalking-storage"
         {{end}}`)
 
-func storageElasticsearch7TemplatesStatefulsetYamlBytes() ([]byte, error) {
-	return _storageElasticsearch7TemplatesStatefulsetYaml, nil
+func storageElasticsearchTemplatesStatefulsetYamlBytes() ([]byte, error) {
+	return _storageElasticsearchTemplatesStatefulsetYaml, nil
 }
 
-func storageElasticsearch7TemplatesStatefulsetYaml() (*asset, error) {
-	bytes, err := storageElasticsearch7TemplatesStatefulsetYamlBytes()
+func storageElasticsearchTemplatesStatefulsetYaml() (*asset, error) {
+	bytes, err := storageElasticsearchTemplatesStatefulsetYamlBytes()
 	if err != nil {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "storage/elasticsearch7/templates/statefulset.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdc, 0x8b, 0x8, 0x38, 0xc7, 0x1e, 0xc9, 0xab, 0xef, 0x48, 0x64, 0x60, 0xeb, 0x68, 0x7e, 0x39, 0x44, 0x5a, 0x7, 0x47, 0x26, 0xea, 0x9d, 0xcc, 0x65, 0x8f, 0xf5, 0xd0, 0x96, 0x92, 0xaf, 0x55}}
+	info := bindataFileInfo{name: "storage/elasticsearch/templates/statefulset.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7f, 0x54, 0x31, 0xb6, 0xbf, 0xaf, 0xb2, 0x47, 0xea, 0xb2, 0x4f, 0x5, 0x54, 0xd6, 0x55, 0xa2, 0x68, 0x47, 0xb2, 0x78, 0x3a, 0xf3, 0x9, 0xf4, 0x56, 0x12, 0xd4, 0x99, 0xcf, 0x23, 0x5e, 0xe7}}
 	return a, nil
 }
 
@@ -1631,27 +1698,27 @@
 
 // _bindata is a table, holding each asset generator, mapped to its name.
 var _bindata = map[string]func() (*asset, error){
-	"fetcher/templates/cluster_role.yaml":                   fetcherTemplatesCluster_roleYaml,
-	"fetcher/templates/cluster_role_binding.yaml":           fetcherTemplatesCluster_role_bindingYaml,
-	"fetcher/templates/configmap.yaml":                      fetcherTemplatesConfigmapYaml,
-	"fetcher/templates/deployment.yaml":                     fetcherTemplatesDeploymentYaml,
-	"fetcher/templates/service_account.yaml":                fetcherTemplatesService_accountYaml,
-	"injector/templates/annotations.yaml":                   injectorTemplatesAnnotationsYaml,
-	"injector/templates/configmap.yaml":                     injectorTemplatesConfigmapYaml,
-	"injector/templates/javaagent.yaml":                     injectorTemplatesJavaagentYaml,
-	"oapserver/templates/cluster_role.yaml":                 oapserverTemplatesCluster_roleYaml,
-	"oapserver/templates/cluster_role_binding.yaml":         oapserverTemplatesCluster_role_bindingYaml,
-	"oapserver/templates/deployment.yaml":                   oapserverTemplatesDeploymentYaml,
-	"oapserver/templates/ingress.yaml":                      oapserverTemplatesIngressYaml,
-	"oapserver/templates/service.yaml":                      oapserverTemplatesServiceYaml,
-	"oapserver/templates/service_account.yaml":              oapserverTemplatesService_accountYaml,
-	"storage/elasticsearch7/templates/configmap.yaml":       storageElasticsearch7TemplatesConfigmapYaml,
-	"storage/elasticsearch7/templates/service.yaml":         storageElasticsearch7TemplatesServiceYaml,
-	"storage/elasticsearch7/templates/service_account.yaml": storageElasticsearch7TemplatesService_accountYaml,
-	"storage/elasticsearch7/templates/statefulset.yaml":     storageElasticsearch7TemplatesStatefulsetYaml,
-	"ui/templates/deployment.yaml":                          uiTemplatesDeploymentYaml,
-	"ui/templates/ingress.yaml":                             uiTemplatesIngressYaml,
-	"ui/templates/service.yaml":                             uiTemplatesServiceYaml,
+	"fetcher/templates/cluster_role.yaml":                  fetcherTemplatesCluster_roleYaml,
+	"fetcher/templates/cluster_role_binding.yaml":          fetcherTemplatesCluster_role_bindingYaml,
+	"fetcher/templates/configmap.yaml":                     fetcherTemplatesConfigmapYaml,
+	"fetcher/templates/deployment.yaml":                    fetcherTemplatesDeploymentYaml,
+	"fetcher/templates/service_account.yaml":               fetcherTemplatesService_accountYaml,
+	"injector/templates/annotations.yaml":                  injectorTemplatesAnnotationsYaml,
+	"injector/templates/configmap.yaml":                    injectorTemplatesConfigmapYaml,
+	"injector/templates/javaagent.yaml":                    injectorTemplatesJavaagentYaml,
+	"oapserver/templates/cluster_role.yaml":                oapserverTemplatesCluster_roleYaml,
+	"oapserver/templates/cluster_role_binding.yaml":        oapserverTemplatesCluster_role_bindingYaml,
+	"oapserver/templates/deployment.yaml":                  oapserverTemplatesDeploymentYaml,
+	"oapserver/templates/ingress.yaml":                     oapserverTemplatesIngressYaml,
+	"oapserver/templates/service.yaml":                     oapserverTemplatesServiceYaml,
+	"oapserver/templates/service_account.yaml":             oapserverTemplatesService_accountYaml,
+	"storage/elasticsearch/templates/configmap.yaml":       storageElasticsearchTemplatesConfigmapYaml,
+	"storage/elasticsearch/templates/service.yaml":         storageElasticsearchTemplatesServiceYaml,
+	"storage/elasticsearch/templates/service_account.yaml": storageElasticsearchTemplatesService_accountYaml,
+	"storage/elasticsearch/templates/statefulset.yaml":     storageElasticsearchTemplatesStatefulsetYaml,
+	"ui/templates/deployment.yaml":                         uiTemplatesDeploymentYaml,
+	"ui/templates/ingress.yaml":                            uiTemplatesIngressYaml,
+	"ui/templates/service.yaml":                            uiTemplatesServiceYaml,
 }
 
 // AssetDebug is true if the assets were built with the debug flag enabled.
@@ -1725,12 +1792,12 @@
 		}},
 	}},
 	"storage": &bintree{nil, map[string]*bintree{
-		"elasticsearch7": &bintree{nil, map[string]*bintree{
+		"elasticsearch": &bintree{nil, map[string]*bintree{
 			"templates": &bintree{nil, map[string]*bintree{
-				"configmap.yaml":       &bintree{storageElasticsearch7TemplatesConfigmapYaml, map[string]*bintree{}},
-				"service.yaml":         &bintree{storageElasticsearch7TemplatesServiceYaml, map[string]*bintree{}},
-				"service_account.yaml": &bintree{storageElasticsearch7TemplatesService_accountYaml, map[string]*bintree{}},
-				"statefulset.yaml":     &bintree{storageElasticsearch7TemplatesStatefulsetYaml, map[string]*bintree{}},
+				"configmap.yaml":       &bintree{storageElasticsearchTemplatesConfigmapYaml, map[string]*bintree{}},
+				"service.yaml":         &bintree{storageElasticsearchTemplatesServiceYaml, map[string]*bintree{}},
+				"service_account.yaml": &bintree{storageElasticsearchTemplatesService_accountYaml, map[string]*bintree{}},
+				"statefulset.yaml":     &bintree{storageElasticsearchTemplatesStatefulsetYaml, map[string]*bintree{}},
 			}},
 		}},
 	}},