You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by as...@apache.org on 2018/10/15 09:11:16 UTC

[incubator-servicecomb-service-center] branch master updated: SCB-949 Configurable aggregate mode (#457)

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

asifdxtreme pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new 8ddbc2f  SCB-949   Configurable aggregate mode (#457)
8ddbc2f is described below

commit 8ddbc2f1bbcda497fb059bac928efb93433e9808
Author: little-cui <su...@qq.com>
AuthorDate: Mon Oct 15 17:11:11 2018 +0800

    SCB-949   Configurable aggregate mode (#457)
    
    * Print log when etcd health check failed
    
    * Configurable aggregate mode
---
 README.md                                          |   2 +-
 docs/README.md                                     |  22 ++-
 docs/aggregate.PNG                                 | Bin 0 -> 68449 bytes
 docs/helm.md                                       | 172 +++++++++++++++++++++
 docs/integration-grafana.md                        |   4 +-
 docs/kubeclusters.md                               |  73 +++++++++
 etc/conf/app.conf                                  |   2 +
 examples/infrastructures/k8s/README.md             | 109 -------------
 .../k8s/service-center/templates/configmap.yaml    |  37 ++---
 .../k8s/service-center/templates/deployment.yaml   |   4 +
 .../k8s/service-center/templates/ingress.yaml      |   2 +
 .../k8s/service-center/templates/rbac.yaml         |   3 +-
 .../k8s/service-center/templates/service.yaml      |   4 +
 .../infrastructures/k8s/service-center/values.yaml |  36 ++---
 server/bootstrap/bootstrap.go                      |   2 +-
 server/plugin/pkg/discovery/aggregate/adaptor.go   |  29 ++--
 server/plugin/pkg/discovery/aggregate/cache.go     |  55 +++++++
 server/plugin/pkg/discovery/aggregate/common.go    |  21 ++-
 server/plugin/pkg/discovery/aggregate/repo.go      |   2 +-
 .../pkg/discovery/{sc => servicecenter}/adaptor.go |   2 +-
 .../discovery/{sc => servicecenter}/aggregate.go   |   6 +-
 .../pkg/discovery/{sc => servicecenter}/cacher.go  |   2 +-
 .../pkg/discovery/{sc => servicecenter}/cluster.go |   2 +-
 .../pkg/discovery/{sc => servicecenter}/common.go  |   2 +-
 .../pkg/discovery/{sc => servicecenter}/repo.go    |   2 +-
 server/plugin/pkg/registry/etcd/etcd.go            |  14 +-
 server/server.go                                   |   4 +
 27 files changed, 423 insertions(+), 190 deletions(-)

diff --git a/README.md b/README.md
index d7302b9..e2fd849 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Apache ServiceComb (incubating) Service-Center is a Restful based service-regist
  
 ## Documentation
 
-Project documentation is available on the [ServiceComb website][servicecomb-website]. You can also find full document [`here`](/docs).
+Project documentation is available on the [ServiceComb website][servicecomb-website]. You can also find full document [`here`](/docs/README.md).
 
 [servicecomb-website]: http://servicecomb.incubator.apache.org/
 
diff --git a/docs/README.md b/docs/README.md
index b94d0ab..c827fb4 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -2,29 +2,35 @@
 
 #### [Design](/docs/design.md)
 
-#### [Development Guide](/docs/dev-guide.md) 
+#### Development Guide
 
+- [Guides](/docs/dev-guide.md) 
 - [Api Documentation](https://rawcdn.githack.com/ServiceComb/service-center/master/docs/api-docs.html),
 Swagger [`v4`](/server/core/swagger/v4.yaml)|[`v3`](/server/core/swagger/v3.yaml)
 - [Plug-in Extension](/docs/plugin.md)
 - [Command Line Client](/scctl/README.md)
 
-#### [Docker Image Guide](/scripts/docker) 
+#### Docker Image Guide
 
 - [Making Service-Center Image](/scripts/docker/build-image)
 - [Making Front-end Image](/scripts/docker/build-frontend-image)
 
 #### Deploy Service-Center Locally
 
-- [In Docker](/examples/infrastructures/docker)
+- [Local](/README.md#running-service-center-using-the-release)
+- [Frontend](/README.md#running-frontend-using-the-release)
+- [Docker Compose](/scripts/docker) 
 
 #### Deploy Service-Center Cluster
 
-- [In Kubernetes Cluster](/examples/infrastructures/k8s)
-- [In VMs](/docs/sc-cluster.md)
-- [Deploy with TLS](/docs/security-tls.md)
-- [Multiple Datacenters](/docs/multidcs.md)
-- [Access Distinct Kubernetes clusters](/docs/aggregate.md)
++ **General**
+  - [VMs Cluster](/docs/sc-cluster.md)
+  - [Deploy with TLS](/docs/security-tls.md)
+  - [Multiple Datacenters](/docs/multidcs.md)
++ **Kubernetes**
+  - [Helm Chart](/docs/helm.md)
+  - [Access Distinct Clusters](/docs/kubeclusters.md)
+  - [Multiple Platforms Micro-services Manage](/docs/aggregate.md)
 
 #### Monitoring Service-Center
 
diff --git a/docs/aggregate.PNG b/docs/aggregate.PNG
new file mode 100644
index 0000000..a23c00a
Binary files /dev/null and b/docs/aggregate.PNG differ
diff --git a/docs/helm.md b/docs/helm.md
new file mode 100644
index 0000000..9c04507
--- /dev/null
+++ b/docs/helm.md
@@ -0,0 +1,172 @@
+Integrate with Kubernetes
+-------
+
+A simple demo to deploy ServiceCenter Cluster in Kubernetes.
+ServiceCenter supports two deploy modes: `Platform Registration` and `Client Side Registration`
+
+## Requirements
+
+1. There is a Kubernetes cluster.
+1. Already install `kubectl` and `helm client` in your local machine.
+1. (Optional) Already deploy helm tiller on Kubernetes.
+
+## Platform Registration
+
+The platform registration indicates that the ServiceCenter automatically accesses `kubernetes` cluster,
+and micro-service instances can discover service and endpoints information through
+the ServiceCenter.
+
+Notes: After deployment, it only create ServiceCenter cluster in the `default` namespace.
+
+#### Use Kubectl
+
+You can use the command `kubectl apply` to deploy ServiceCenter cluster.
+
+```bash
+cd ${PROJECT_ROOT}/examples/infrastructures/k8s
+kubectl apply -f <(helm template --name servicecomb --namespace default service-center/)
+```
+
+#### Use Helm Install
+
+You can also use the helm commands to deploy ServiceCenter cluster if 
+you already deploy helm tiller.
+
+```bash
+cd ${PROJECT_ROOT}/examples/infrastructures/k8s
+helm install --name servicecomb --namespace default service-center/
+```
+
+## Client Side Registration
+
+The client-side registration representational ServiceCenter receives and 
+processes registration requests from micro-service instances and 
+stores instance information in `etcd`.
+
+Notes: After deployment, it create ServiceCenter cluster and etcd cluster in the `default` namespace.
+
+#### Use Kubectl
+
+You can use the command `kubectl apply` to deploy ServiceCenter cluster.
+
+```bash
+cd ${PROJECT_ROOT}/examples/infrastructures/k8s
+# install etcd cluster
+kubectl apply -f <(helm template --name coreos --namespace default etcd/)
+# install sc cluster
+kubectl apply -f <(helm template --name servicecomb --namespace default \
+    --set sc.discovery.type="etcd" \
+    --set sc.discovery.clusters="http://coreos-etcd-client:2379" \
+    --set sc.registry.enabled=true \
+    --set sc.registry.type="etcd" \
+    service-center/)
+```
+
+#### Use Helm Install
+
+You can also use the helm commands to deploy ServiceCenter cluster if
+you already deploy helm tiller.
+
+```bash
+cd ${PROJECT_ROOT}/examples/infrastructures/k8s
+# install etcd cluster
+helm install --name coreos --namespace default etcd/
+# install sc cluster
+helm install --name dc1 --namespace default \
+    --set frontend.deployment=false \
+    --set sc.image.repository="desktop-0028:5000/servicecomb/service-center" \
+    --set sc.discovery.type="aggregate" \
+    --set sc.discovery.aggregate="etcd\,servicecenter" \
+    --set sc.discovery.clusters="sc-1=http://c1-etcd-client:2379\,sc-2=http://dc2-service-center:30100" \
+    --set sc.registry.enabled=true \
+    --set sc.registry.type="etcd" \
+    --set sc.registry.name="sc-1" \
+    service-center/
+helm install --name dc2 --namespace default \
+    --set frontend.deployment=false \
+    --set sc.image.repository="desktop-0028:5000/servicecomb/service-center" \
+    --set sc.discovery.type="aggregate" \
+    --set sc.discovery.aggregate="etcd\,servicecenter" \
+    --set sc.discovery.clusters="sc-2=http://c2-etcd-client:2379\,sc-1=http://dc1-service-center:30100" \
+    --set sc.registry.enabled=true \
+    --set sc.registry.type="etcd" \
+    --set sc.registry.name="sc-2" \
+    service-center/
+```
+
+## Confirm the deploy is ok
+
+By default, the ServiceCenter frontend use `NodePort` service type to deploy in Kubernetes.
+
+1. You can execute the command `kubectl get pod`, to check all pods are running.
+1. You can also point your browser to `http://${NODE}:30103` to view the dashboard of ServiceCenter.
+1. (Recommended) You can use [`scctl`](/scctl) tool to list micro-service information.
+
+```bash
+# ./scctl get svc --addr http://servicecomb-service-center:30100 -owide
+  DOMAIN  |                  NAME               |            APPID        | VERSIONS | ENV | FRAMEWORK  |        ENDPOINTS         | AGE  
++---------+-------------------------------------+-------------------------+----------+-----+------------+--------------------------+-----+
+  default | servicecomb-service-center-frontend | service-center-frontend | 0.0.1    |     | Kubernetes | http://172.0.1.101:30103 | 2m   
+  default | servicecomb-service-center          | service-center          | 0.0.1    |     | Kubernetes | http://172.0.1.102:30100 | 2m
+```
+
+## Clean up
+
+If you use the kubectl to deploy, take deploy mode `platform registration` as example.
+
+```bash
+cd ${PROJECT_ROOT}/examples/infrastructures/k8s
+kubectl delete -f <(helm template --name servicecomb --namespace default service-center/)
+```
+
+If you use helm tiller to deploy, take deploy mode `platform registration` as example.
+
+```bash
+cd ${PROJECT_ROOT}/k8s
+helm delete --purge servicecomb
+```
+
+## Helm Configuration Values
+
+- **Service Center (sc)**
+    + **deployment** (bool: true) Deploy this component or not.
+    + **service**
+        - **`type`** (string: "ClusterIP") The kubernetes service type.
+        - **`externalPort`** (int16: 30100) The external access port. If the type is `ClusterIP`,
+        it is set to the access port of the kubernetes service, and if the type
+        is `NodePort`, it is set to the listening port of the node.
+    + **discovery**
+        - **`type`** (string: "aggregate") The Service Center discovery type.
+        This can also be set to `etcd` or `servicecenter`. `aggregate` let Service Center merge the
+        discovery sources and applications can discover microservices from these through using
+        Service Center HTTP API. `etcd` let Service Center start with client registration mode, all the
+        microservices information comes from application self registration. `servicecenter` let Service
+        Center manage multiple Service Center clusters at the same time. It can be applied to multiple
+        datacenters scenarios.
+        - **`aggregate`** (string: "k8s,etcd") The discovery sources of aggregation, only enabled if `type`
+        is set to `aggregate`. Different discovery sources are merged together by commas(,),
+        indicating that the Service Center will aggregate service information through these
+        sources. Now support these scenarios: `k8s,etcd`(for managing services from multiple platforms),
+        `k8s,servicecenter`(for accessing distinct kubernetes clusters).
+        - **`clusters`** (string: "sc-0=http://127.0.0.1:2380") The cluster address managed by Service Center.
+        If `type` is set to `etcd`, its format is `http(s)://{etcd-1},http(s)://{etcd-2}`. If `type` is
+        set to other value, its format is `{cluster name 1}=http(s)://{cluster-1-1}|http(s)://{cluster-1-2},{cluster-2}=http(s)://{cluster-2-1}`
+    + **registry**
+        - **`enabled`** (bool: false) Register Service Center itself or not.
+        - **`type`** (string: "embeded_etcd") The class of backend storage provider, this decide how
+        Service Center store the microservices information. `embeded_etcd` let Service Center store data
+        in local file system, it means distributed file system is need if you deploy high availability
+        Service Center. `etcd` let Service Center store data in existing etcd cluster, then Service Center
+        could be a stateless service. `builin` disabled the storage.
+        - **`name`** (string: "sc-0") The Service Center cluster name, only enabled if `type` is set to
+        `embeded_etcd` or `etcd`.
+        - **`addr`** (string: "http://127.0.0.1:2380") The backend storage provider address. This value
+        should be a part of `sc.discovery.clusters` value.
+
+- **UI (frontend)**
+    + **deployment** (bool: true) Deploy this component of not.
+    + **service**
+        - **`type`** (string: "NodePort") The kubernetes service type.
+        - **`externalPort`** (int16: 30103) The external access port. If the type is `ClusterIP`,
+        it is set to the access port of the kubernetes service, and if the type
+        is `NodePort`, it is set to the listening port of the node.
\ No newline at end of file
diff --git a/docs/integration-grafana.md b/docs/integration-grafana.md
index 1909fd8..3e2d22b 100644
--- a/docs/integration-grafana.md
+++ b/docs/integration-grafana.md
@@ -2,7 +2,9 @@
 
 As Service-Center uses Prometheus lib to report metrics.
 Then it is easy to integrate with Grafana.
-Here is a [template](/integration/health-metrics-grafana.json) file can be imported in Grafana.
+Here is a [`DEMO`](/examples/infrastructures/docker) to deploy Service-Center with Grafana, 
+and this is the [`template`](/integration/health-metrics-grafana.json) file 
+can be imported in Grafana.
 
 After the import, you can get the view like blow.
 
diff --git a/docs/kubeclusters.md b/docs/kubeclusters.md
new file mode 100644
index 0000000..adcb4d0
--- /dev/null
+++ b/docs/kubeclusters.md
@@ -0,0 +1,73 @@
+Access Distinct Clusters
+-------
+
+## ServiceCenter Aggregate Architecture
+
+In the [`Multiple Datacenters`](/docs/multidcs.md) article, we introduce
+the aggregation architecture of service center. In fact, this aggregation
+architecture of service center can be applied not only to the scene deployed 
+in multiple datacenters, but also to the scene services data aggregation in 
+multiple kubernetes clusters.
+
+![architecture](/docs/kubeclusters.PNG)
+
+The service centers deployed in distinct kubernetes clusters can communicate 
+with each other, sync the services data from other kubernetes clusters.
+Applications can discover services from different the kubernetes cluster through
+using the service center HTTP API.
+**It solve the problem of isolation between kubernetes clusters**.
+
+## Quick Start
+
+Let's assume you want to install 2 clusters of Service-Center in different Kubernetes clusters with following details.
+
+| Cluster | Kubernetes | namespace  | Node        |  
+| :-----: | :--------: | :--------: | :---------: |  
+| sc1     | k1         | default    | 10.12.0.1   |   
+| sc2     | k2         | default    | 10.12.0.2   | 
+
+To facilitate deployment, we will publish the service address of the service center in [`NodePort`] mode.
+
+##### Deploy the Service Center
+
+Using helm to deploy the service center to kubernetes here, the instructions for specific `values` can be referred to
+[`here`](/examples/infrastructures/k8s/README.md#helm-configuration-values).
+
+Take deployment to kubernetes cluster 1 as an example.
+```bash
+# login the k1 kubernetes master node to deploy sc1
+git clone git@github.com:apache/incubator-servicecomb-service-center.git
+cd examples/infrastructures/k8s
+helm install --name k1 \
+    --set sc.discovery.clusters="sc2=http://10.12.0.2:30100" \
+    --set sc.discovery.aggregate="k8s\,servicecenter" \
+    --set sc.registry.type="buildin" \
+    --set sc.service.type=NodePort \
+    service-center/
+```
+Notes: To deploy Service Center in kuberbetes cluster 2, you can repeat the
+above steps and just change the `sc.discovery.clusters` value to 
+`sc1=http://10.12.0.1:30100`.
+
+##### Confirm the service is OK
+
+We recommend that you use [`scctl`](/scctl/README.md), and using
+[`cluster command`](/scctl/pkg/plugin/README.md#cluster-options)
+which makes it very convenient to verify OK.
+
+```bash
+# check the sc1 cluster api
+scctl --addr http://10.12.0.3:30100 get cluster
+#   CLUSTER |        ENDPOINTS         
+# +---------+-------------------------+
+#   sc2     | http://10.12.0.2:30100
+
+# check the sc2 cluster api
+scctl --addr http://10.12.0.3:30100 get cluster
+#   CLUSTER |        ENDPOINTS         
+# +---------+-------------------------+
+#   sc1     | http://10.12.0.1:30100
+```
+
+
+
diff --git a/etc/conf/app.conf b/etc/conf/app.conf
index 4407f85..df4128c 100644
--- a/etc/conf/app.conf
+++ b/etc/conf/app.conf
@@ -50,6 +50,8 @@ plugins_dir = ./plugins
 
 # pluggable discovery service
 discovery_plugin = etcd
+# the discovery plugins are part of aggregator
+aggregate_mode = ""
 
 # enable to register service center to backend registry
 self_register = 1
diff --git a/examples/infrastructures/k8s/README.md b/examples/infrastructures/k8s/README.md
deleted file mode 100644
index a929598..0000000
--- a/examples/infrastructures/k8s/README.md
+++ /dev/null
@@ -1,109 +0,0 @@
-Integrate with Kubernetes
--------
-
-A simple demo to deploy ServiceCenter Cluster in Kubernetes.
-ServiceCenter supports two deploy modes: `Platform Registration` and `Self Registration`
-
-## Requirements
-
-1. There is a Kubernetes cluster.
-1. Already install `kubectl` and `helm client` in your local machine.
-1. (Optional) Already deploy helm tiller on Kubernetes.
-
-## Platform Registration
-
-The platform-registration indicates that the ServiceCenter automatically accesses `kubernetes` cluster,
-and micro-service instances can discover service and endpoints information through
-the ServiceCenter.
-
-Notes: After deployment, it only create ServiceCenter cluster in the `default` namespace.
-
-#### Use Kubectl
-
-You can use the command `kubectl apply` to deploy ServiceCenter cluster.
-
-```bash
-cd ${PROJECT_ROOT}/examples/infrastructures/k8s
-kubectl apply -f <(helm template --name servicecomb --namespace default service-center/)
-```
-
-#### Use Helm Install
-
-You can also use the helm commands to deploy ServiceCenter cluster if 
-you already deploy helm tiller.
-
-```bash
-cd ${PROJECT_ROOT}/examples/infrastructures/k8s
-helm install --name servicecomb --namespace default service-center/
-```
-
-## Self Registration
-
-The self-registration representational ServiceCenter receives and 
-processes registration requests from micro-service instances and 
-stores instance information in `etcd`.
-
-Notes: After deployment, it create ServiceCenter cluster and etcd cluster in the `default` namespace.
-
-#### Use Kubectl
-
-You can use the command `kubectl apply` to deploy ServiceCenter cluster.
-
-```bash
-cd ${PROJECT_ROOT}/examples/infrastructures/k8s
-# install etcd cluster
-kubectl apply -f <(helm template --name coreos --namespace default etcd/)
-# install sc cluster
-kubectl apply -f <(helm template --name servicecomb --namespace default \
- --set sc.discovery.type="etcd" \
- --set sc.discovery.uris="http://coreos-etcd-client:2379" \
- service-center/)
-```
-
-#### Use Helm Install
-
-You can also use the helm commands to deploy ServiceCenter cluster if
-you already deploy helm tiller.
-
-```bash
-cd ${PROJECT_ROOT}/examples/infrastructures/k8s
-# install etcd cluster
-helm install --name coreos --namespace default etcd/
-# install sc cluster
-helm install --name servicecomb --namespace default \
- --set sc.discovery.type="etcd" \
- --set sc.discovery.uris="http://coreos-etcd-client:2379" \
- service-center/
-```
-
-## Confirm the deploy is ok
-
-By default, the ServiceCenter frontend use `NodePort` service type to deploy in Kubernetes.
-
-1. You can execute the command `kubectl get pod`, to check all pods are running.
-1. You can also point your browser to `http://${NODE}:30103` to view the dashboard of ServiceCenter.
-1. (Recommended) You can use [`scctl`](/scctl) tool to list micro-service information.
-
-```bash
-# ./scctl get svc --addr http://servicecomb-service-center:30100 -owide
-  DOMAIN  |                  NAME               |            APPID        | VERSIONS | ENV | FRAMEWORK  |        ENDPOINTS         | AGE  
-+---------+-------------------------------------+-------------------------+----------+-----+------------+--------------------------+-----+
-  default | servicecomb-service-center-frontend | service-center-frontend | 0.0.1    |     | Kubernetes | http://172.0.1.101:30103 | 2m   
-  default | servicecomb-service-center          | service-center          | 0.0.1    |     | Kubernetes | http://172.0.1.102:30100 | 2m
-```
-
-## Clean up
-
-If you use the kubectl to deploy, take deploy mode `platform registration` as example.
-
-```bash
-cd ${PROJECT_ROOT}/examples/infrastructures/k8s
-kubectl delete -f <(helm template --name servicecomb --namespace default service-center/)
-```
-
-If you use helm tiller to deploy, take deploy mode `platform registration` as example.
-
-```bash
-cd ${PROJECT_ROOT}/k8s
-helm delete --purge servicecomb
-```
\ No newline at end of file
diff --git a/examples/infrastructures/k8s/service-center/templates/configmap.yaml b/examples/infrastructures/k8s/service-center/templates/configmap.yaml
index e9c8dcd..1a2c72d 100644
--- a/examples/infrastructures/k8s/service-center/templates/configmap.yaml
+++ b/examples/infrastructures/k8s/service-center/templates/configmap.yaml
@@ -1,3 +1,4 @@
+{{- if .Values.sc.deployment -}}
 ---
 apiVersion: v1
 kind: ConfigMap
@@ -13,36 +14,29 @@ data:
   app-config: |
     httpaddr = ${HOSTNAME}
     httpport = {{ .Values.sc.service.internalPort }}
-    {{- if eq .Values.sc.discovery.type "k8s" }}
-    discovery_plugin = k8s
-    registry_plugin = buildin
-    self_register = 0
-    {{- else if eq .Values.sc.discovery.type "etcd" }}
-    discovery_plugin = etcd
-    registry_plugin = etcd
+
+    {{- if .Values.sc.registry.enabled }}
     self_register = 1
-    manager_cluster = {{ .Values.sc.discovery.uris }}
-    {{- else if eq .Values.sc.discovery.type "servicecenter" }}
-    discovery_plugin = servicecenter
-    registry_plugin = buildin
-    self_register = 0
-    manager_cluster = "{{ .Values.sc.discovery.clusters }}"
-    {{- else if eq .Values.sc.discovery.type "aggregate" }}
-    discovery_plugin = aggregate
-    registry_plugin = buildin
+    {{- else }}
     self_register = 0
+    {{- end }}
+    registry_plugin = {{ .Values.sc.registry.type }}
+    manager_name = "{{ .Values.sc.registry.name }}"
+    manager_addr = "{{ .Values.sc.registry.addr }}"
+
+    {{- if ne .Values.sc.discovery.type "local" }}
+    discovery_plugin = {{ .Values.sc.discovery.type }}
+    aggregate_mode = "{{ .Values.sc.discovery.aggregate }}"
     manager_cluster = "{{ .Values.sc.discovery.clusters }}"
     {{- else }}
     discovery_plugin = etcd
-    registry_plugin = embeded_etcd
-    self_register = 1
-    manager_name = "sr-0"
-    manager_addr = "http://127.0.0.1:2380"
-    manager_cluster = "sr-0=http://127.0.0.1:2380"
     {{- end }}
+
     ssl_mode = 0
     enable_pprof = 1
+{{- end }}
 
+{{- if .Values.frontend.deployment -}}
 ---
 apiVersion: v1
 kind: ConfigMap
@@ -60,3 +54,4 @@ data:
     frontend_host_port = {{ .Values.frontend.service.internalPort }}
     httpaddr = {{ template "service-center.fullname" . }}
     httpport = {{ .Values.sc.service.externalPort }}
+{{- end }}
diff --git a/examples/infrastructures/k8s/service-center/templates/deployment.yaml b/examples/infrastructures/k8s/service-center/templates/deployment.yaml
index f016f8a..8bf7418 100644
--- a/examples/infrastructures/k8s/service-center/templates/deployment.yaml
+++ b/examples/infrastructures/k8s/service-center/templates/deployment.yaml
@@ -1,5 +1,6 @@
 {{- $serviceName := include "service-center.fullname" . -}}
 {{- $servicePort := .Values.sc.service.externalPort -}}
+{{- if .Values.sc.deployment -}}
 ---
 apiVersion: extensions/v1beta1
 kind: Deployment
@@ -51,7 +52,9 @@ spec:
       nodeSelector:
 {{ toYaml .Values.sc.nodeSelector | indent 8 }}
     {{- end }}
+{{- end }}
 
+{{- if .Values.frontend.deployment -}}
 ---
 apiVersion: extensions/v1beta1
 kind: Deployment
@@ -102,3 +105,4 @@ spec:
       nodeSelector:
 {{ toYaml .Values.frontend.nodeSelector | indent 8 }}
     {{- end }}
+{{- end }}
diff --git a/examples/infrastructures/k8s/service-center/templates/ingress.yaml b/examples/infrastructures/k8s/service-center/templates/ingress.yaml
index 14b7fa0..2d74596 100644
--- a/examples/infrastructures/k8s/service-center/templates/ingress.yaml
+++ b/examples/infrastructures/k8s/service-center/templates/ingress.yaml
@@ -1,3 +1,4 @@
+{{- if .Values.sc.deployment -}}
 {{- if .Values.sc.ingress.enabled -}}
 {{- $serviceName := include "service-center.fullname" . -}}
 {{- $servicePort := .Values.sc.service.externalPort -}}
@@ -32,3 +33,4 @@ spec:
 {{ toYaml .Values.sc.ingress.tls | indent 4 }}
   {{- end -}}
 {{- end -}}
+{{- end -}}
diff --git a/examples/infrastructures/k8s/service-center/templates/rbac.yaml b/examples/infrastructures/k8s/service-center/templates/rbac.yaml
index ab34413..c9f35b4 100644
--- a/examples/infrastructures/k8s/service-center/templates/rbac.yaml
+++ b/examples/infrastructures/k8s/service-center/templates/rbac.yaml
@@ -1,3 +1,4 @@
+{{- if .Values.sc.deployment -}}
 {{- if or (eq .Values.sc.discovery.type "k8s") (eq .Values.sc.discovery.type "aggregate") -}}
 ---
 apiVersion: rbac.authorization.k8s.io/v1
@@ -46,6 +47,7 @@ subjects:
     namespace: {{ .Release.Namespace }}
 
 {{ end -}}
+{{ end -}}
 ---
 apiVersion: v1
 kind: ServiceAccount
@@ -57,4 +59,3 @@ metadata:
     chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
     release: {{ .Release.Name }}
     heritage: {{ .Release.Service }}
-
diff --git a/examples/infrastructures/k8s/service-center/templates/service.yaml b/examples/infrastructures/k8s/service-center/templates/service.yaml
index b907537..078b6df 100644
--- a/examples/infrastructures/k8s/service-center/templates/service.yaml
+++ b/examples/infrastructures/k8s/service-center/templates/service.yaml
@@ -1,3 +1,4 @@
+{{- if .Values.sc.deployment -}}
 ---
 apiVersion: v1
 kind: Service
@@ -22,7 +23,9 @@ spec:
   selector:
     app: {{ template "service-center.name" . }}
     release: {{ .Release.Name }}
+{{- end }}
 
+{{- if .Values.frontend.deployment -}}
 ---
 apiVersion: v1
 kind: Service
@@ -47,3 +50,4 @@ spec:
   selector:
     app: {{ template "service-center.name" . }}-frontend
     release: {{ .Release.Name }}
+{{- end }}
diff --git a/examples/infrastructures/k8s/service-center/values.yaml b/examples/infrastructures/k8s/service-center/values.yaml
index 05bbf6d..ebe4067 100644
--- a/examples/infrastructures/k8s/service-center/values.yaml
+++ b/examples/infrastructures/k8s/service-center/values.yaml
@@ -2,7 +2,8 @@
 # This is a YAML-formatted file.
 # Declare variables to be passed into your templates.
 frontend:
-  replicaCount: 2
+  deployment: true
+  replicaCount: 1
   image:
     repository: servicecomb/scfrontend
     tag: latest
@@ -15,28 +16,23 @@ frontend:
   resources: {}
 
 sc:
-  replicaCount: 2
+  deployment: true
+  replicaCount: 1
   discovery:
-    # support local, servicecenter, etcd, k8s and aggregate discovery mode
-    # type: local
-    #   bootstrap a lightweight service center, can only support replicaCount is one
-    # type: servicecenter
-    #   The precondition is that one or more service center clusters have been deployed,
-    #   this deployment will bootstrap a service center aggregation service which
-    #   provides micro-services and instances information aggregation queries
-    # type: etcd
-    #   bootstrap a standard service center cluster which micro-services and instances
-    #   information stored in etcd
-    # type: k8s
-    #   bootstrap a standard service center cluster which micro-services and instances
-    #   information discovered from kubernetes services
-    # type: aggregate
-    #   this type not only support aggregate service center cluster but also aggregate
-    #   the kubernetes services
-    type: k8s
+    # support servicecenter, etcd, and aggregate discovery mode
+    type: aggregate
     # the cluster urls list, can only support discovery type is "servicecenter" or "aggregate"
     # e.g. clusters: "sc-0=http://service-center-1:30100,sc-1=http://service-center-2:30100"
-    clusters: ""
+    clusters: "sc-0=http://127.0.0.1:2380"
+    # setting up the configuration of aggregator, only enabled when discovery type is "aggregate"
+    # e.g. aggregate: "k8s,servicecenter"
+    aggregate: "k8s,etcd"
+  registry:
+    enabled: false
+    # support embeded_etcd, etcd, and buildin registry mode
+    type: "embeded_etcd"
+    name: "sc-0"
+    addr: "http://127.0.0.1:2380"
   image:
     repository: servicecomb/service-center
     tag: latest
diff --git a/server/bootstrap/bootstrap.go b/server/bootstrap/bootstrap.go
index c0ebc88..2f80cc0 100644
--- a/server/bootstrap/bootstrap.go
+++ b/server/bootstrap/bootstrap.go
@@ -27,7 +27,7 @@ import _ "github.com/apache/incubator-servicecomb-service-center/server/plugin/p
 
 // discovery
 import _ "github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery/aggregate"
-import _ "github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery/sc"
+import _ "github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery/servicecenter"
 import _ "github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery/etcd"
 import _ "github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery/k8s"
 
diff --git a/server/plugin/pkg/discovery/aggregate/adaptor.go b/server/plugin/pkg/discovery/aggregate/adaptor.go
index ad1327e..7196d11 100644
--- a/server/plugin/pkg/discovery/aggregate/adaptor.go
+++ b/server/plugin/pkg/discovery/aggregate/adaptor.go
@@ -25,9 +25,9 @@ import (
 // Aggregator is a discovery service adaptor implement of one kubernetes cluster
 type Aggregator []discovery.Adaptor
 
-func (as *Aggregator) Search(ctx context.Context, opts ...registry.PluginOpOption) (*discovery.Response, error) {
+func (as Aggregator) Search(ctx context.Context, opts ...registry.PluginOpOption) (*discovery.Response, error) {
 	var response discovery.Response
-	for _, a := range *as {
+	for _, a := range as {
 		resp, err := a.Search(ctx, opts...)
 		if err != nil {
 			continue
@@ -38,34 +38,37 @@ func (as *Aggregator) Search(ctx context.Context, opts ...registry.PluginOpOptio
 	return &response, nil
 }
 
-func (as *Aggregator) Cache() discovery.Cache {
-	return discovery.NullCache
+func (as Aggregator) Cache() discovery.Cache {
+	var cache Cache
+	for _, a := range as {
+		cache = append(cache, a.Cache())
+	}
+	return cache
 }
 
-func (as *Aggregator) Run() {
-	for _, a := range *as {
+func (as Aggregator) Run() {
+	for _, a := range as {
 		a.Run()
 	}
 }
 
-func (as *Aggregator) Stop() {
-	for _, a := range *as {
+func (as Aggregator) Stop() {
+	for _, a := range as {
 		a.Stop()
 	}
 }
 
-func (as *Aggregator) Ready() <-chan struct{} {
-	for _, a := range *as {
+func (as Aggregator) Ready() <-chan struct{} {
+	for _, a := range as {
 		<-a.Ready()
 	}
 	return closedCh
 }
 
-func NewAggregator(t discovery.Type, cfg *discovery.Config) (as *Aggregator) {
-	as = &Aggregator{}
+func NewAggregator(t discovery.Type, cfg *discovery.Config) (as Aggregator) {
 	for _, name := range repos {
 		repo := mgr.Plugins().Get(mgr.DISCOVERY, name).New().(discovery.AdaptorRepository)
-		*as = append(*as, repo.New(t, cfg))
+		as = append(as, repo.New(t, cfg))
 	}
 	return as
 }
diff --git a/server/plugin/pkg/discovery/aggregate/cache.go b/server/plugin/pkg/discovery/aggregate/cache.go
new file mode 100644
index 0000000..28c65ad
--- /dev/null
+++ b/server/plugin/pkg/discovery/aggregate/cache.go
@@ -0,0 +1,55 @@
+// Licensed to the 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.
+// The 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.
+
+package aggregate
+
+import "github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery"
+
+type Cache []discovery.Cache
+
+func (c Cache) Name() string { return c[0].Name() }
+func (c Cache) Size() (s int) {
+	for _, cache := range c {
+		s += cache.Size()
+	}
+	return s
+}
+func (c Cache) Get(k string) (kv *discovery.KeyValue) {
+	for _, cache := range c {
+		if kv = cache.Get(k); kv != nil {
+			return
+		}
+	}
+	return
+}
+func (c Cache) GetAll(arr *[]*discovery.KeyValue) (s int) {
+	for _, cache := range c {
+		s += cache.GetAll(arr)
+	}
+	return
+}
+func (c Cache) GetPrefix(prefix string, arr *[]*discovery.KeyValue) (s int) {
+	for _, cache := range c {
+		s += cache.GetPrefix(prefix, arr)
+	}
+	return
+}
+func (c Cache) ForEach(iter func(k string, v *discovery.KeyValue) (next bool)) {
+	for _, cache := range c {
+		cache.ForEach(iter)
+	}
+}
+func (c Cache) Put(k string, v *discovery.KeyValue) { return }
+func (c Cache) Remove(k string)                     { return }
diff --git a/server/plugin/pkg/discovery/aggregate/common.go b/server/plugin/pkg/discovery/aggregate/common.go
index 48679e0..b5fa265 100644
--- a/server/plugin/pkg/discovery/aggregate/common.go
+++ b/server/plugin/pkg/discovery/aggregate/common.go
@@ -15,11 +15,30 @@
 
 package aggregate
 
+import (
+	"github.com/apache/incubator-servicecomb-service-center/pkg/log"
+	"github.com/astaxie/beego"
+	"strings"
+)
+
+const (
+	Aggregate      = "aggregate"
+	AggregateModes = "k8s,servicecenter"
+)
+
 var (
 	closedCh = make(chan struct{})
-	repos    = []string{"k8s", "servicecenter"}
+	repos    []string
 )
 
 func init() {
 	close(closedCh)
+
+	if Aggregate != beego.AppConfig.String("discovery_plugin") {
+		return
+	}
+
+	modes := beego.AppConfig.DefaultString("aggregate_mode", AggregateModes)
+	repos = strings.Split(modes, ",")
+	log.Infof("aggregate_mode is %s", repos)
 }
diff --git a/server/plugin/pkg/discovery/aggregate/repo.go b/server/plugin/pkg/discovery/aggregate/repo.go
index e7f34b3..18ecde6 100644
--- a/server/plugin/pkg/discovery/aggregate/repo.go
+++ b/server/plugin/pkg/discovery/aggregate/repo.go
@@ -21,7 +21,7 @@ import (
 )
 
 func init() {
-	mgr.RegisterPlugin(mgr.Plugin{mgr.DISCOVERY, "aggregate", NewRepository})
+	mgr.RegisterPlugin(mgr.Plugin{mgr.DISCOVERY, Aggregate, NewRepository})
 }
 
 type AggregateRepository struct {
diff --git a/server/plugin/pkg/discovery/sc/adaptor.go b/server/plugin/pkg/discovery/servicecenter/adaptor.go
similarity index 98%
rename from server/plugin/pkg/discovery/sc/adaptor.go
rename to server/plugin/pkg/discovery/servicecenter/adaptor.go
index 0b12378..99726a5 100644
--- a/server/plugin/pkg/discovery/sc/adaptor.go
+++ b/server/plugin/pkg/discovery/servicecenter/adaptor.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package sc
+package servicecenter
 
 import (
 	"github.com/apache/incubator-servicecomb-service-center/server/core/backend"
diff --git a/server/plugin/pkg/discovery/sc/aggregate.go b/server/plugin/pkg/discovery/servicecenter/aggregate.go
similarity index 97%
rename from server/plugin/pkg/discovery/sc/aggregate.go
rename to server/plugin/pkg/discovery/servicecenter/aggregate.go
index d16430c..fd14ad6 100644
--- a/server/plugin/pkg/discovery/sc/aggregate.go
+++ b/server/plugin/pkg/discovery/servicecenter/aggregate.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package sc
+package servicecenter
 
 import (
 	"github.com/apache/incubator-servicecomb-service-center/pkg/client/sc"
@@ -51,7 +51,7 @@ func (c *SCClientAggregate) GetSchemasByServiceId(domainProject, serviceId strin
 	var schemas []*pb.Schema
 	for _, client := range *c {
 		ss, err := client.GetSchemasByServiceId(domainProject, serviceId)
-		if err != nil {
+		if err != nil && err.InternalError() {
 			log.Errorf(err, "get schema by serviceId[%s/%s] failed", domainProject, serviceId)
 			continue
 		}
@@ -64,7 +64,7 @@ func (c *SCClientAggregate) GetSchemasByServiceId(domainProject, serviceId strin
 func (c *SCClientAggregate) GetSchemaBySchemaId(domainProject, serviceId, schemaId string) (schema *pb.Schema, err *scerr.Error) {
 	for _, client := range *c {
 		schema, err = client.GetSchemaBySchemaId(domainProject, serviceId, schemaId)
-		if err != nil {
+		if err != nil && err.InternalError() {
 			log.Errorf(err, "get schema by serviceId[%s/%s] failed", domainProject, serviceId)
 			continue
 		}
diff --git a/server/plugin/pkg/discovery/sc/cacher.go b/server/plugin/pkg/discovery/servicecenter/cacher.go
similarity index 98%
rename from server/plugin/pkg/discovery/sc/cacher.go
rename to server/plugin/pkg/discovery/servicecenter/cacher.go
index 01f0861..01eb9b4 100644
--- a/server/plugin/pkg/discovery/sc/cacher.go
+++ b/server/plugin/pkg/discovery/servicecenter/cacher.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package sc
+package servicecenter
 
 import (
 	"github.com/apache/incubator-servicecomb-service-center/server/plugin/pkg/discovery"
diff --git a/server/plugin/pkg/discovery/sc/cluster.go b/server/plugin/pkg/discovery/servicecenter/cluster.go
similarity index 99%
rename from server/plugin/pkg/discovery/sc/cluster.go
rename to server/plugin/pkg/discovery/servicecenter/cluster.go
index a07a241..5c0bdd0 100644
--- a/server/plugin/pkg/discovery/sc/cluster.go
+++ b/server/plugin/pkg/discovery/servicecenter/cluster.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package sc
+package servicecenter
 
 import (
 	"fmt"
diff --git a/server/plugin/pkg/discovery/sc/common.go b/server/plugin/pkg/discovery/servicecenter/common.go
similarity index 97%
rename from server/plugin/pkg/discovery/sc/common.go
rename to server/plugin/pkg/discovery/servicecenter/common.go
index d6227fd..d59957f 100644
--- a/server/plugin/pkg/discovery/sc/common.go
+++ b/server/plugin/pkg/discovery/servicecenter/common.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package sc
+package servicecenter
 
 import "time"
 
diff --git a/server/plugin/pkg/discovery/sc/repo.go b/server/plugin/pkg/discovery/servicecenter/repo.go
similarity index 98%
rename from server/plugin/pkg/discovery/sc/repo.go
rename to server/plugin/pkg/discovery/servicecenter/repo.go
index cedc6f6..96f0889 100644
--- a/server/plugin/pkg/discovery/sc/repo.go
+++ b/server/plugin/pkg/discovery/servicecenter/repo.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package sc
+package servicecenter
 
 import (
 	mgr "github.com/apache/incubator-servicecomb-service-center/server/plugin"
diff --git a/server/plugin/pkg/registry/etcd/etcd.go b/server/plugin/pkg/registry/etcd/etcd.go
index b94fa00..c940828 100644
--- a/server/plugin/pkg/registry/etcd/etcd.go
+++ b/server/plugin/pkg/registry/etcd/etcd.go
@@ -700,7 +700,7 @@ func (c *EtcdClient) HealthCheck() {
 }
 
 func (c *EtcdClient) healthCheckLoop(pctx context.Context) {
-	retries := healthCheckRetryTimes
+	retries, start := healthCheckRetryTimes, time.Now()
 hcLoop:
 	for {
 		select {
@@ -711,20 +711,24 @@ hcLoop:
 			for i := 0; i < retries; i++ {
 				ctx, _ := context.WithTimeout(c.Client.Ctx(), healthCheckTimeout)
 				if err = c.SyncMembers(ctx); err != nil {
+					d := util.GetBackoff().Delay(i)
+					log.Errorf(err, "retry to sync members from etcd %s after %s", c.Endpoints, d)
 					select {
 					case <-pctx.Done():
 						return
-					case <-time.After(util.GetBackoff().Delay(i)):
+					case <-time.After(d):
 						continue
 					}
 				}
-				retries = healthCheckRetryTimes
+				retries, start = healthCheckRetryTimes, time.Now()
 				continue hcLoop
 			}
 
 			retries = 1 // fail fast
-			if cerr := c.ReOpen(); cerr == nil {
-				log.Errorf(err, "re-connected to etcd %s", c.Endpoints)
+			if cerr := c.ReOpen(); cerr != nil {
+				log.Errorf(cerr, "retry to health check etcd %s after %s", c.Endpoints, c.AutoSyncInterval)
+			} else {
+				log.Infof("[%s]re-connected to etcd %s", time.Now().Sub(start), c.Endpoints)
 			}
 		}
 	}
diff --git a/server/server.go b/server/server.go
index 8702454..37bb393 100644
--- a/server/server.go
+++ b/server/server.go
@@ -34,6 +34,8 @@ import (
 	"time"
 )
 
+const buildin = "buildin"
+
 type ServiceCenterServer struct {
 	apiServer     *APIServer
 	notifyService *nf.NotifyService
@@ -144,6 +146,8 @@ func (s *ServiceCenterServer) initialize() {
 	if core.ServerInfo.Config.SelfRegister {
 		// check version
 		s.loadOrUpgradeServerVersion()
+	}
+	if buildin != beego.AppConfig.DefaultString("registry_plugin", buildin) {
 		// compact backend automatically
 		s.compactBackendService()
 	}