You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2022/07/20 10:34:00 UTC

[skywalking-swck] branch master updated: Add CRD, Controller, e2e for OAPServer's configuration (#65)

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

hanahmily pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-swck.git


The following commit(s) were added to refs/heads/master by this push:
     new e822fca  Add CRD, Controller, e2e for OAPServer's configuration (#65)
e822fca is described below

commit e822fca26c0f6b15fac3d9d9a936dc4f4ccb9707
Author: dashanji <da...@gmail.com>
AuthorDate: Wed Jul 20 18:33:55 2022 +0800

    Add CRD, Controller, e2e for OAPServer's configuration (#65)
    
    * Add CRD OAPServerConfig, Controller, and Webhooks to support static and dynamic configuration for OAPServer.
    * Add the e2e test for OAPServerConfig and OAPServerDynamicConfig.
    * Add the usage doc about OAPServerConfig and OAPServerDynamicConfig.
    
    Signed-off-by: dashanji <da...@gmail.com>
    Co-authored-by: Gao Hongtao <ha...@gmail.com>
---
 .github/workflows/go.yml                           |  17 +-
 CHANGES.md                                         |  15 +
 Makefile                                           |   8 +-
 docs/examples/java-agent-injector-usage.md         |   4 +-
 docs/examples/storage.md                           |   4 +-
 docs/java-agent-injector.md                        |   4 +-
 docs/oapserver-configuration.md                    | 279 +++++++++++++++++++
 hack/prepare-e2e.sh                                |   2 +-
 operator/PROJECT                                   |  26 ++
 .../operator/v1alpha1/oapserverconfig_types.go     |  88 ++++++
 .../operator/v1alpha1/oapserverconfig_webhook.go   |  81 ++++++
 .../v1alpha1/oapserverdynamicconfig_types.go       |  80 ++++++
 .../v1alpha1/oapserverdynamicconfig_webhook.go     |  88 ++++++
 .../operator/v1alpha1/zz_generated.deepcopy.go     | 229 +++++++++++++++
 .../operator.skywalking.apache.org_fetchers.yaml   |   2 +-
 .../operator.skywalking.apache.org_javaagents.yaml |   2 +-
 ...or.skywalking.apache.org_oapserverconfigs.yaml} | 142 ++++------
 ...alking.apache.org_oapserverdynamicconfigs.yaml} |  80 +++---
 .../operator.skywalking.apache.org_oapservers.yaml |   2 +-
 .../operator.skywalking.apache.org_satellites.yaml |   2 +-
 .../operator.skywalking.apache.org_storages.yaml   |   2 +-
 .../bases/operator.skywalking.apache.org_uis.yaml  |   2 +-
 operator/config/crd/kustomization.yaml             |   6 +
 .../patches/cainjection_in_oapserverconfigs.yaml}  |  24 +-
 .../cainjection_in_oapserverdynamicconfigs.yaml}   |  24 +-
 .../patches/webhook_in_oapserverconfigs.yaml}      |  31 +--
 .../webhook_in_oapserverdynamicconfigs.yaml}       |  31 +--
 .../rbac/oapserverconfig_editor_role.yaml}         |  34 ++-
 .../rbac/oapserverconfig_viewer_role.yaml}         |  30 +-
 .../rbac/oapserverdynamicconfig_editor_role.yaml}  |  34 ++-
 .../rbac/oapserverdynamicconfig_viewer_role.yaml}  |  30 +-
 operator/config/rbac/role.yaml                     |  42 ++-
 operator/config/samples/default.yaml               |   8 +-
 operator/config/samples/fetcher.yaml               |   8 +-
 operator/config/samples/minimal.yaml               |   4 +-
 operator/config/samples/oapserverconfig.yaml       |  95 +++++++
 .../config/samples/oapserverdynamicconfig.yaml     | 114 ++++++++
 operator/config/webhook/manifests.yaml             |  82 +++++-
 .../controllers/operator/fetcher_controller.go     |  31 ++-
 .../controllers/operator/javaagent_controller.go   |  29 +-
 .../controllers/operator/oapserver_controller.go   |  32 ++-
 .../operator/oapserverconfig_controller.go         | 308 +++++++++++++++++++++
 .../operator/oapserverdynamicconfig_controller.go  | 303 ++++++++++++++++++++
 .../controllers/operator/satellite_controller.go   |  22 +-
 .../controllers/operator/storage_controller.go     |  22 +-
 operator/controllers/operator/ui_controller.go     |  23 +-
 operator/main.go                                   |  26 +-
 .../manifests/injector/templates/annotations.yaml  |   2 +-
 .../oapserver/templates/cluster_role.yaml          |   2 +-
 test/e2e/kind.yaml                                 |  23 +-
 test/e2e/oap-agent-adapter-hpa/e2e.yaml            |   7 +-
 test/e2e/oap-satellite-adapter-hpa/e2e.yaml        |  12 +-
 test/e2e/oap-ui-agent-external-storage/e2e.yaml    |   8 +-
 test/e2e/oap-ui-agent-internal-storage/e2e.yaml    |   2 +-
 .../e2e.yaml                                       |  48 +++-
 test/e2e/oap-ui-agent-satellite/e2e.yaml           |   2 +-
 test/e2e/oap-ui-agent/e2e.yaml                     |   2 +-
 test/e2e/oapserverconfig-demo.yaml                 |  87 ++++++
 test/e2e/oapserverdynamicconfig-demo.yaml          | 117 ++++++++
 test/e2e/resource.yaml                             |  62 +++++
 test/e2e/satellite-hpa-demo.yaml                   |   3 -
 test/e2e/skywalking-components-with-satellite.yaml |   8 +-
 test/e2e/skywalking-components-with-storage.yaml   |   8 +-
 test/e2e/skywalking-components.yaml                |   8 +-
 .../{satellite-hpa-demo.yaml => verify/logs.yaml}  |  50 ++--
 .../service-apdex.yaml}                            |  32 +--
 66 files changed, 2621 insertions(+), 414 deletions(-)

diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 3112cb0..bd51eea 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -161,9 +161,24 @@ jobs:
         uses: apache/skywalking-infra-e2e@996ed8902e941e2883fcf0ac5b3090364942d205
         with:
           e2e-file: test/e2e/oap-satellite-adapter-hpa/e2e.yaml
+  oapserver-configuration-e2e-tests:
+    name: e2e tests(oap+ui+agent+oapserverconfig+oapserverdynamicconfig)
+    runs-on: ubuntu-latest
+    steps:
+      - name: Install Go
+        uses: actions/setup-go@v2
+        with:
+          go-version: 1.17
+        id: go
+      - name: Check out code into the Go module directory
+        uses: actions/checkout@v2
+      - name: Run E2E Test
+        uses: apache/skywalking-infra-e2e@996ed8902e941e2883fcf0ac5b3090364942d205     
+        with:
+          e2e-file: test/e2e/oap-ui-agent-oapserverconfig-oapserverdynamicconfig/e2e.yaml
   checks:
     name: build
     runs-on: ubuntu-20.04
-    needs: [check, build, unit-tests, e2e-tests, internel-storage-e2e-tests, external-storage-e2e-tests , adapter-hpa-e2e-tests]
+    needs: [check, build, unit-tests, e2e-tests, internel-storage-e2e-tests, external-storage-e2e-tests, adapter-hpa-e2e-tests, e2e-tests-with-satellite, adapter-satellite-hpa-e2e-tests, oapserver-configuration-e2e-tests]
     steps:
       - run: echo 'success'
diff --git a/CHANGES.md b/CHANGES.md
index bf6c2ab..067996d 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,21 @@ Changes by Version
 ==================
 Release Notes.
 
+0.7.0
+------------------
+
+#### Features
+- Add the OAPServerConfig CRD, webhooks and controller.
+- Add the OAPServerDynamicConfig CRD, webhooks and controller.
+
+#### Bugs
+- Fixed the error in e2e testing.
+- Fixed status inconsistent with CI.
+
+#### Chores
+- Bump up SkyWalking OAP to 9.0.0.
+- Bump up the k8s api of the e2e environment to v1.21.10
+
 0.6.1
 ------------------
 
diff --git a/Makefile b/Makefile
index 6f2285f..f85251e 100644
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,7 @@ clean: ## Clean project
 ##@ End to End Test
 
 .PHONY:e2e-test
-e2e-test: e2e-oap-ui-agent e2e-oap-ui-agent-storage-internal e2e-oap-agent-adapter-hpa e2e-oap-ui-agent-satellite e2e-oap-agent-satellite-adapter-hpa ## Run End to End tests.
+e2e-test: e2e-oap-ui-agent e2e-oap-ui-agent-storage-internal e2e-oap-agent-adapter-hpa e2e-oap-ui-agent-satellite e2e-oap-agent-satellite-adapter-hpa e2e-oap-ui-agent-oapserverconfig-oapserverdynamicconfig ## Run End to End tests.
 
 .PHONY:e2e-oap-ui-agent
 e2e-oap-ui-agent: e2e ## Run oap+ui+agent test
@@ -81,6 +81,11 @@ e2e-oap-agent-satellite-adapter-hpa: e2e ## Run oap+agent+satellite+adapter HPA
 	@echo "Run Satellite HPA e2e..."
 	$(E2E) run -c test/e2e/oap-satellite-adapter-hpa/e2e.yaml
 
+.PHONY:e2e-oap-ui-agent-oapserverconfig-oapserverdynamicconfig
+e2e-oap-ui-agent-oapserverconfig-oapserverdynamicconfig: e2e ## Run e2e-oap-ui-agent-oapserverconfig-oapserverdynamicconfig test
+	@echo "Run e2e-oap-ui-agent-oapserverconfig-oapserverdynamicconfig e2e..."
+	$(E2E) run -c test/e2e/oap-ui-agent-oapserverconfig/e2e.yaml
+
 E2E = $(tool_bin)/cmd
 .PHONY: e2e
 e2e: ## Download e2e-setup locally if necessary.
@@ -90,7 +95,6 @@ e2e: ## Download e2e-setup locally if necessary.
 
 .PHONY: check
 check: ## Check that the status
-	$(MAKE) -C operator generate
 	$(MAKE) -C operator lint
 	$(MAKE) -C operator dependency-resolve
 	$(MAKE) -C operator check
diff --git a/docs/examples/java-agent-injector-usage.md b/docs/examples/java-agent-injector-usage.md
index 960e5cc..e7b17ea 100644
--- a/docs/examples/java-agent-injector-usage.md
+++ b/docs/examples/java-agent-injector-usage.md
@@ -65,7 +65,7 @@ spec:
     - mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent
     command:
     - sh
-    image: apache/skywalking-java-agent:8.8.0-java8
+    image: apache/skywalking-java-agent:8.10.0-java8
     name: inject-skywalking-agent
     volumeMounts:
     - mountPath: /sky/agent
@@ -343,7 +343,7 @@ spec:
       -i cp {} /sky/agent/plugins/
     command:
     - sh
-    image: apache/skywalking-java-agent:8.8.0-java8
+    image: apache/skywalking-java-agent:8.10.0-java8
     name: inject-skywalking-agent
     volumeMounts:
     - mountPath: /sky/agent
diff --git a/docs/examples/storage.md b/docs/examples/storage.md
index ae2249d..a0a66da 100644
--- a/docs/examples/storage.md
+++ b/docs/examples/storage.md
@@ -84,9 +84,9 @@ kind: OAPServer
 metadata:
   name: default
 spec:
-  version: 8.8.1
+  version: 9.0.0
   instances: 1
-  image: apache/skywalking-oap-server:8.8.1
+  image: apache/skywalking-oap-server:9.0.0
   service:
     template:
       type: ClusterIP
diff --git a/docs/java-agent-injector.md b/docs/java-agent-injector.md
index 495d78e..1d368e1 100644
--- a/docs/java-agent-injector.md
+++ b/docs/java-agent-injector.md
@@ -98,7 +98,7 @@ initContainers:
     - mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent
     command:
     - sh
-    image: apache/skywalking-java-agent:8.8.0-java8
+    image: apache/skywalking-java-agent:8.10.0-java8
     name: inject-skywalking-agent
     volumeMounts:
     - mountPath: /sky/agent
@@ -155,7 +155,7 @@ The injector can recognize the following annotations to configure the sidecar:
 | Annotation key                                               | Description                                                  | Annotation Default value                                     |
 | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
 | `sidecar.skywalking.apache.org/initcontainer.Name`           | The name of the injected java agent container.               | `inject-skywalking-agent`                                    |
-| `sidecar.skywalking.apache.org/initcontainer.Image`          | The container image of the injected java agent container.    | `apache/skywalking-java-agent:8.8.0-java8`                    |
+| `sidecar.skywalking.apache.org/initcontainer.Image`          | The container image of the injected java agent container.    | `apache/skywalking-java-agent:8.10.0-java8`                    |
 | `sidecar.skywalking.apache.org/initcontainer.Command`        | The command of the injected java agent container.            | `sh`                                                         |
 | `sidecar.skywalking.apache.org/initcontainer.args.Option`    | The args option of the injected java agent container.       | `-c`                                                         |
 | `sidecar.skywalking.apache.org/initcontainer.args.Command`   | The args command of the injected java agent container.       | `mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent` |
diff --git a/docs/oapserver-configuration.md b/docs/oapserver-configuration.md
new file mode 100644
index 0000000..3ce1cda
--- /dev/null
+++ b/docs/oapserver-configuration.md
@@ -0,0 +1,279 @@
+## OAPSever Configuration Introduction
+
+To configure the OAP Sever, we propose two CRDs: 
+
+- OAPServerConfig: The CRD holds all static configuration, including [environment variable](https://skywalking.apache.org/docs/main/latest/en/setup/backend/configuration-vocabulary/) and [file configuration](https://github.com/apache/skywalking/tree/master/oap-server/server-starter/src/main/resources).
+- OAPServerDynamicConfig: The CRD holds all [dynamic configuration](https://skywalking.apache.org/docs/main/latest/en/setup/backend/dynamic-config/).
+
+
+
+## Spec of OAPServerConfig
+
+| Field Name | Description                                                  |
+| ---------- | ------------------------------------------------------------ |
+| Version    | The version of OAP server, the default value is 9.0.0        |
+| Env        | The environment variable of OAP server                       |
+| File       | The static file in OAP Server, which contains three fields`file.path`、`file.name` and `file.data`.  The `file.path` plus the `file.name`  is the real file that needs to be replaced in the container image, and the `file.data` is the final data in the specific file. |
+
+
+
+## Status of OAPServerConfig 
+
+| Field Name            | Description                                          |
+| --------------------- | ---------------------------------------------------- |
+| Desired  | The number of oapserver that need to be configured   |
+| Ready     | The number of oapserver that configured successfully |
+| CreationTime          | The time the OAPServerConfig was created.            |
+| LastUpdateTime        | The last time this condition was updated.            |
+
+
+
+## Demo of OAPServerConfig 
+
+> When using the `file`, please don't set the same name
+
+```yaml
+# static configuration of OAPServer
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerConfig
+metadata:
+  name: oapserverconfig-sample
+  namespace: skywalking-system
+spec:
+  # The version of OAPServer
+  version: 9.0.0
+  # The env configuration of OAPServer
+  env:
+    - name: JAVA_OPTS
+      value: -Xmx2048M
+    - name: SW_CLUSTER
+      value: kubernetes
+    - name: SW_CLUSTER_K8S_NAMESPACE
+      value: skywalking-system
+    # enable the dynamic configuration
+    - name: SW_CONFIGURATION
+      value: k8s-configmap
+    # set the labelselector of the dynamic configuration
+    - name: SW_CLUSTER_K8S_LABEL
+      value: app=collector,release=skywalking
+    - name: SW_TELEMETRY
+      value: prometheus
+    - name: SW_HEALTH_CHECKER
+      value: default
+    - name: SKYWALKING_COLLECTOR_UID
+      valueFrom:
+        fieldRef:
+          fieldPath: metadata.uid
+    - name: SW_LOG_LAL_FILES
+      value: test1
+    - name: SW_LOG_MAL_FILES
+      value: test2
+  # The file configuration of OAPServer
+  # we should avoid setting the same file name in the file
+  file:
+    - name: test1.yaml
+      path: /skywalking/config/lal
+      data: |
+        rules:
+          - name: example
+            dsl: |
+              filter {
+                text {
+                  abortOnFailure false // for test purpose, we want to persist all logs
+                  regexp $/(?s)(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}) \[TID:(?<tid>.+?)] \[(?<thread>.+?)] (?<level>\w{4,}) (?<logger>.{1,36}) (?<msg>.+)/$
+                }
+                extractor {
+                  metrics {
+                    timestamp log.timestamp as Long
+                    labels level: parsed.level, service: log.service, instance: log.serviceInstance
+                    name "log_count"
+                    value 1
+                  }
+                }
+                sink {
+                }
+              }
+    - name: test2.yaml
+      path: /skywalking/config/log-mal-rules
+      data: |
+        expSuffix: instance(['service'], ['instance'], Layer.GENERAL)
+        metricPrefix: log
+        metricsRules:
+          - name: count_info
+            exp: log_count.tagEqual('level', 'INFO').sum(['service', 'instance']).downsampling(SUM)
+
+```
+
+
+
+## Spec of OAPServerDynamicConfig
+
+| Field Name    | Description                                            |
+| ------------- | ------------------------------------------------------ |
+| Version       | The version of the OAP server, the default value is 9.0.0      |
+| LabelSelector | The label selector of the specific configmap, the default value is "app=collector,release=skywalking"               |
+| Data          | All configurations' key and value                      |
+
+
+
+## Status of OAPServerDynamicConfig
+
+| Field Name     | Description                                                |
+| -------------- | ---------------------------------------------------------- |
+| State          | The state of dynamic configuration, `running` or `stopped` |
+| CreationTime   | All configurations in one CR, the default value is `false`     |
+| LastUpdateTime | The last time this condition was updated                   |
+
+
+
+## Usage of OAPServerDynamicConfig
+
+> Notice, the CR's name cannot contain capital letters.
+
+Users can split all configurations into several CRs. when using the OAPServerDynamicConfig, users can not only put some configurations in a CR, but also put a configuration in a CR, and the `spec.data.name` in CR represents one dynamic configuration.
+
+
+
+#### Demo of Global configuration
+
+```yaml
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerDynamicConfig
+metadata:
+  name: oapserverdynamicconfig-sample
+spec:
+  # The version of OAPServer
+  version: 9.0.0
+  # The labelselector of OAPServer's dynamic configuration, it should be the same as labelSelector of OAPServerConfig
+  labelSelector: app=collector,release=skywalking
+  data:
+    - name: agent-analyzer.default.slowDBAccessThreshold
+      value: default:200,mongodb:50
+    - name: alarm.default.alarm-settings
+      value: |-
+        rules:
+          # Rule unique name, must be ended with `_rule`.
+          service_resp_time_rule:
+            metrics-name: service_resp_time
+            op: ">"
+            threshold: 1000
+            period: 10
+            count: 3
+            silence-period: 5
+            message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
+          service_sla_rule:
+            # Metrics value need to be long, double or int
+            metrics-name: service_sla
+            op: "<"
+            threshold: 8000
+            # The length of time to evaluate the metrics
+            period: 10
+            # How many times after the metrics match the condition, will trigger alarm
+            count: 2
+            # How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
+            silence-period: 3
+            message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
+          service_resp_time_percentile_rule:
+            # Metrics value need to be long, double or int
+            metrics-name: service_percentile
+            op: ">"
+            threshold: 1000,1000,1000,1000,1000
+            period: 10
+            count: 3
+            silence-period: 5
+            message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
+          service_instance_resp_time_rule:
+            metrics-name: service_instance_resp_time
+            op: ">"
+            threshold: 1000
+            period: 10
+            count: 2
+            silence-period: 5
+            message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
+          database_access_resp_time_rule:
+            metrics-name: database_access_resp_time
+            threshold: 1000
+            op: ">"
+            period: 10
+            count: 2
+            message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes
+          endpoint_relation_resp_time_rule:
+            metrics-name: endpoint_relation_resp_time
+            threshold: 1000
+            op: ">"
+            period: 10
+            count: 2
+            message: Response time of endpoint relation {name} is more than 1000ms in 2 minutes of last 10 minutes
+        #  Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
+        #  Because the number of endpoint is much more than service and instance.
+        #
+        #  endpoint_resp_time_rule:
+        #    metrics-name: endpoint_resp_time
+        #    op: ">"
+        #    threshold: 1000
+        #    period: 10
+        #    count: 2
+        #    silence-period: 5
+        #    message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
+
+        webhooks:
+        #  - http://127.0.0.1/notify/
+        #  - http://127.0.0.1/go-wechat/
+    - name: core.default.apdexThreshold
+      value: |-
+        default: 500
+        # example:
+        # the threshold of service "tomcat" is 1s
+        # tomcat: 1000
+        # the threshold of service "springboot1" is 50ms
+        # springboot1: 50
+    - name: agent-analyzer.default.uninstrumentedGateways
+      value: |-
+        #gateways:
+        #  - name: proxy0
+        #    instances:
+        #      - host: 127.0.0.1 # the host/ip of this gateway instance
+        #        port: 9099 # the port of this gateway instance, defaults to 80
+
+```
+
+
+
+#### Demo of Single configuration
+
+Set the dynamic configuration `agent-analyzer.default.slowDBAccessThreshold` as follows.
+
+```yaml
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerDynamicConfig
+metadata:
+  name: agent-analyzer.default
+spec:
+  # The version of OAPServer
+  version: 9.0.0
+  # The labelselector of OAPServer's dynamic configuration, it should be the same as labelSelector of OAPServerConfig
+  labelSelector: app=collector,release=skywalking
+  data:
+    - name: slowDBAccessThreshold
+      value: default:200,mongodb:50
+```
+
+Set the dynamic configuration `core.default.endpoint-name-grouping-openapi.customerAPI-v1` and `core.default.endpoint-name-grouping-openapi.productAPI-v1` as follows.
+
+```yaml
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerDynamicConfig
+metadata:
+  name: core.default.endpoint-name-grouping-openapi
+spec:
+  # The version of OAPServer
+  version: 9.0.0
+  # The labelselector of OAPServer's dynamic configuration, it should be the same as labelSelector of OAPServerConfig
+  labelSelector: app=collector,release=skywalking
+  data:
+    - name: customerAPI-v1
+      value: value of customerAPI-v1
+    - name: productAPI-v1
+    	value: value of productAPI-v1
+```
+
diff --git a/hack/prepare-e2e.sh b/hack/prepare-e2e.sh
index 8e6ffb9..05fa0dc 100755
--- a/hack/prepare-e2e.sh
+++ b/hack/prepare-e2e.sh
@@ -26,7 +26,7 @@ prepare_ok=true
 function install_kubectl()
 {
     if ! command -v kubectl &> /dev/null; then
-      curl -LO https://dl.k8s.io/release/v1.19.1/bin/${OS}/${ARCH}/kubectl && chmod +x ./kubectl && mv ./kubectl ${INSTALL_DIR}
+      curl -LO https://dl.k8s.io/release/v1.21.10/bin/${OS}/${ARCH}/kubectl && chmod +x ./kubectl && mv ./kubectl ${INSTALL_DIR}
       if [ $? -ne 0 ]; then
         echo "install kubectl error, please check"
         prepare_ok=false
diff --git a/operator/PROJECT b/operator/PROJECT
index 93216a7..d8e71ea 100644
--- a/operator/PROJECT
+++ b/operator/PROJECT
@@ -83,4 +83,30 @@ resources:
     defaulting: true
     validation: true
     webhookVersion: v1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: skywalking.apache.org
+  group: operator
+  kind: OAPServerConfig
+  path: github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1
+  version: v1alpha1
+  webhooks:
+    defaulting: true
+    validation: true
+    webhookVersion: v1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: skywalking.apache.org
+  group: operator
+  kind: OAPServerDynamicConfig
+  path: github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1
+  version: v1alpha1
+  webhooks:
+    defaulting: true
+    validation: true
+    webhookVersion: v1
 version: "3"
diff --git a/operator/apis/operator/v1alpha1/oapserverconfig_types.go b/operator/apis/operator/v1alpha1/oapserverconfig_types.go
new file mode 100644
index 0000000..f9e8d0f
--- /dev/null
+++ b/operator/apis/operator/v1alpha1/oapserverconfig_types.go
@@ -0,0 +1,88 @@
+// 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.
+
+package v1alpha1
+
+import (
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// FileConfig contains the static file configuration's name, path and data
+// Static files refer to all files in the oap-server's configuration directory
+// (/skywalking/config)
+type FileConfig struct {
+	// Name of static file
+	Name string `json:"name,omitempty"`
+	// Path of static file
+	Path string `json:"path,omitempty"`
+	// Data of static file
+	Data string `json:"data,omitempty"`
+}
+
+// OAPServerConfigSpec defines the desired state of OAPServerConfig
+type OAPServerConfigSpec struct {
+	// Version of OAP.
+	//+kubebuilder:validation:Required
+	Version string `json:"version,omitempty"`
+	// Env holds the OAP server environment configuration.
+	// +kubebuilder:validation:Optional
+	Env []corev1.EnvVar `json:"env,omitempty"`
+	// File holds the OAP server's static file configuration
+	// +kubebuilder:validation:Optional
+	File []FileConfig `json:"file,omitempty"`
+}
+
+// OAPServerConfigStatus defines the observed state of OAPServerConfig
+type OAPServerConfigStatus struct {
+	// The number of oapserver that need to be configured
+	Desired int `json:"desired,omitempty"`
+	// The number of oapserver that configured successfully
+	Ready int `json:"ready,omitempty"`
+	// The time the OAPServerConfig was created.
+	CreationTime metav1.Time `json:"creationTime,omitempty"`
+	// The last time this condition was updated.
+	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:printcolumn:name="Version",type="string",priority=1,JSONPath=".spec.version",description="The version"
+// +kubebuilder:printcolumn:name="Instances",type="string",JSONPath=".status.desired",description="The number of expected instance"
+// +kubebuilder:printcolumn:name="Running",type="string",JSONPath=".status.ready",description="The number of running"
+
+// OAPServerConfig is the Schema for the oapserverconfigs API
+type OAPServerConfig struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   OAPServerConfigSpec   `json:"spec,omitempty"`
+	Status OAPServerConfigStatus `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// OAPServerConfigList contains a list of OAPServerConfig
+type OAPServerConfigList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []OAPServerConfig `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&OAPServerConfig{}, &OAPServerConfigList{})
+}
diff --git a/operator/apis/operator/v1alpha1/oapserverconfig_webhook.go b/operator/apis/operator/v1alpha1/oapserverconfig_webhook.go
new file mode 100644
index 0000000..9d77455
--- /dev/null
+++ b/operator/apis/operator/v1alpha1/oapserverconfig_webhook.go
@@ -0,0 +1,81 @@
+// 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.
+
+package v1alpha1
+
+import (
+	"fmt"
+
+	"k8s.io/apimachinery/pkg/runtime"
+	ctrl "sigs.k8s.io/controller-runtime"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
+	"sigs.k8s.io/controller-runtime/pkg/webhook"
+)
+
+// log is for logging in this package.
+var oapserverconfiglog = logf.Log.WithName("oapserverconfig-resource")
+
+func (r *OAPServerConfig) SetupWebhookWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewWebhookManagedBy(mgr).
+		For(r).
+		Complete()
+}
+
+// nolint: lll
+//+kubebuilder:webhook:path=/mutate-operator-skywalking-apache-org-v1alpha1-oapserverconfig,mutating=true,failurePolicy=fail,sideEffects=None,groups=operator.skywalking.apache.org,resources=oapserverconfigs,verbs=create;update,versions=v1alpha1,name=moapserverconfig.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Defaulter = &OAPServerConfig{}
+
+// Default implements webhook.Defaulter so a webhook will be registered for the type
+func (r *OAPServerConfig) Default() {
+	oapserverconfiglog.Info("default", "name", r.Name)
+
+	// Default version is "9.1.0"
+	if r.Spec.Version == "" {
+		r.Spec.Version = "9.1.0"
+	}
+}
+
+// nolint: lll
+//+kubebuilder:webhook:path=/validate-operator-skywalking-apache-org-v1alpha1-oapserverconfig,mutating=false,failurePolicy=fail,sideEffects=None,groups=operator.skywalking.apache.org,resources=oapserverconfigs,verbs=create;update,versions=v1alpha1,name=voapserverconfig.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Validator = &OAPServerConfig{}
+
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
+func (r *OAPServerConfig) ValidateCreate() error {
+	oapserverconfiglog.Info("validate create", "name", r.Name)
+	return r.validate()
+}
+
+// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
+func (r *OAPServerConfig) ValidateUpdate(old runtime.Object) error {
+	oapserverconfiglog.Info("validate update", "name", r.Name)
+	return r.validate()
+}
+
+// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
+func (r *OAPServerConfig) ValidateDelete() error {
+	oapserverconfiglog.Info("validate delete", "name", r.Name)
+	return nil
+}
+
+func (r *OAPServerConfig) validate() error {
+	if r.Spec.Version == "" {
+		return fmt.Errorf("OAPServerconfig's version is absent")
+	}
+	return nil
+}
diff --git a/operator/apis/operator/v1alpha1/oapserverdynamicconfig_types.go b/operator/apis/operator/v1alpha1/oapserverdynamicconfig_types.go
new file mode 100644
index 0000000..1409eb8
--- /dev/null
+++ b/operator/apis/operator/v1alpha1/oapserverdynamicconfig_types.go
@@ -0,0 +1,80 @@
+// 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.
+
+package v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// Config contains the dynamic configuration's key and value
+type Config struct {
+	// configuration's key
+	Name string `json:"name,omitempty"`
+	// configuration's value
+	Value string `json:"value,omitempty"`
+}
+
+// OAPServerDynamicConfigSpec defines the desired state of OAPServerDynamicConfig
+type OAPServerDynamicConfigSpec struct {
+	// Version of OAP.
+	//+kubebuilder:validation:Required
+	Version string `json:"version,omitempty"`
+	// Locate specific configmap
+	// +kubebuilder:validation:Optional
+	LabelSelector string `json:"labelSelector,omitempty"`
+	// All configurations' key and value
+	// +kubebuilder:validation:Optional
+	Data []Config `json:"data,omitempty"`
+}
+
+// OAPServerDynamicConfigStatus defines the observed state of OAPServerDynamicConfig
+type OAPServerDynamicConfigStatus struct {
+	// The state of dynamic configuration
+	State string `json:"state,omitempty"`
+	// The time the OAPServerDynamicConfig was created.
+	CreationTime metav1.Time `json:"creationTime,omitempty"`
+	// The last time this condition was updated.
+	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:printcolumn:name="Version",type="string",priority=1,JSONPath=".spec.version",description="The version"
+// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.state",description="The state of dynamic configuration"
+
+// OAPServerDynamicConfig is the Schema for the oapserverdynamicconfigs API
+type OAPServerDynamicConfig struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   OAPServerDynamicConfigSpec   `json:"spec,omitempty"`
+	Status OAPServerDynamicConfigStatus `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// OAPServerDynamicConfigList contains a list of OAPServerDynamicConfig
+type OAPServerDynamicConfigList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []OAPServerDynamicConfig `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&OAPServerDynamicConfig{}, &OAPServerDynamicConfigList{})
+}
diff --git a/operator/apis/operator/v1alpha1/oapserverdynamicconfig_webhook.go b/operator/apis/operator/v1alpha1/oapserverdynamicconfig_webhook.go
new file mode 100644
index 0000000..9549590
--- /dev/null
+++ b/operator/apis/operator/v1alpha1/oapserverdynamicconfig_webhook.go
@@ -0,0 +1,88 @@
+// 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.
+
+package v1alpha1
+
+import (
+	"fmt"
+
+	"k8s.io/apimachinery/pkg/runtime"
+	ctrl "sigs.k8s.io/controller-runtime"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
+	"sigs.k8s.io/controller-runtime/pkg/webhook"
+)
+
+// log is for logging in this package.
+var oapserverdynamicconfiglog = logf.Log.WithName("oapserverdynamicconfig-resource")
+
+func (r *OAPServerDynamicConfig) SetupWebhookWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewWebhookManagedBy(mgr).
+		For(r).
+		Complete()
+}
+
+// nolint: lll
+//+kubebuilder:webhook:path=/mutate-operator-skywalking-apache-org-v1alpha1-oapserverdynamicconfig,mutating=true,failurePolicy=fail,sideEffects=None,groups=operator.skywalking.apache.org,resources=oapserverdynamicconfigs,verbs=create;update,versions=v1alpha1,name=moapserverdynamicconfig.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Defaulter = &OAPServerDynamicConfig{}
+
+// Default implements webhook.Defaulter so a webhook will be registered for the type
+func (r *OAPServerDynamicConfig) Default() {
+	oapserverdynamicconfiglog.Info("default", "name", r.Name)
+
+	// Default version is "9.1.0"
+	if r.Spec.Version == "" {
+		r.Spec.Version = "9.1.0"
+	}
+
+	// Default labelselector is "app=collector,release=skywalking"
+	if r.Spec.LabelSelector == "" {
+		r.Spec.LabelSelector = "app=collector,release=skywalking"
+	}
+}
+
+// nolint: lll
+//+kubebuilder:webhook:path=/validate-operator-skywalking-apache-org-v1alpha1-oapserverdynamicconfig,mutating=false,failurePolicy=fail,sideEffects=None,groups=operator.skywalking.apache.org,resources=oapserverdynamicconfigs,verbs=create;update,versions=v1alpha1,name=voapserverdynamicconfig.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Validator = &OAPServerDynamicConfig{}
+
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
+func (r *OAPServerDynamicConfig) ValidateCreate() error {
+	oapserverdynamicconfiglog.Info("validate create", "name", r.Name)
+	return r.validate()
+}
+
+// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
+func (r *OAPServerDynamicConfig) ValidateUpdate(old runtime.Object) error {
+	oapserverdynamicconfiglog.Info("validate update", "name", r.Name)
+	return r.validate()
+}
+
+// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
+func (r *OAPServerDynamicConfig) ValidateDelete() error {
+	oapserverdynamicconfiglog.Info("validate delete", "name", r.Name)
+	return nil
+}
+
+func (r *OAPServerDynamicConfig) validate() error {
+	if r.Spec.Version == "" {
+		return fmt.Errorf("OAPServerDynamicConfig's version is absent")
+	} else if r.Spec.LabelSelector == "" {
+		return fmt.Errorf("OAPServerDynamicConfig's labelselector is absent")
+	}
+	return nil
+}
diff --git a/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go b/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go
index 6b82d1d..5dd8aa5 100644
--- a/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -29,6 +29,21 @@ import (
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Config) DeepCopyInto(out *Config) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config.
+func (in *Config) DeepCopy() *Config {
+	if in == nil {
+		return nil
+	}
+	out := new(Config)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Fetcher) DeepCopyInto(out *Fetcher) {
 	*out = *in
@@ -147,6 +162,21 @@ func (in *FetcherStatus) DeepCopy() *FetcherStatus {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *FileConfig) DeepCopyInto(out *FileConfig) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileConfig.
+func (in *FileConfig) DeepCopy() *FileConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(FileConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Ingress) DeepCopyInto(out *Ingress) {
 	*out = *in
@@ -306,6 +336,205 @@ func (in *OAPServer) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerConfig) DeepCopyInto(out *OAPServerConfig) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerConfig.
+func (in *OAPServerConfig) DeepCopy() *OAPServerConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OAPServerConfig) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerConfigList) DeepCopyInto(out *OAPServerConfigList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]OAPServerConfig, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerConfigList.
+func (in *OAPServerConfigList) DeepCopy() *OAPServerConfigList {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerConfigList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OAPServerConfigList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerConfigSpec) DeepCopyInto(out *OAPServerConfigSpec) {
+	*out = *in
+	if in.Env != nil {
+		in, out := &in.Env, &out.Env
+		*out = make([]corev1.EnvVar, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.File != nil {
+		in, out := &in.File, &out.File
+		*out = make([]FileConfig, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerConfigSpec.
+func (in *OAPServerConfigSpec) DeepCopy() *OAPServerConfigSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerConfigSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerConfigStatus) DeepCopyInto(out *OAPServerConfigStatus) {
+	*out = *in
+	in.CreationTime.DeepCopyInto(&out.CreationTime)
+	in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerConfigStatus.
+func (in *OAPServerConfigStatus) DeepCopy() *OAPServerConfigStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerConfigStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerDynamicConfig) DeepCopyInto(out *OAPServerDynamicConfig) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerDynamicConfig.
+func (in *OAPServerDynamicConfig) DeepCopy() *OAPServerDynamicConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerDynamicConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OAPServerDynamicConfig) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerDynamicConfigList) DeepCopyInto(out *OAPServerDynamicConfigList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]OAPServerDynamicConfig, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerDynamicConfigList.
+func (in *OAPServerDynamicConfigList) DeepCopy() *OAPServerDynamicConfigList {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerDynamicConfigList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OAPServerDynamicConfigList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerDynamicConfigSpec) DeepCopyInto(out *OAPServerDynamicConfigSpec) {
+	*out = *in
+	if in.Data != nil {
+		in, out := &in.Data, &out.Data
+		*out = make([]Config, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerDynamicConfigSpec.
+func (in *OAPServerDynamicConfigSpec) DeepCopy() *OAPServerDynamicConfigSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerDynamicConfigSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OAPServerDynamicConfigStatus) DeepCopyInto(out *OAPServerDynamicConfigStatus) {
+	*out = *in
+	in.CreationTime.DeepCopyInto(&out.CreationTime)
+	in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAPServerDynamicConfigStatus.
+func (in *OAPServerDynamicConfigStatus) DeepCopy() *OAPServerDynamicConfigStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(OAPServerDynamicConfigStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *OAPServerList) DeepCopyInto(out *OAPServerList) {
 	*out = *in
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_fetchers.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_fetchers.yaml
index beebdf9..596e7d5 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_fetchers.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_fetchers.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml
index 848f70b..8cab91a 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_oapserverconfigs.yaml
similarity index 72%
copy from operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml
copy to operator/config/crd/bases/operator.skywalking.apache.org_oapserverconfigs.yaml
index fcf89ab..a16f87f 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_oapserverconfigs.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
@@ -22,37 +22,34 @@ metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.7.0
   creationTimestamp: null
-  name: storages.operator.skywalking.apache.org
+  name: oapserverconfigs.operator.skywalking.apache.org
 spec:
   group: operator.skywalking.apache.org
   names:
-    kind: Storage
-    listKind: StorageList
-    plural: storages
-    singular: storage
+    kind: OAPServerConfig
+    listKind: OAPServerConfigList
+    plural: oapserverconfigs
+    singular: oapserverconfig
   scope: Namespaced
   versions:
   - additionalPrinterColumns:
-    - description: The number of expected instance
-      jsonPath: .spec.instances
-      name: Instances
-      type: string
-    - description: The type of storage
-      jsonPath: .spec.type
-      name: Type
-      type: string
     - description: The version
       jsonPath: .spec.version
       name: Version
+      priority: 1
+      type: string
+    - description: The number of expected instance
+      jsonPath: .status.desired
+      name: Instances
       type: string
-    - description: the way to connect storage
-      jsonPath: .spec.connectType
-      name: ConnectType
+    - description: The number of running
+      jsonPath: .status.ready
+      name: Running
       type: string
     name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: Storage is the Schema for the storages API
+        description: OAPServerConfig is the Schema for the oapserverconfigs API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -67,13 +64,10 @@ spec:
           metadata:
             type: object
           spec:
-            description: StorageSpec defines the desired state of Storage
+            description: OAPServerConfigSpec defines the desired state of OAPServerConfig
             properties:
-              address:
-                description: Address of external storage address.
-                type: string
-              config:
-                description: Config holds the Storage configuration.
+              env:
+                description: Env holds the OAP server environment configuration.
                 items:
                   description: EnvVar represents an environment variable present in
                     a Container.
@@ -177,81 +171,45 @@ spec:
                   - name
                   type: object
                 type: array
-              connectType:
-                description: ConnectType is the way to connect storage(e.g. external,internal).
-                type: string
-              image:
-                description: Image is the storage Docker image to deploy.
-                type: string
-              instances:
-                description: Instance is the number of storage.
-                format: int32
-                type: integer
-              resource:
-                description: ResourceCnfig relevant settings
-                properties:
-                  limit:
-                    type: string
-                  requests:
-                    type: string
-                type: object
-              security:
-                description: Security relevant settings
-                properties:
-                  tls:
-                    description: SSLConfig of  storage .
-                    type: boolean
-                  user:
-                    description: UserConfig of storage .
-                    properties:
-                      secretName:
-                        description: SecretName of storage user .
-                        type: string
-                    type: object
-                type: object
-              servicename:
-                description: ServiceName relevant settings
-                type: string
-              type:
-                description: Type of storage.
-                type: string
-              version:
-                description: Version of storage.
-                type: string
-            type: object
-          status:
-            description: StorageStatus defines the observed state of Storage
-            properties:
-              conditions:
-                description: Represents the latest available observations of the underlying
-                  statefulset's current state.
+              file:
+                description: File holds the OAP server's static file configuration
                 items:
-                  description: StatefulSetCondition describes the state of a statefulset
-                    at a certain point.
+                  description: FileConfig contains the static file configuration's
+                    name, path and data Static files refer to all files in the oap-server's
+                    configuration directory (/skywalking/config)
                   properties:
-                    lastTransitionTime:
-                      description: Last time the condition transitioned from one status
-                        to another.
-                      format: date-time
-                      type: string
-                    message:
-                      description: A human readable message indicating details about
-                        the transition.
+                    data:
+                      description: Data of static file
                       type: string
-                    reason:
-                      description: The reason for the condition's last transition.
-                      type: string
-                    status:
-                      description: Status of the condition, one of True, False, Unknown.
+                    name:
+                      description: Name of static file
                       type: string
-                    type:
-                      description: Type of statefulset condition.
+                    path:
+                      description: Path of static file
                       type: string
-                  required:
-                  - status
-                  - type
                   type: object
                 type: array
+              version:
+                description: Version of OAP.
+                type: string
+            type: object
+          status:
+            description: OAPServerConfigStatus defines the observed state of OAPServerConfig
+            properties:
+              creationTime:
+                description: The time the OAPServerConfig was created.
+                format: date-time
+                type: string
+              desired:
+                description: The number of oapserver that need to be configured
+                type: integer
+              lastUpdateTime:
+                description: The last time this condition was updated.
+                format: date-time
+                type: string
+              ready:
+                description: The number of oapserver that configured successfully
+                type: integer
             type: object
         type: object
     served: true
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_oapserverdynamicconfigs.yaml
similarity index 60%
copy from operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml
copy to operator/config/crd/bases/operator.skywalking.apache.org_oapserverdynamicconfigs.yaml
index 848f70b..ed3d4ae 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_javaagents.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_oapserverdynamicconfigs.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
@@ -22,33 +22,31 @@ metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.7.0
   creationTimestamp: null
-  name: javaagents.operator.skywalking.apache.org
+  name: oapserverdynamicconfigs.operator.skywalking.apache.org
 spec:
   group: operator.skywalking.apache.org
   names:
-    kind: JavaAgent
-    listKind: JavaAgentList
-    plural: javaagents
-    singular: javaagent
+    kind: OAPServerDynamicConfig
+    listKind: OAPServerDynamicConfigList
+    plural: oapserverdynamicconfigs
+    singular: oapserverdynamicconfig
   scope: Namespaced
   versions:
   - additionalPrinterColumns:
-    - description: The selector label of injected Pod
-      jsonPath: .spec.podSelector
-      name: PodSelector
-      type: string
-    - description: The name of service in the injected agent
-      jsonPath: .spec.serviceName
-      name: ServiceName
+    - description: The version
+      jsonPath: .spec.version
+      name: Version
+      priority: 1
       type: string
-    - description: The backend service in the injected agent
-      jsonPath: .spec.backendService
-      name: BackendService
+    - description: The state of dynamic configuration
+      jsonPath: .status.state
+      name: State
       type: string
     name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: JavaAgent is the Schema for the javaagents API
+        description: OAPServerDynamicConfig is the Schema for the oapserverdynamicconfigs
+          API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -63,42 +61,44 @@ spec:
           metadata:
             type: object
           spec:
-            description: JavaAgentSpec defines the desired state of JavaAgent
+            description: OAPServerDynamicConfigSpec defines the desired state of OAPServerDynamicConfig
             properties:
-              agentConfiguration:
-                additionalProperties:
-                  type: string
-                description: AgentConfiguration is the injected agent's final configuration
-                type: object
-              backendService:
-                description: BackendService is the backend service in the injected
-                  agent, which need to be printed
+              data:
+                description: All configurations' key and value
+                items:
+                  description: Config contains the dynamic configuration's key and
+                    value
+                  properties:
+                    name:
+                      description: configuration's key
+                      type: string
+                    value:
+                      description: configuration's value
+                      type: string
+                  type: object
+                type: array
+              labelSelector:
+                description: Locate specific configmap
                 type: string
-              podSelector:
-                description: PodSelector is the selector label of injected Pod
-                type: string
-              serviceName:
-                description: ServiceName is the name of service in the injected agent,
-                  which need to be printed
+              version:
+                description: Version of OAP.
                 type: string
             type: object
           status:
-            description: JavaAgentStatus defines the observed state of JavaAgent
+            description: OAPServerDynamicConfigStatus defines the observed state of
+              OAPServerDynamicConfig
             properties:
               creationTime:
-                description: The time the JavaAgent was created.
+                description: The time the OAPServerDynamicConfig was created.
                 format: date-time
                 type: string
-              expectedInjectiedNum:
-                description: The number of pods that need to be injected
-                type: integer
               lastUpdateTime:
                 description: The last time this condition was updated.
                 format: date-time
                 type: string
-              realInjectedNum:
-                description: The number of pods that injected successfully
-                type: integer
+              state:
+                description: The state of dynamic configuration
+                type: string
             type: object
         type: object
     served: true
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml
index a03720f..4d4670e 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_satellites.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_satellites.yaml
index 1483b6e..a1e6318 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_satellites.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_satellites.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml
index fcf89ab..a9caa6c 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_storages.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_uis.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_uis.yaml
index d9af6db..ed4a3b8 100644
--- a/operator/config/crd/bases/operator.skywalking.apache.org_uis.yaml
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_uis.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
diff --git a/operator/config/crd/kustomization.yaml b/operator/config/crd/kustomization.yaml
index 1451512..aac1aa2 100644
--- a/operator/config/crd/kustomization.yaml
+++ b/operator/config/crd/kustomization.yaml
@@ -25,6 +25,8 @@ resources:
 - bases/operator.skywalking.apache.org_storages.yaml
 - bases/operator.skywalking.apache.org_javaagents.yaml
 - bases/operator.skywalking.apache.org_satellites.yaml
+- bases/operator.skywalking.apache.org_oapserverconfigs.yaml
+- bases/operator.skywalking.apache.org_oapserverdynamicconfigs.yaml
 #+kubebuilder:scaffold:crdkustomizeresource
 
 patchesStrategicMerge:
@@ -36,6 +38,8 @@ patchesStrategicMerge:
 - patches/webhook_in_storages.yaml
 - patches/webhook_in_javaagents.yaml
 - patches/webhook_in_satellites.yaml
+- patches/webhook_in_oapserverconfigs.yaml
+#- patches/webhook_in_oapserverdynamicconfigs.yaml
 #+kubebuilder:scaffold:crdkustomizewebhookpatch
 
 # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
@@ -46,6 +50,8 @@ patchesStrategicMerge:
 - patches/cainjection_in_storages.yaml
 - patches/cainjection_in_javaagents.yaml
 - patches/cainjection_in_satellites.yaml
+- patches/cainjection_in_oapserverconfigs.yaml
+#- patches/cainjection_in_oapserverdynamicconfigs.yaml
 #+kubebuilder:scaffold:crdkustomizecainjectionpatch
 
 # the following config is for teaching kustomize how to do kustomization for CRDs.
diff --git a/operator/config/samples/minimal.yaml b/operator/config/crd/patches/cainjection_in_oapserverconfigs.yaml
similarity index 72%
copy from operator/config/samples/minimal.yaml
copy to operator/config/crd/patches/cainjection_in_oapserverconfigs.yaml
index 8f41ea7..40c8aab 100644
--- a/operator/config/samples/minimal.yaml
+++ b/operator/config/crd/patches/cainjection_in_oapserverconfigs.yaml
@@ -14,21 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: OAPServer
-metadata:
-  name: minimal
-spec:
-  version: 8.8.1
-  instances: 1
-  
----
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: UI 
+#
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
 metadata:
-  name: minimal
-spec:
-  version: 8.8.1
-  instances: 1
- 
\ No newline at end of file
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: oapserverconfigs.operator.skywalking.apache.org
diff --git a/operator/config/samples/minimal.yaml b/operator/config/crd/patches/cainjection_in_oapserverdynamicconfigs.yaml
similarity index 72%
copy from operator/config/samples/minimal.yaml
copy to operator/config/crd/patches/cainjection_in_oapserverdynamicconfigs.yaml
index 8f41ea7..ec098ec 100644
--- a/operator/config/samples/minimal.yaml
+++ b/operator/config/crd/patches/cainjection_in_oapserverdynamicconfigs.yaml
@@ -14,21 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: OAPServer
-metadata:
-  name: minimal
-spec:
-  version: 8.8.1
-  instances: 1
-  
----
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: UI 
+#
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
 metadata:
-  name: minimal
-spec:
-  version: 8.8.1
-  instances: 1
- 
\ No newline at end of file
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: oapserverdynamicconfigs.operator.skywalking.apache.org
diff --git a/operator/config/samples/minimal.yaml b/operator/config/crd/patches/webhook_in_oapserverconfigs.yaml
similarity index 67%
copy from operator/config/samples/minimal.yaml
copy to operator/config/crd/patches/webhook_in_oapserverconfigs.yaml
index 8f41ea7..e9d4f03 100644
--- a/operator/config/samples/minimal.yaml
+++ b/operator/config/crd/patches/webhook_in_oapserverconfigs.yaml
@@ -14,21 +14,20 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: OAPServer
-metadata:
-  name: minimal
-spec:
-  version: 8.8.1
-  instances: 1
-  
----
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: UI 
+#
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
 metadata:
-  name: minimal
+  name: oapserverconfigs.operator.skywalking.apache.org
 spec:
-  version: 8.8.1
-  instances: 1
- 
\ No newline at end of file
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
+      conversionReviewVersions:
+      - v1
diff --git a/operator/config/samples/minimal.yaml b/operator/config/crd/patches/webhook_in_oapserverdynamicconfigs.yaml
similarity index 66%
copy from operator/config/samples/minimal.yaml
copy to operator/config/crd/patches/webhook_in_oapserverdynamicconfigs.yaml
index 8f41ea7..184fc8d 100644
--- a/operator/config/samples/minimal.yaml
+++ b/operator/config/crd/patches/webhook_in_oapserverdynamicconfigs.yaml
@@ -14,21 +14,20 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: OAPServer
-metadata:
-  name: minimal
-spec:
-  version: 8.8.1
-  instances: 1
-  
----
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: UI 
+#
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
 metadata:
-  name: minimal
+  name: oapserverdynamicconfigs.operator.skywalking.apache.org
 spec:
-  version: 8.8.1
-  instances: 1
- 
\ No newline at end of file
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
+      conversionReviewVersions:
+      - v1
diff --git a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml b/operator/config/rbac/oapserverconfig_editor_role.yaml
similarity index 70%
copy from operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
copy to operator/config/rbac/oapserverconfig_editor_role.yaml
index 368682d..861c8ac 100644
--- a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
+++ b/operator/config/rbac/oapserverconfig_editor_role.yaml
@@ -14,18 +14,28 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-kind: ClusterRole
+#
+# permissions for end users to edit oapserverconfigs.
 apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
 metadata:
-  name: swck:oapserver
-  labels:
-    operator.skywalking.apache.org/application: oapserver
-    operator.skywalking.apache.org/component: rbac
+  name: oapserverconfig-editor-role
 rules:
-  - apiGroups: [""]
-    resources: ["pods", "endpoints", "services"]
-    verbs: ["get", "watch", "list"]
-  - apiGroups: ["extensions"]
-    resources: ["deployments", "replicasets"]
-    verbs: ["get", "watch", "list"]
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverconfigs
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverconfigs/status
+  verbs:
+  - get
diff --git a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml b/operator/config/rbac/oapserverconfig_viewer_role.yaml
similarity index 70%
copy from operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
copy to operator/config/rbac/oapserverconfig_viewer_role.yaml
index 368682d..a10e679 100644
--- a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
+++ b/operator/config/rbac/oapserverconfig_viewer_role.yaml
@@ -14,18 +14,24 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-kind: ClusterRole
+#
+# permissions for end users to view oapserverconfigs.
 apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
 metadata:
-  name: swck:oapserver
-  labels:
-    operator.skywalking.apache.org/application: oapserver
-    operator.skywalking.apache.org/component: rbac
+  name: oapserverconfig-viewer-role
 rules:
-  - apiGroups: [""]
-    resources: ["pods", "endpoints", "services"]
-    verbs: ["get", "watch", "list"]
-  - apiGroups: ["extensions"]
-    resources: ["deployments", "replicasets"]
-    verbs: ["get", "watch", "list"]
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverconfigs
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverconfigs/status
+  verbs:
+  - get
diff --git a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml b/operator/config/rbac/oapserverdynamicconfig_editor_role.yaml
similarity index 69%
copy from operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
copy to operator/config/rbac/oapserverdynamicconfig_editor_role.yaml
index 368682d..ff4aca7 100644
--- a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
+++ b/operator/config/rbac/oapserverdynamicconfig_editor_role.yaml
@@ -14,18 +14,28 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-kind: ClusterRole
+#
+# permissions for end users to edit oapserverdynamicconfigs.
 apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
 metadata:
-  name: swck:oapserver
-  labels:
-    operator.skywalking.apache.org/application: oapserver
-    operator.skywalking.apache.org/component: rbac
+  name: oapserverdynamicconfig-editor-role
 rules:
-  - apiGroups: [""]
-    resources: ["pods", "endpoints", "services"]
-    verbs: ["get", "watch", "list"]
-  - apiGroups: ["extensions"]
-    resources: ["deployments", "replicasets"]
-    verbs: ["get", "watch", "list"]
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverdynamicconfigs
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverdynamicconfigs/status
+  verbs:
+  - get
diff --git a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml b/operator/config/rbac/oapserverdynamicconfig_viewer_role.yaml
similarity index 70%
copy from operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
copy to operator/config/rbac/oapserverdynamicconfig_viewer_role.yaml
index 368682d..0bcdd1b 100644
--- a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
+++ b/operator/config/rbac/oapserverdynamicconfig_viewer_role.yaml
@@ -14,18 +14,24 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-kind: ClusterRole
+#
+# permissions for end users to view oapserverdynamicconfigs.
 apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
 metadata:
-  name: swck:oapserver
-  labels:
-    operator.skywalking.apache.org/application: oapserver
-    operator.skywalking.apache.org/component: rbac
+  name: oapserverdynamicconfig-viewer-role
 rules:
-  - apiGroups: [""]
-    resources: ["pods", "endpoints", "services"]
-    verbs: ["get", "watch", "list"]
-  - apiGroups: ["extensions"]
-    resources: ["deployments", "replicasets"]
-    verbs: ["get", "watch", "list"]
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverdynamicconfigs
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverdynamicconfigs/status
+  verbs:
+  - get
diff --git a/operator/config/rbac/role.yaml b/operator/config/rbac/role.yaml
index bb18d8a..04986d3 100644
--- a/operator/config/rbac/role.yaml
+++ b/operator/config/rbac/role.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
@@ -188,6 +188,46 @@ rules:
   - get
   - patch
   - update
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverconfigs
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverconfigs/status
+  verbs:
+  - get
+  - patch
+  - update
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverdynamicconfigs
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapserverdynamicconfigs/status
+  verbs:
+  - get
+  - patch
+  - update
 - apiGroups:
   - operator.skywalking.apache.org
   resources:
diff --git a/operator/config/samples/default.yaml b/operator/config/samples/default.yaml
index f2f0919..d32fb9f 100644
--- a/operator/config/samples/default.yaml
+++ b/operator/config/samples/default.yaml
@@ -20,9 +20,9 @@ kind: OAPServer
 metadata:
   name: default
 spec:
-  version: 8.8.1
+  version: 9.1.0
   instances: 1
-  image: apache/skywalking-oap-server:8.8.1
+  image: apache/skywalking-oap-server:9.1.0
   service:
     template:
       type: ClusterIP
@@ -33,9 +33,9 @@ kind: UI
 metadata:
   name: default
 spec:
-  version: 8.8.1
+  version: 9.1.0
   instances: 1
-  image: apache/skywalking-ui:8.8.1
+  image: apache/skywalking-ui:9.1.0
   OAPServerAddress: http://default-oap.default:12800
   service:
     template:
diff --git a/operator/config/samples/fetcher.yaml b/operator/config/samples/fetcher.yaml
index 8ba8b77..b7a15e9 100644
--- a/operator/config/samples/fetcher.yaml
+++ b/operator/config/samples/fetcher.yaml
@@ -30,9 +30,9 @@ kind: OAPServer
 metadata:
   name: default
 spec:
-  version: 8.8.1
+  version: 9.1.0
   instances: 1
-  image: apache/skywalking-oap-server:8.8.1
+  image: apache/skywalking-oap-server:9.1.0
   config:
     - name: SW_OTEL_RECEIVER
       value: default
@@ -46,9 +46,9 @@ kind: UI
 metadata:
   name: default
 spec:
-  version: 8.8.1
+  version: 9.1.0
   instances: 1
-  image: apache/skywalking-ui:8.8.1
+  image: apache/skywalking-ui:9.1.0
   OAPServerAddress: default-oap:12800
   service:
     template:
diff --git a/operator/config/samples/minimal.yaml b/operator/config/samples/minimal.yaml
index 8f41ea7..36a48dc 100644
--- a/operator/config/samples/minimal.yaml
+++ b/operator/config/samples/minimal.yaml
@@ -20,7 +20,7 @@ kind: OAPServer
 metadata:
   name: minimal
 spec:
-  version: 8.8.1
+  version: 9.1.0
   instances: 1
   
 ---
@@ -29,6 +29,6 @@ kind: UI
 metadata:
   name: minimal
 spec:
-  version: 8.8.1
+  version: 9.1.0
   instances: 1
  
\ No newline at end of file
diff --git a/operator/config/samples/oapserverconfig.yaml b/operator/config/samples/oapserverconfig.yaml
new file mode 100644
index 0000000..3bb664b
--- /dev/null
+++ b/operator/config/samples/oapserverconfig.yaml
@@ -0,0 +1,95 @@
+# 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: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerConfig
+metadata:
+  name: oapserverconfig-sample
+spec:
+  # The version of OAPServer
+  version: 9.1.0
+  # The labelselector of OAPServer's dynamic configuration 
+  labelSelector: app=collector,release=skywalking
+  # Enable the dynamic configuration before using the OAPServerDynamicConfig
+  enableDynamicConfiguration: true
+  # The static configuration of OAPServer
+  env:
+    - name: SW_CONFIG_CONFIGMAP_PERIOD
+      value: "10"
+  # The dynamic configuration of OAPServer
+  file:
+    - name: gateways.yml
+      path: /skywalking/config
+      data: |-
+        # 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.
+
+        gateways:
+          - name: proxy0
+            instances:
+              - host: 127.0.0.1 # the host/ip of this gateway instance
+                port: 9099 # the port of this gateway instance, defaults to 80
+    - name: log4j2.xml
+      path: /skywalking/config
+      data: |-
+        <?xml version="1.0" encoding="UTF-8"?>
+        <!--
+          ~ 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.
+          ~
+          -->
+
+        <Configuration status="INFO">
+            <Appenders>
+                <Console name="Console" target="SYSTEM_OUT">
+                    <PatternLayout>
+                        <LevelPatternSelector defaultPattern="%d %c %L [%t] %-5p %x - %m%n">
+                            <PatternMatch key="ERROR" pattern="%d %c %L [%t] %-5p %x - [%swversion] %m%n" />
+                        </LevelPatternSelector>
+                    </PatternLayout>
+                </Console>
+            </Appenders>
+            <Loggers>
+                <Root level="INFO">
+                    <AppenderRef ref="Console"/>
+                </Root>
+            </Loggers>
+        </Configuration>
\ No newline at end of file
diff --git a/operator/config/samples/oapserverdynamicconfig.yaml b/operator/config/samples/oapserverdynamicconfig.yaml
new file mode 100644
index 0000000..81ebcd9
--- /dev/null
+++ b/operator/config/samples/oapserverdynamicconfig.yaml
@@ -0,0 +1,114 @@
+# 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: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerDynamicConfig
+metadata:
+  name: oapserverdynamicconfig-sample
+spec:
+  # The version of OAPServer
+  version: 9.1.0
+  # The labelselector of OAPServer's dynamic configuration, it should be the same as labelSelector of OAPServerConfig
+  labelSelector: app=collector,release=skywalking
+  data:
+    - name: agent-analyzer.default.slowDBAccessThreshold
+      value: default:200,mongodb:50
+    - name: alarm.default.alarm-settings
+      value: |-
+        rules:
+          # Rule unique name, must be ended with `_rule`.
+          service_resp_time_rule:
+            metrics-name: service_resp_time
+            op: ">"
+            threshold: 1000
+            period: 10
+            count: 3
+            silence-period: 5
+            message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
+          service_sla_rule:
+            # Metrics value need to be long, double or int
+            metrics-name: service_sla
+            op: "<"
+            threshold: 8000
+            # The length of time to evaluate the metrics
+            period: 10
+            # How many times after the metrics match the condition, will trigger alarm
+            count: 2
+            # How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
+            silence-period: 3
+            message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
+          service_resp_time_percentile_rule:
+            # Metrics value need to be long, double or int
+            metrics-name: service_percentile
+            op: ">"
+            threshold: 1000,1000,1000,1000,1000
+            period: 10
+            count: 3
+            silence-period: 5
+            message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
+          service_instance_resp_time_rule:
+            metrics-name: service_instance_resp_time
+            op: ">"
+            threshold: 1000
+            period: 10
+            count: 2
+            silence-period: 5
+            message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
+          database_access_resp_time_rule:
+            metrics-name: database_access_resp_time
+            threshold: 1000
+            op: ">"
+            period: 10
+            count: 2
+            message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes
+          endpoint_relation_resp_time_rule:
+            metrics-name: endpoint_relation_resp_time
+            threshold: 1000
+            op: ">"
+            period: 10
+            count: 2
+            message: Response time of endpoint relation {name} is more than 1000ms in 2 minutes of last 10 minutes
+        #  Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
+        #  Because the number of endpoint is much more than service and instance.
+        #
+        #  endpoint_resp_time_rule:
+        #    metrics-name: endpoint_resp_time
+        #    op: ">"
+        #    threshold: 1000
+        #    period: 10
+        #    count: 2
+        #    silence-period: 5
+        #    message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
+
+        webhooks:
+        #  - http://127.0.0.1/notify/
+        #  - http://127.0.0.1/go-wechat/
+    - name: core.default.apdexThreshold
+      value: |-
+        default: 500
+        # example:
+        # the threshold of service "tomcat" is 1s
+        # tomcat: 1000
+        # the threshold of service "springboot1" is 50ms
+        # springboot1: 50
+    - name: agent-analyzer.default.uninstrumentedGateways
+      value: |-
+        #gateways:
+        #  - name: proxy0
+        #    instances:
+        #      - host: 127.0.0.1 # the host/ip of this gateway instance
+        #        port: 9099 # the port of this gateway instance, defaults to 80
diff --git a/operator/config/webhook/manifests.yaml b/operator/config/webhook/manifests.yaml
index 1d301d3..945d86d 100644
--- a/operator/config/webhook/manifests.yaml
+++ b/operator/config/webhook/manifests.yaml
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
 ---
 apiVersion: admissionregistration.k8s.io/v1
 kind: MutatingWebhookConfiguration
@@ -102,6 +102,46 @@ webhooks:
     resources:
     - oapservers
   sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-operator-skywalking-apache-org-v1alpha1-oapserverconfig
+  failurePolicy: Fail
+  name: moapserverconfig.kb.io
+  rules:
+  - apiGroups:
+    - operator.skywalking.apache.org
+    apiVersions:
+    - v1alpha1
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - oapserverconfigs
+  sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-operator-skywalking-apache-org-v1alpha1-oapserverdynamicconfig
+  failurePolicy: Fail
+  name: moapserverdynamicconfig.kb.io
+  rules:
+  - apiGroups:
+    - operator.skywalking.apache.org
+    apiVersions:
+    - v1alpha1
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - oapserverdynamicconfigs
+  sideEffects: None
 - admissionReviewVersions:
   - v1
   clientConfig:
@@ -230,6 +270,46 @@ webhooks:
     resources:
     - oapservers
   sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /validate-operator-skywalking-apache-org-v1alpha1-oapserverconfig
+  failurePolicy: Fail
+  name: voapserverconfig.kb.io
+  rules:
+  - apiGroups:
+    - operator.skywalking.apache.org
+    apiVersions:
+    - v1alpha1
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - oapserverconfigs
+  sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /validate-operator-skywalking-apache-org-v1alpha1-oapserverdynamicconfig
+  failurePolicy: Fail
+  name: voapserverdynamicconfig.kb.io
+  rules:
+  - apiGroups:
+    - operator.skywalking.apache.org
+    apiVersions:
+    - v1alpha1
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - oapserverdynamicconfigs
+  sideEffects: None
 - admissionReviewVersions:
   - v1
   clientConfig:
diff --git a/operator/controllers/operator/fetcher_controller.go b/operator/controllers/operator/fetcher_controller.go
index cf3424e..3be7718 100644
--- a/operator/controllers/operator/fetcher_controller.go
+++ b/operator/controllers/operator/fetcher_controller.go
@@ -21,11 +21,13 @@ import (
 	"context"
 	"time"
 
+	"github.com/go-logr/logr"
 	apps "k8s.io/api/apps/v1"
 	core "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/tools/record"
+	"k8s.io/client-go/util/retry"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
@@ -67,17 +69,18 @@ func (r *FetcherReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
 		Recorder: r.Recorder,
 	}
 	if err := app.ApplyAll(ctx, ff, log); err != nil {
-		_ = r.updateStatus(ctx, fetcher, core.ConditionFalse, "Failed to apply resources")
+		_ = r.UpdateStatus(ctx, fetcher, core.ConditionFalse, "Failed to apply resources")
 		return ctrl.Result{}, err
 	}
-	if err := r.updateStatus(ctx, fetcher, core.ConditionTrue, "Reconciled all of resources"); err != nil {
+	if err := r.UpdateStatus(ctx, fetcher, core.ConditionTrue, "Reconciled all of resources"); err != nil {
 		return ctrl.Result{}, err
 	}
 	return ctrl.Result{RequeueAfter: schedDuration}, nil
 }
 
-func (r *FetcherReconciler) updateStatus(ctx context.Context, fetcher *operatorv1alpha1.Fetcher, status core.ConditionStatus, msg string) error {
+func (r *FetcherReconciler) UpdateStatus(ctx context.Context, fetcher *operatorv1alpha1.Fetcher, status core.ConditionStatus, msg string) error {
 	log := runtimelog.FromContext(ctx)
+
 	if fetcher.Status.Replicas == 0 {
 		fetcher.Status.Replicas = 1
 	}
@@ -104,13 +107,33 @@ func (r *FetcherReconciler) updateStatus(ctx context.Context, fetcher *operatorv
 	if !changed {
 		return nil
 	}
-	if err := r.Status().Update(ctx, fetcher); err != nil {
+	overlay := fetcher.Status
+	if err := r.updateStatus(ctx, fetcher, overlay, log); err != nil {
 		log.Error(err, "failed to update status")
 		return err
 	}
 	return nil
 }
 
+func (r *FetcherReconciler) updateStatus(ctx context.Context, fetcher *operatorv1alpha1.Fetcher,
+	overlay operatorv1alpha1.FetcherStatus, log logr.Logger) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: fetcher.Name, Namespace: fetcher.Namespace}, fetcher); err != nil {
+			log.Error(err, "failed to get fetcher")
+		}
+		fetcher.Status = overlay
+		fetcher.Kind = "Fetcher"
+		if err := kubernetes.ApplyOverlay(fetcher, &operatorv1alpha1.Fetcher{Status: overlay}); err != nil {
+			log.Error(err, "failed to apply overlay")
+		}
+		if err := r.Status().Update(ctx, fetcher); err != nil {
+			log.Error(err, "failed to update status of fetcher")
+		}
+		return nil
+	})
+}
+
 func (r *FetcherReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
 		For(&operatorv1alpha1.Fetcher{}).
diff --git a/operator/controllers/operator/javaagent_controller.go b/operator/controllers/operator/javaagent_controller.go
index 5235057..ebb8f16 100644
--- a/operator/controllers/operator/javaagent_controller.go
+++ b/operator/controllers/operator/javaagent_controller.go
@@ -29,6 +29,7 @@ import (
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/util/retry"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/event"
@@ -54,7 +55,7 @@ type JavaAgentReconciler struct {
 
 func (r *JavaAgentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 	log := runtimelog.FromContext(ctx)
-	log.Info("=====================javaagent started================================")
+	log.Info("=====================reconcile started================================")
 
 	pod := &core.Pod{}
 	err := r.Client.Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: req.Name}, pod)
@@ -150,7 +151,7 @@ func (r *JavaAgentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
 		return ctrl.Result{}, err
 	}
 
-	if err := r.updateStatus(ctx, log, req.Namespace, selectorname, podselector); err != nil {
+	if err := r.UpdateStatus(ctx, log, req.Namespace, selectorname, podselector); err != nil {
 		log.Error(err, "failed to update javaagent's status")
 		return ctrl.Result{}, err
 	}
@@ -158,7 +159,7 @@ func (r *JavaAgentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
 	return ctrl.Result{}, nil
 }
 
-func (r *JavaAgentReconciler) updateStatus(ctx context.Context, log logr.Logger, namespace, selectorname, podselector string) error {
+func (r *JavaAgentReconciler) UpdateStatus(ctx context.Context, log logr.Logger, namespace, selectorname, podselector string) error {
 	errCol := new(kubernetes.ErrorCollector)
 
 	// get javaagent by selectorname
@@ -213,7 +214,8 @@ func (r *JavaAgentReconciler) updateStatus(ctx context.Context, log logr.Logger,
 		javaagent.Status.LastUpdateTime = now
 	}
 
-	if err := r.Status().Update(ctx, javaagent); err != nil {
+	overlay := javaagent.Status
+	if err := r.updateStatus(ctx, javaagent, overlay, errCol); err != nil {
 		errCol.Collect(fmt.Errorf("failed to update java status: %w", err))
 	}
 
@@ -221,6 +223,25 @@ func (r *JavaAgentReconciler) updateStatus(ctx context.Context, log logr.Logger,
 	return errCol.Error()
 }
 
+func (r *JavaAgentReconciler) updateStatus(ctx context.Context, javaagent *operatorv1alpha1.JavaAgent,
+	overlay operatorv1alpha1.JavaAgentStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: javaagent.Name, Namespace: javaagent.Namespace}, javaagent); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get javaagent: %w", err))
+		}
+		javaagent.Status = overlay
+		javaagent.Kind = "JavaAgent"
+		if err := kubernetes.ApplyOverlay(javaagent, &operatorv1alpha1.JavaAgent{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, javaagent); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status of JavaAgent: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
 func (r *JavaAgentReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
 		For(&core.Pod{}).
diff --git a/operator/controllers/operator/oapserver_controller.go b/operator/controllers/operator/oapserver_controller.go
index c47d8bc..dbe1112 100644
--- a/operator/controllers/operator/oapserver_controller.go
+++ b/operator/controllers/operator/oapserver_controller.go
@@ -31,6 +31,7 @@ import (
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/tools/record"
+	"k8s.io/client-go/util/retry"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
@@ -113,20 +114,35 @@ func (r *OAPServerReconciler) checkState(ctx context.Context, log logr.Logger, o
 	if apiequal.Semantic.DeepDerivative(overlay, oapServer.Status) {
 		log.Info("Status keeps the same as before")
 	}
-	oapServer.Status = overlay
-	oapServer.Kind = "OAPServer"
-	if err := kubernetes.ApplyOverlay(oapServer, &operatorv1alpha1.OAPServer{Status: overlay}); err != nil {
-		errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
-		return errCol.Error()
-	}
-	if err := r.Status().Update(ctx, oapServer); err != nil {
-		errCol.Collect(fmt.Errorf("failed to update status of OAPServer: %w", err))
+
+	if err := r.updateStatus(ctx, oapServer, overlay, errCol); err != nil {
+		errCol.Collect(fmt.Errorf("failed to update status of oapServer: %w", err))
 	}
+
 	log.Info("updated Status sub resource")
 
 	return errCol.Error()
 }
 
+func (r *OAPServerReconciler) updateStatus(ctx context.Context, oapServer *operatorv1alpha1.OAPServer,
+	overlay operatorv1alpha1.OAPServerStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: oapServer.Name, Namespace: oapServer.Namespace}, oapServer); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get oapServer: %w", err))
+		}
+		oapServer.Status = overlay
+		oapServer.Kind = "OAPServer"
+		if err := kubernetes.ApplyOverlay(oapServer, &operatorv1alpha1.OAPServer{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, oapServer); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status of OAPServer: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
 //InjectStorage Inject Storage
 func (r *OAPServerReconciler) InjectStorage(ctx context.Context, log logr.Logger, oapServer *operatorv1alpha1.OAPServer) {
 	if oapServer.Spec.StorageConfig.Name == "" {
diff --git a/operator/controllers/operator/oapserverconfig_controller.go b/operator/controllers/operator/oapserverconfig_controller.go
new file mode 100644
index 0000000..350b288
--- /dev/null
+++ b/operator/controllers/operator/oapserverconfig_controller.go
@@ -0,0 +1,308 @@
+// 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.
+
+package operator
+
+import (
+	"context"
+	"fmt"
+	"sort"
+	"time"
+
+	"github.com/go-logr/logr"
+	apps "k8s.io/api/apps/v1"
+	core "k8s.io/api/core/v1"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/util/retry"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
+
+	operatorv1alpha1 "github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
+	"github.com/apache/skywalking-swck/operator/pkg/kubernetes"
+)
+
+// OAPServerConfigReconciler reconciles a OAPServerConfig object
+type OAPServerConfigReconciler struct {
+	client.Client
+	Scheme *runtime.Scheme
+}
+
+type SortByFileName []operatorv1alpha1.FileConfig
+
+func (a SortByFileName) Len() int {
+	return len(a)
+}
+func (a SortByFileName) Swap(i, j int) {
+	a[i], a[j] = a[j], a[i]
+}
+func (a SortByFileName) Less(i, j int) bool {
+	return a[i].Name < a[j].Name
+}
+
+type SortByEnvName []core.EnvVar
+
+func (a SortByEnvName) Len() int {
+	return len(a)
+}
+func (a SortByEnvName) Swap(i, j int) {
+	a[i], a[j] = a[j], a[i]
+}
+func (a SortByEnvName) Less(i, j int) bool {
+	return a[i].Name < a[j].Name
+}
+
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapserverconfigs,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapserverconfigs/status,verbs=get;update;patch
+// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapservers,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapservers/status,verbs=get;update;patch
+// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
+
+func (r *OAPServerConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+	log := runtimelog.FromContext(ctx)
+	log.Info("=====================reconcile started================================")
+
+	oapServerConfig := operatorv1alpha1.OAPServerConfig{}
+	if err := r.Client.Get(ctx, req.NamespacedName, &oapServerConfig); err != nil {
+		return ctrl.Result{}, client.IgnoreNotFound(err)
+	}
+
+	oapList := operatorv1alpha1.OAPServerList{}
+	opts := []client.ListOption{
+		client.InNamespace(req.Namespace),
+	}
+
+	if err := r.List(ctx, &oapList, opts...); err != nil && !apierrors.IsNotFound(err) {
+		return ctrl.Result{}, fmt.Errorf("failed to list oapserver: %w", err)
+	}
+
+	// get the specific version's oapserver
+	for i := range oapList.Items {
+		if oapList.Items[i].Spec.Version == oapServerConfig.Spec.Version {
+			oapServer := oapList.Items[i]
+			deployment := apps.Deployment{}
+			if err := r.Client.Get(ctx, client.ObjectKey{Namespace: oapServer.Namespace, Name: oapServer.Name + "-oap"}, &deployment); err != nil && !apierrors.IsNotFound(err) {
+				return ctrl.Result{}, fmt.Errorf("failed to get the deployment of OAPServer: %w", err)
+			}
+			// overlay the env configuration
+			envChanged, err := r.OverlayEnv(ctx, log, &oapServer, &oapServerConfig, &deployment)
+			if err != nil {
+				log.Error(err, "failed to overlay the env configuration")
+			}
+			// overlay the file configuration
+			fileChanged, err := r.OverlayStaticFile(ctx, log, &oapServerConfig, &deployment)
+			if err != nil {
+				log.Error(err, "failed to overlay the file configuration")
+			}
+			// update the deployment
+			if envChanged || fileChanged {
+				if err := r.Client.Update(ctx, &deployment); err != nil {
+					return ctrl.Result{}, fmt.Errorf("failed to update the deployment of OAPServer: %w", err)
+				}
+			}
+		}
+	}
+
+	if err := r.checkState(ctx, log, &oapServerConfig, oapList); err != nil {
+		log.Error(err, "failed to update OAPServerConfig's status")
+		return ctrl.Result{}, err
+	}
+
+	return ctrl.Result{RequeueAfter: schedDuration}, nil
+}
+
+func (r *OAPServerConfigReconciler) OverlayEnv(ctx context.Context, log logr.Logger,
+	oapServer *operatorv1alpha1.OAPServer, oapServerConfig *operatorv1alpha1.OAPServerConfig, deployment *apps.Deployment) (bool, error) {
+	changed := false
+
+	sort.Sort(SortByEnvName(oapServerConfig.Spec.Env))
+	newMd5Hash := MD5Hash(oapServerConfig.Spec.Env)
+
+	oldMd5Hash, ok := deployment.Spec.Template.Labels["md5-env"]
+	if !ok || oldMd5Hash != newMd5Hash {
+		changed = true
+	}
+
+	if changed {
+		deployment.Spec.Template.Spec.Containers[0].Env = oapServerConfig.Spec.Env
+		deployment.Spec.Template.Labels["md5-env"] = newMd5Hash
+	} else {
+		log.Info("env configuration keeps the same as before")
+		return changed, nil
+	}
+
+	log.Info("successfully overlay the env configuration")
+	return changed, nil
+}
+
+func (r *OAPServerConfigReconciler) OverlayStaticFile(ctx context.Context, log logr.Logger,
+	oapServerConfig *operatorv1alpha1.OAPServerConfig, deployment *apps.Deployment) (bool, error) {
+	changed := false
+
+	sort.Sort(SortByFileName(oapServerConfig.Spec.File))
+	newMd5Hash := MD5Hash(oapServerConfig.Spec.File)
+	configmap := core.ConfigMap{}
+	err := r.Client.Get(ctx, client.ObjectKey{Namespace: oapServerConfig.Namespace,
+		Name: oapServerConfig.Name}, &configmap)
+	if err != nil && !apierrors.IsNotFound(err) {
+		log.Error(err, "failed to get the static file configuration's configmap")
+		return changed, err
+	}
+	// if the configmap exist and the static configuration changed, then delete it
+	if !apierrors.IsNotFound(err) {
+		oldMd5Hash := configmap.Labels["md5-file"]
+		if oldMd5Hash != newMd5Hash {
+			changed = true
+			if err := r.Client.Delete(ctx, &configmap); err != nil {
+				log.Error(err, "faled to delete the static file configuration's configmap")
+			}
+		} else {
+			log.Info("file configuration keeps the same as before")
+			return changed, nil
+		}
+	}
+
+	data := make(map[string]string)
+	mounts := []core.VolumeMount{}
+	volume := core.Volume{
+		Name: oapServerConfig.Name,
+		VolumeSource: core.VolumeSource{
+			ConfigMap: &core.ConfigMapVolumeSource{
+				LocalObjectReference: core.LocalObjectReference{
+					Name: oapServerConfig.Name,
+				},
+			},
+		},
+	}
+	for _, f := range oapServerConfig.Spec.File {
+		mounts = append(mounts, core.VolumeMount{
+			MountPath: f.Path + "/" + f.Name,
+			Name:      oapServerConfig.Name,
+			SubPath:   f.Name,
+		})
+		data[f.Name] = f.Data
+	}
+
+	labels := make(map[string]string)
+	// set the version label
+	labels["version"] = oapServerConfig.Spec.Version
+	// set the configuration type
+	labels["oapServerConfig"] = "static"
+	// set the md5 value of the data
+	labels["md5-file"] = newMd5Hash
+	// create configmap for static files
+	configmap = core.ConfigMap{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      oapServerConfig.Name,
+			Namespace: oapServerConfig.Namespace,
+			OwnerReferences: []metav1.OwnerReference{
+				metav1.OwnerReference{
+					APIVersion: oapServerConfig.APIVersion,
+					Kind:       oapServerConfig.Kind,
+					Name:       oapServerConfig.Name,
+					UID:        oapServerConfig.UID,
+				},
+			},
+			Labels: labels,
+		},
+		Data: data,
+	}
+
+	if err := r.Client.Create(ctx, &configmap); err != nil {
+		log.Error(err, "failed to create static configuration configmap")
+		return changed, err
+	}
+
+	overlayDeployment := deployment
+	overlayDeployment.Spec.Template.Spec.Containers[0].VolumeMounts = mounts
+	overlayDeployment.Spec.Template.Spec.Volumes = []core.Volume{volume}
+	if err := kubernetes.ApplyOverlay(deployment, overlayDeployment); err != nil {
+		log.Error(err, "failed to apply overlay deployment")
+	}
+
+	log.Info("successfully overlay the file configuration")
+	return changed, nil
+}
+
+func (r *OAPServerConfigReconciler) checkState(ctx context.Context, log logr.Logger,
+	oapServerConfig *operatorv1alpha1.OAPServerConfig, oapList operatorv1alpha1.OAPServerList) error {
+	errCol := new(kubernetes.ErrorCollector)
+
+	nilTime := metav1.Time{}
+	now := metav1.NewTime(time.Now())
+	overlay := operatorv1alpha1.OAPServerConfigStatus{}
+
+	// get Instances and AvailableReplicas
+	for i := range oapList.Items {
+		if oapList.Items[i].Spec.Version == oapServerConfig.Spec.Version {
+			overlay.Desired += int(oapList.Items[i].Spec.Instances)
+			overlay.Ready += int(oapList.Items[i].Status.AvailableReplicas)
+		}
+	}
+
+	if oapServerConfig.Status.CreationTime == nilTime {
+		overlay.CreationTime = now
+		overlay.LastUpdateTime = now
+	} else {
+		overlay.CreationTime = oapServerConfig.Status.CreationTime
+		overlay.LastUpdateTime = now
+	}
+
+	oapServerConfig.Status = overlay
+	oapServerConfig.Kind = "OAPServerConfig"
+	if err := kubernetes.ApplyOverlay(oapServerConfig, &operatorv1alpha1.OAPServerConfig{Status: overlay}); err != nil {
+		errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		return errCol.Error()
+	}
+
+	if err := r.updateStatus(ctx, oapServerConfig, overlay, errCol); err != nil {
+		errCol.Collect(fmt.Errorf("failed to update status of OAPServerConfig: %w", err))
+	}
+
+	log.Info("updated OAPServerConfig sub resource")
+	return errCol.Error()
+}
+
+func (r *OAPServerConfigReconciler) updateStatus(ctx context.Context, oapServerConfig *operatorv1alpha1.OAPServerConfig,
+	overlay operatorv1alpha1.OAPServerConfigStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: oapServerConfig.Name, Namespace: oapServerConfig.Namespace}, oapServerConfig); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get oapServerConfig: %w", err))
+		}
+		oapServerConfig.Status = overlay
+		oapServerConfig.Kind = "OAPServerConfig"
+		if err := kubernetes.ApplyOverlay(oapServerConfig, &operatorv1alpha1.OAPServerConfig{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, oapServerConfig); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *OAPServerConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewControllerManagedBy(mgr).
+		For(&operatorv1alpha1.OAPServerConfig{}).
+		Owns(&apps.Deployment{}).
+		Complete(r)
+}
diff --git a/operator/controllers/operator/oapserverdynamicconfig_controller.go b/operator/controllers/operator/oapserverdynamicconfig_controller.go
new file mode 100644
index 0000000..712199e
--- /dev/null
+++ b/operator/controllers/operator/oapserverdynamicconfig_controller.go
@@ -0,0 +1,303 @@
+// 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.
+
+package operator
+
+import (
+	"context"
+	"crypto/md5"
+	"fmt"
+	"sort"
+	"strings"
+	"time"
+
+	"github.com/go-logr/logr"
+	core "k8s.io/api/core/v1"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/util/retry"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/log"
+	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
+
+	operatorv1alpha1 "github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
+	"github.com/apache/skywalking-swck/operator/pkg/kubernetes"
+)
+
+// OAPServerDynamicConfigReconciler reconciles a OAPServerDynamicConfig object
+type OAPServerDynamicConfigReconciler struct {
+	client.Client
+	Scheme *runtime.Scheme
+}
+
+type SortByConfigName []operatorv1alpha1.Config
+
+func (a SortByConfigName) Len() int {
+	return len(a)
+}
+func (a SortByConfigName) Swap(i, j int) {
+	a[i], a[j] = a[j], a[i]
+}
+func (a SortByConfigName) Less(i, j int) bool {
+	return a[i].Name < a[j].Name
+}
+
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapserverdynamicconfigs,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapserverdynamicconfigs/status,verbs=get;update;patch
+// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapservers,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapservers/status,verbs=get;update;patch
+// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
+
+func (r *OAPServerDynamicConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+	_ = log.FromContext(ctx)
+
+	log := runtimelog.FromContext(ctx)
+	log.Info("=====================reconcile started================================")
+
+	config := operatorv1alpha1.OAPServerDynamicConfig{}
+	if err := r.Client.Get(ctx, req.NamespacedName, &config); err != nil {
+		return ctrl.Result{}, client.IgnoreNotFound(err)
+	}
+
+	oapList := operatorv1alpha1.OAPServerList{}
+	opts := []client.ListOption{
+		client.InNamespace(req.Namespace),
+	}
+
+	if err := r.List(ctx, &oapList, opts...); err != nil && !apierrors.IsNotFound(err) {
+		return ctrl.Result{}, fmt.Errorf("failed to list oapserver: %w", err)
+	}
+
+	// get the specific version's oapserver
+	for i := range oapList.Items {
+		if oapList.Items[i].Spec.Version == config.Spec.Version {
+			oapServer := oapList.Items[i]
+			// Update the dynamic configuration
+			err := r.UpdateDynamicConfig(ctx, log, &oapServer, &config)
+			if err != nil {
+				log.Error(err, "failed to update the dynamic configuration")
+				return ctrl.Result{}, err
+			}
+
+		}
+	}
+
+	if err := r.checkState(ctx, log, &config); err != nil {
+		log.Error(err, "failed to update OAPServerDynamicConfig's status")
+		return ctrl.Result{}, err
+	}
+
+	return ctrl.Result{RequeueAfter: schedDuration}, nil
+}
+
+func (r *OAPServerDynamicConfigReconciler) UpdateDynamicConfig(ctx context.Context, log logr.Logger,
+	oapServer *operatorv1alpha1.OAPServer, config *operatorv1alpha1.OAPServerDynamicConfig) error {
+	changed := false
+	exsitedConfiguration := map[string]bool{}
+
+	dynamicConfigList := operatorv1alpha1.OAPServerDynamicConfigList{}
+	opts := []client.ListOption{
+		client.InNamespace(config.Namespace),
+	}
+	if err := r.List(ctx, &dynamicConfigList, opts...); err != nil && !apierrors.IsNotFound(err) {
+		return fmt.Errorf("failed to list OAPServerDynamicConfig: %w", err)
+	}
+	for _, i := range dynamicConfigList.Items {
+		if i.Name != config.Name {
+			for _, n := range i.Spec.Data {
+				exsitedConfiguration[n.Name] = true
+			}
+		}
+	}
+
+	configuration := config.Spec.Data
+	for i := range configuration {
+		_, ok := exsitedConfiguration[configuration[i].Name]
+		if ok {
+			return fmt.Errorf("the configuration %s already exist", configuration[i].Name)
+		}
+	}
+	sort.Sort(SortByConfigName(configuration))
+	newMd5Hash := MD5Hash(configuration)
+
+	labelSelector, err := labels.Parse(config.Spec.LabelSelector)
+	if err != nil {
+		log.Error(err, "failed to parse string to labelselector")
+		return err
+	}
+	label, err := labels.ConvertSelectorToLabelsMap(config.Spec.LabelSelector)
+	if err != nil {
+		log.Error(err, "failed to convert labelselector to map")
+		return err
+	}
+
+	configmap := core.ConfigMap{}
+	err = r.Client.Get(ctx, client.ObjectKey{Namespace: config.Namespace,
+		Name: config.Name}, &configmap)
+	if err != nil && !apierrors.IsNotFound(err) {
+		log.Error(err, "failed to get the dynamic configuration configmap")
+		return err
+	}
+	// if the configmap exist and the dynamic configuration or labelselector changed, then delete it
+	if !apierrors.IsNotFound(err) {
+		oldMd5Hash := configmap.Labels["md5"]
+		// check dynamic configuration
+		if oldMd5Hash != newMd5Hash {
+			changed = true
+		}
+
+		// check labelselector
+		if !labelSelector.Matches(labels.Set(configmap.Labels)) {
+			changed = true
+		}
+		if changed {
+			if err := r.Client.Delete(ctx, &configmap); err != nil {
+				log.Error(err, "faled to delete the dynamic configuration configmap")
+			}
+		} else {
+			log.Info("dynamic configuration keeps the same as before")
+			return nil
+		}
+	}
+
+	// set the version label
+	label["version"] = config.Spec.Version
+	// set the configuration type
+	label["OAPServerConfig"] = "dynamic"
+	// set the md5 value
+	label["md5"] = newMd5Hash
+	// set the data
+	data := map[string]string{}
+	for _, v := range configuration {
+		data[v.Name] = v.Value
+	}
+	configmap = core.ConfigMap{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      config.Name,
+			Namespace: oapServer.Namespace,
+			OwnerReferences: []metav1.OwnerReference{
+				metav1.OwnerReference{
+					APIVersion: config.APIVersion,
+					Kind:       config.Kind,
+					Name:       config.Name,
+					UID:        config.UID,
+				},
+			},
+			Labels: label,
+		},
+		Data: data,
+	}
+
+	// create the dynamic configuration configmap
+	if err := r.Client.Create(ctx, &configmap); err != nil {
+		log.Error(err, "failed to create dynamic configuration configmap")
+		return err
+	}
+
+	log.Info("successfully setup the dynamic configuration")
+	return nil
+}
+
+func (r *OAPServerDynamicConfigReconciler) checkState(ctx context.Context, log logr.Logger,
+	config *operatorv1alpha1.OAPServerDynamicConfig) error {
+	errCol := new(kubernetes.ErrorCollector)
+
+	nilTime := metav1.Time{}
+	now := metav1.NewTime(time.Now())
+	overlay := operatorv1alpha1.OAPServerDynamicConfigStatus{
+		State: "Stopped",
+	}
+
+	// get dynamic configuration's state
+	configmapList := core.ConfigMapList{}
+	opts := []client.ListOption{
+		client.InNamespace(config.Namespace),
+		client.MatchingLabels{
+			"version":         config.Spec.Version,
+			"OAPServerConfig": "dynamic",
+		},
+	}
+
+	if err := r.List(ctx, &configmapList, opts...); err != nil && !apierrors.IsNotFound(err) {
+		errCol.Collect(fmt.Errorf("failed to list configmap: %w", err))
+	}
+
+	for i := range configmapList.Items {
+		if strings.Contains(configmapList.Items[i].Name, config.Name) {
+			overlay.State = "Running"
+		}
+	}
+
+	if config.Status.CreationTime == nilTime {
+		overlay.CreationTime = now
+		overlay.LastUpdateTime = now
+	} else {
+		overlay.CreationTime = config.Status.CreationTime
+		overlay.LastUpdateTime = now
+	}
+
+	config.Status = overlay
+	config.Kind = "OAPServerDynamicConfig"
+	if err := kubernetes.ApplyOverlay(config, &operatorv1alpha1.OAPServerDynamicConfig{Status: overlay}); err != nil {
+		errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		return errCol.Error()
+	}
+
+	if err := r.updateStatus(ctx, config, overlay, errCol); err != nil {
+		errCol.Collect(fmt.Errorf("failed to update status of OAPServerDynamicConfig: %w", err))
+	}
+
+	log.Info("updated OAPServerDynamicConfig sub resource")
+	return errCol.Error()
+}
+
+func (r *OAPServerDynamicConfigReconciler) updateStatus(ctx context.Context, config *operatorv1alpha1.OAPServerDynamicConfig,
+	overlay operatorv1alpha1.OAPServerDynamicConfigStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: config.Name, Namespace: config.Namespace}, config); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get OAPServerDynamicConfig: %w", err))
+		}
+		config.Status = overlay
+		config.Kind = "OAPServerDynamicConfig"
+		if err := kubernetes.ApplyOverlay(config, &operatorv1alpha1.OAPServerDynamicConfig{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, config); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *OAPServerDynamicConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewControllerManagedBy(mgr).
+		For(&operatorv1alpha1.OAPServerDynamicConfig{}).
+		Complete(r)
+}
+
+func MD5Hash(a interface{}) string {
+	h := md5.New()
+	h.Write([]byte(fmt.Sprintf("%v", a)))
+
+	return fmt.Sprintf("%x", h.Sum(nil))
+}
diff --git a/operator/controllers/operator/satellite_controller.go b/operator/controllers/operator/satellite_controller.go
index ad35548..b376041 100644
--- a/operator/controllers/operator/satellite_controller.go
+++ b/operator/controllers/operator/satellite_controller.go
@@ -27,6 +27,7 @@ import (
 	apiequal "k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/tools/record"
+	"k8s.io/client-go/util/retry"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
@@ -105,7 +106,7 @@ func (r *SatelliteReconciler) checkState(ctx context.Context, log logr.Logger, s
 		errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
 		return errCol.Error()
 	}
-	if err := r.Status().Update(ctx, satellite); err != nil {
+	if err := r.updateStatus(ctx, satellite, overlay, errCol); err != nil {
 		errCol.Collect(fmt.Errorf("failed to update status of satellite: %w", err))
 	}
 	log.Info("updated Status sub resource")
@@ -113,6 +114,25 @@ func (r *SatelliteReconciler) checkState(ctx context.Context, log logr.Logger, s
 	return errCol.Error()
 }
 
+func (r *SatelliteReconciler) updateStatus(ctx context.Context, satellite *operatorv1alpha1.Satellite,
+	overlay operatorv1alpha1.SatelliteStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: satellite.Name, Namespace: satellite.Namespace}, satellite); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get satellite: %w", err))
+		}
+		satellite.Status = overlay
+		satellite.Kind = "Satellite"
+		if err := kubernetes.ApplyOverlay(satellite, &operatorv1alpha1.Satellite{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, satellite); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status of satellite: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
 // SetupWithManager sets up the controller with the Manager.
 func (r *SatelliteReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
diff --git a/operator/controllers/operator/storage_controller.go b/operator/controllers/operator/storage_controller.go
index d41e596..6d615f6 100644
--- a/operator/controllers/operator/storage_controller.go
+++ b/operator/controllers/operator/storage_controller.go
@@ -42,6 +42,7 @@ import (
 	kubeclient "k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/record"
+	"k8s.io/client-go/util/retry"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
@@ -144,13 +145,32 @@ func (r *StorageReconciler) checkState(ctx context.Context, log logr.Logger, sto
 		errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
 		return errCol.Error()
 	}
-	if err := r.Status().Update(ctx, storage); err != nil {
+	if err := r.updateStatus(ctx, storage, overlay, errCol); err != nil {
 		errCol.Collect(fmt.Errorf("failed to update status of es: %w", err))
 	}
 	log.Info("updated Status sub resource")
 	return errCol.Error()
 }
 
+func (r *StorageReconciler) updateStatus(ctx context.Context, storage *operatorv1alpha1.Storage,
+	overlay operatorv1alpha1.StorageStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: storage.Name, Namespace: storage.Namespace}, storage); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get storage: %w", err))
+		}
+		storage.Status = overlay
+		storage.Kind = "Storage"
+		if err := kubernetes.ApplyOverlay(storage, &operatorv1alpha1.Storage{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, storage); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status of storage: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
 func (r *StorageReconciler) checkSecurity(ctx context.Context, log logr.Logger, s *operatorv1alpha1.Storage) {
 	user, tls := s.Spec.Security.User, s.Spec.Security.TLS
 	if user.SecretName != "" {
diff --git a/operator/controllers/operator/ui_controller.go b/operator/controllers/operator/ui_controller.go
index 816a97c..06a9d83 100644
--- a/operator/controllers/operator/ui_controller.go
+++ b/operator/controllers/operator/ui_controller.go
@@ -29,10 +29,12 @@ import (
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/tools/record"
+	"k8s.io/client-go/util/retry"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
 
+	operatorv1alpha1 "github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
 	uiv1alpha1 "github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
 	"github.com/apache/skywalking-swck/operator/pkg/kubernetes"
 )
@@ -115,7 +117,7 @@ func (r *UIReconciler) checkState(ctx context.Context, log logr.Logger, ui *uiv1
 		errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
 		return errCol.Error()
 	}
-	if err := r.Status().Update(ctx, ui); err != nil {
+	if err := r.updateStatus(ctx, ui, overlay, errCol); err != nil {
 		errCol.Collect(fmt.Errorf("failed to update status of UI: %w", err))
 	}
 	log.Info("updated Status sub resource")
@@ -123,6 +125,25 @@ func (r *UIReconciler) checkState(ctx context.Context, log logr.Logger, ui *uiv1
 	return errCol.Error()
 }
 
+func (r *UIReconciler) updateStatus(ctx context.Context, ui *uiv1alpha1.UI,
+	overlay operatorv1alpha1.UIStatus, errCol *kubernetes.ErrorCollector) error {
+	// avoid resource conflict
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		if err := r.Client.Get(ctx, client.ObjectKey{Name: ui.Name, Namespace: ui.Namespace}, ui); err != nil {
+			errCol.Collect(fmt.Errorf("failed to get ui: %w", err))
+		}
+		ui.Status = overlay
+		ui.Kind = "UI"
+		if err := kubernetes.ApplyOverlay(ui, &operatorv1alpha1.UI{Status: overlay}); err != nil {
+			errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+		}
+		if err := r.Status().Update(ctx, ui); err != nil {
+			errCol.Collect(fmt.Errorf("failed to update status of ui: %w", err))
+		}
+		return errCol.Error()
+	})
+}
+
 func (r *UIReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
 		For(&uiv1alpha1.UI{}).
diff --git a/operator/main.go b/operator/main.go
index 4806dad..e4b4174 100644
--- a/operator/main.go
+++ b/operator/main.go
@@ -24,7 +24,6 @@ import (
 	"k8s.io/apimachinery/pkg/runtime"
 	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	"sigs.k8s.io/controller-runtime/pkg/webhook"
 
 	// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
 	// to ensure that exec-entrypoint and run can make use of them.
@@ -32,6 +31,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/healthz"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+	"sigs.k8s.io/controller-runtime/pkg/webhook"
 
 	operatorv1alpha1 "github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
 	operatorcontroller "github.com/apache/skywalking-swck/operator/controllers/operator"
@@ -143,8 +143,22 @@ func main() {
 		setupLog.Error(err, "unable to create controller", "controller", "Satellite")
 		os.Exit(1)
 	}
-	//+kubebuilder:scaffold:builder
+	if err = (&operatorcontrollers.OAPServerConfigReconciler{
+		Client: mgr.GetClient(),
+		Scheme: mgr.GetScheme(),
+	}).SetupWithManager(mgr); err != nil {
+		setupLog.Error(err, "unable to create controller", "controller", "OAPServerConfig")
+		os.Exit(1)
+	}
+	if err = (&operatorcontrollers.OAPServerDynamicConfigReconciler{
+		Client: mgr.GetClient(),
+		Scheme: mgr.GetScheme(),
+	}).SetupWithManager(mgr); err != nil {
+		setupLog.Error(err, "unable to create controller", "controller", "OAPServerDynamicConfig")
+		os.Exit(1)
+	}
 
+	//+kubebuilder:scaffold:builder
 	if os.Getenv("ENABLE_WEBHOOKS") != "false" {
 		if err = (&operatorv1alpha1.OAPServer{}).SetupWebhookWithManager(mgr); err != nil {
 			setupLog.Error(err, "unable to create webhook", "webhook", "OAPServer")
@@ -170,6 +184,14 @@ func main() {
 			setupLog.Error(err, "unable to create webhook", "webhook", "Satellite")
 			os.Exit(1)
 		}
+		if err = (&operatorv1alpha1.OAPServerConfig{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, "unable to create webhook", "webhook", "OAPServerConfig")
+			os.Exit(1)
+		}
+		if err = (&operatorv1alpha1.OAPServerDynamicConfig{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, "unable to create webhook", "webhook", "OAPServerDynamicConfig")
+			os.Exit(1)
+		}
 		// register a webhook to enable the java agent injector
 		setupLog.Info("registering /mutate-v1-pod webhook")
 		mgr.GetWebhookServer().Register("/mutate-v1-pod",
diff --git a/operator/pkg/operator/manifests/injector/templates/annotations.yaml b/operator/pkg/operator/manifests/injector/templates/annotations.yaml
index 46680fd..31a6777 100644
--- a/operator/pkg/operator/manifests/injector/templates/annotations.yaml
+++ b/operator/pkg/operator/manifests/injector/templates/annotations.yaml
@@ -30,7 +30,7 @@ annotations:
     envName: nil
 
   - name: sidecar.skywalking.apache.org/initcontainer.Image
-    defaultValue: apache/skywalking-java-agent:8.8.0-java8
+    defaultValue: apache/skywalking-java-agent:8.10.0-java8
     validateFunc: nil
     envName: nil
 
diff --git a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml b/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
index 368682d..ff6b859 100644
--- a/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
+++ b/operator/pkg/operator/manifests/oapserver/templates/cluster_role.yaml
@@ -24,7 +24,7 @@ metadata:
     operator.skywalking.apache.org/component: rbac
 rules:
   - apiGroups: [""]
-    resources: ["pods", "endpoints", "services"]
+    resources: ["pods", "endpoints", "services", "configmaps"]
     verbs: ["get", "watch", "list"]
   - apiGroups: ["extensions"]
     resources: ["deployments", "replicasets"]
diff --git a/test/e2e/kind.yaml b/test/e2e/kind.yaml
index fcb7a90..ce15e28 100644
--- a/test/e2e/kind.yaml
+++ b/test/e2e/kind.yaml
@@ -17,25 +17,10 @@
 # NOTE: this is not a particularly useful config file
 kind: Cluster
 apiVersion: kind.x-k8s.io/v1alpha4
-# patch the generated kubeadm config with some extra settings
-kubeadmConfigPatches:
-- |
-  apiVersion: kubelet.config.k8s.io/v1beta1
-  kind: KubeletConfiguration
-  evictionHard:
-    nodefs.available: "0%"
-# patch it further using a JSON 6902 patch
-kubeadmConfigPatchesJSON6902:
-- group: kubeadm.k8s.io
-  version: v1beta2
-  kind: ClusterConfiguration
-  patch: |
-    - op: add
-      path: /apiServer/certSANs/-
-      value: my-hostname
-# 1 control plane node
+# control plane node
 nodes:
-# the control plane node config
 - role: control-plane
-  image: kindest/node:v1.19.1
+  image: kindest/node:v1.21.10
+- role: worker
+  image: kindest/node:v1.21.10
 
diff --git a/test/e2e/oap-agent-adapter-hpa/e2e.yaml b/test/e2e/oap-agent-adapter-hpa/e2e.yaml
index da5a40f..17af5e6 100644
--- a/test/e2e/oap-agent-adapter-hpa/e2e.yaml
+++ b/test/e2e/oap-agent-adapter-hpa/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
@@ -45,10 +45,7 @@ setup:
         make -C adapter docker-build
         kind load docker-image metrics-adapter
         make -C adapter deploy
-      wait:
-        - namespace: skywalking-custom-metrics-system
-          resource: pod
-          for: condition=Ready
+        kubectl wait pods -n skywalking-custom-metrics-system -l app=custom-metrics-apiserver --for condition=Ready --timeout=90s
     - name: setup oapserver and ui
       command: |
         kubectl create namespace skywalking-system
diff --git a/test/e2e/oap-satellite-adapter-hpa/e2e.yaml b/test/e2e/oap-satellite-adapter-hpa/e2e.yaml
index 492cd0c..d9c5b9a 100644
--- a/test/e2e/oap-satellite-adapter-hpa/e2e.yaml
+++ b/test/e2e/oap-satellite-adapter-hpa/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
@@ -45,10 +45,7 @@ setup:
         make -C adapter docker-build
         kind load docker-image metrics-adapter
         make -C adapter deploy
-      wait:
-        - namespace: skywalking-custom-metrics-system
-          resource: pod
-          for: condition=Ready
+        kubectl wait pods -n skywalking-custom-metrics-system -l app=custom-metrics-apiserver --for condition=Ready --timeout=180s
     - name: setup oapserver and ui
       command: |
         kubectl create namespace skywalking-system
@@ -74,6 +71,7 @@ setup:
     - name: increase the satellite connection count
       command: |
         kubectl -n skywalking-system scale deployment/demo --replicas 5
+        kubectl rollout status --watch --timeout=120s deployment/demo -n skywalking-system
   kind:
     expose-ports:
       - namespace: skywalking-system
@@ -95,11 +93,11 @@ verify:
   # verify with retry strategy
   retry:
     # max retry count
-    count: 10
+    count: 15
     # the interval between two attempts, e.g. 10s, 1m.
     interval: 15s
   cases:
-    - query: swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql metrics linear --name satellite_service_grpc_connect_count --service-name satellite::satellite-service | yq e 'to_entries' -
+    - query: swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql metrics linear --name satellite_service_grpc_connect_count --service-name satellite-service | yq e 'to_entries' -
       expected: ../verify/satellite-hpa-metrics.yaml
     # the trigger will do 30 times, as the hpa's value is set as 5, so the deployment's replicas will be 3(maxReplicas).
     - query: 'kubectl get deployment skywalking-system-satellite -n skywalking-system -o jsonpath=''{.status.replicas}'' | yq e ''{"replicas": .}'' - | yq e ''to_entries'' -'
diff --git a/test/e2e/oap-ui-agent-external-storage/e2e.yaml b/test/e2e/oap-ui-agent-external-storage/e2e.yaml
index 0c13d67..cdc26d4 100644
--- a/test/e2e/oap-ui-agent-external-storage/e2e.yaml
+++ b/test/e2e/oap-ui-agent-external-storage/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
@@ -42,11 +42,7 @@ setup:
     - name: setup elasticsearch
       command: |
         kubectl apply -f test/e2e/deploy-elasticsearch.yaml
-      wait:
-        - namespace: default
-          resource: pod
-          label-selector: k8s-app=es
-          for: condition=Ready
+        kubectl rollout status --watch --timeout=120s statefulset/es
     - name: setup storage(use the external type)
       command: |
         kubectl apply -f test/e2e/external-storage.yaml
diff --git a/test/e2e/oap-ui-agent-internal-storage/e2e.yaml b/test/e2e/oap-ui-agent-internal-storage/e2e.yaml
index f45a4e6..9a9ad8c 100644
--- a/test/e2e/oap-ui-agent-internal-storage/e2e.yaml
+++ b/test/e2e/oap-ui-agent-internal-storage/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
diff --git a/test/e2e/oap-ui-agent/e2e.yaml b/test/e2e/oap-ui-agent-oapserverconfig-oapserverdynamicconfig/e2e.yaml
similarity index 61%
copy from test/e2e/oap-ui-agent/e2e.yaml
copy to test/e2e/oap-ui-agent-oapserverconfig-oapserverdynamicconfig/e2e.yaml
index 06405b1..830ceaa 100644
--- a/test/e2e/oap-ui-agent/e2e.yaml
+++ b/test/e2e/oap-ui-agent-oapserverconfig-oapserverdynamicconfig/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
@@ -40,7 +40,7 @@ setup:
           resource: pod
           for: condition=Ready
     - name: setup oapserver and ui
-      command: |
+      command: | 
         kubectl create namespace skywalking-system
         kubectl apply -f test/e2e/skywalking-components.yaml
       wait:
@@ -50,19 +50,43 @@ setup:
         - namespace: skywalking-system
           resource: UI/skywalking-system
           for: condition=Available
-    - name: setup java agent demo
+    - name: setup java agent demo(test for dynamic configuration)
       command: |
         kubectl label namespace skywalking-system swck-injection=enabled
         sed 's/oap-service/skywalking-system-oap.skywalking-system/' test/e2e/demo.yaml | kubectl create -f -
       wait:
         - namespace: skywalking-system
           resource: deployment/demo
+          for: condition=Available
+    - name: setup oapserverconfig(static configuration)
+      command: |
+        export oap_podname=$(kubectl get pod -lapp=oap -n skywalking-system -o jsonpath='{.items[*].metadata.name}')
+        kubectl apply -f test/e2e/oapserverconfig-demo.yaml
+    - name: wait the old pod teminated
+      command: |
+        while kubectl get pod $oap_podname -n skywalking-system > /dev/null; \
+        do \
+          sleep 0.1; \
+        done
+    - name: setup java agent demo(test for static configuration)
+      command: |
+        sed 's/oap-service/skywalking-system-oap.skywalking-system/' test/e2e/resource.yaml | kubectl create -f -
+      wait:
+        - namespace: skywalking-system
+          resource: deployment/songs-deployment
           for: condition=Available 
+    - name: setup oapserverdynamicconfig(dynamic configuration)
+      command: |
+        sed 's/default: 0.1/default: 500/' test/e2e/oapserverdynamicconfig-demo.yaml | kubectl apply -f -
+        kubectl get po -A
   kind:
     expose-ports:
       - namespace: skywalking-system
         resource: service/demo 
         port: 8085
+      - namespace: skywalking-system
+        resource: service/songs 
+        port: 80
       - namespace: skywalking-system
         resource: service/skywalking-system-oap
         port: 12800
@@ -77,7 +101,7 @@ cleanup:
 
 trigger:
   action: http
-  interval: 10s
+  interval: 5s
   times: 5
   url: http://${service_demo_host}:${service_demo_8085}/hello
   method: GET
@@ -86,7 +110,7 @@ verify:
   # verify with retry strategy
   retry:
     # max retry count
-    count: 10
+    count: 20
     # the interval between two attempts, e.g. 10s, 1m.
     interval: 10s
   cases:
@@ -100,4 +124,16 @@ verify:
     - query: swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql metrics linear --name endpoint_cpm --endpoint-name GET:/hello --service-name Your_ApplicationName | yq e 'to_entries' -
       expected: ../verify/metrics.yaml
     - includes:
-        - ../ui-cases.yaml
\ No newline at end of file
+        - ../ui-cases.yaml
+    # test oapsever's static configuration
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql logs list --service-name=agent::songs --tags level=INFO --trace-id=$( \
+            swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql trace ls \
+              | yq e '.traces | select(.[].endpointnames[0]=="HikariCP/Connection/getConnection") | .[0].traceids[0]' -
+        ) | yq e '.logs' -
+      expected: ../verify/logs.yaml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql metrics linear --name=log_count_info --instance-name=songs --service-name=agent::songs | yq e 'to_entries' -
+      expected: ../verify/metrics.yaml
+    # test oapsever's dynamic configuration
+    - query: swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql metrics linear --name=service_apdex --service-name=Your_ApplicationName | yq e 'to_entries' -
+      expected: ../verify/service-apdex.yaml
\ No newline at end of file
diff --git a/test/e2e/oap-ui-agent-satellite/e2e.yaml b/test/e2e/oap-ui-agent-satellite/e2e.yaml
index 5374776..cf003fd 100644
--- a/test/e2e/oap-ui-agent-satellite/e2e.yaml
+++ b/test/e2e/oap-ui-agent-satellite/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
diff --git a/test/e2e/oap-ui-agent/e2e.yaml b/test/e2e/oap-ui-agent/e2e.yaml
index 06405b1..fe489c2 100644
--- a/test/e2e/oap-ui-agent/e2e.yaml
+++ b/test/e2e/oap-ui-agent/e2e.yaml
@@ -23,7 +23,7 @@ setup:
       command: |
         # kind k8s cluster is in $TMPDIR
         export KUBECONFIG=$TMPDIR/e2e-k8s.config
-        kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+        kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
       wait:
         - namespace: cert-manager
           resource: pod
diff --git a/test/e2e/oapserverconfig-demo.yaml b/test/e2e/oapserverconfig-demo.yaml
new file mode 100644
index 0000000..cdf982a
--- /dev/null
+++ b/test/e2e/oapserverconfig-demo.yaml
@@ -0,0 +1,87 @@
+# 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.
+
+# static configuration of OAPServer
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerConfig
+metadata:
+  name: oapserverconfig-sample
+  namespace: skywalking-system
+spec:
+  # The version of OAPServer
+  version: 9.0.0
+  # The env configuration of OAPServer
+  env:
+    - name: ONLY_TEST
+      value: testonly
+    - name: JAVA_OPTS
+      value: -Xmx2048M
+    - name: SW_CLUSTER
+      value: kubernetes
+    - name: SW_CLUSTER_K8S_NAMESPACE
+      value: skywalking-system
+    # enable the dynamic configuration
+    - name: SW_CONFIGURATION
+      value: k8s-configmap
+    # set the labelselector of the dynamic configuration
+    - name: SW_CLUSTER_K8S_LABEL
+      value: app=collector,release=skywalking
+    - name: SW_TELEMETRY
+      value: prometheus
+    - name: SW_HEALTH_CHECKER
+      value: default
+    - name: SKYWALKING_COLLECTOR_UID
+      valueFrom:
+        fieldRef:
+          fieldPath: metadata.uid
+    - name: SW_LOG_LAL_FILES
+      value: test1
+    - name: SW_LOG_MAL_FILES
+      value: test2
+  # The file configuration of OAPServer
+  # we should avoid setting the same name in the file
+  file:
+    - name: test1.yaml
+      path: /skywalking/config/lal
+      data: |
+        rules:
+          - name: example
+            dsl: |
+              filter {
+                text {
+                  abortOnFailure false // for test purpose, we want to persist all logs
+                  regexp $/(?s)(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}) \[TID:(?<tid>.+?)] \[(?<thread>.+?)] (?<level>\w{4,}) (?<logger>.{1,36}) (?<msg>.+)/$
+                }
+                extractor {
+                  metrics {
+                    timestamp log.timestamp as Long
+                    labels level: parsed.level, service: log.service, instance: log.serviceInstance
+                    name "log_count"
+                    value 1
+                  }
+                }
+                sink {
+                }
+              }
+    - name: test2.yaml
+      path: /skywalking/config/log-mal-rules
+      data: |
+        expSuffix: instance(['service'], ['instance'], Layer.GENERAL)
+        metricPrefix: log
+        metricsRules:
+          - name: count_info
+            exp: log_count.tagEqual('level', 'INFO').sum(['service', 'instance']).downsampling(SUM)
diff --git a/test/e2e/oapserverdynamicconfig-demo.yaml b/test/e2e/oapserverdynamicconfig-demo.yaml
new file mode 100644
index 0000000..c25efc5
--- /dev/null
+++ b/test/e2e/oapserverdynamicconfig-demo.yaml
@@ -0,0 +1,117 @@
+# 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.
+
+# static configuration of OAPServer
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServerDynamicConfig
+metadata:
+  name: oapserverdynamicconfig-sample
+  namespace: skywalking-system
+spec:
+  # The version of OAPServer
+  version: 9.0.0
+  # The labelselector of OAPServer's dynamic configuration, it should be the same as labelSelector of OAPServerConfig
+  labelSelector: app=collector,release=skywalking
+  data:
+    - name: agent-analyzer.default.slowDBAccessThreshold
+      value: default:200,mongodb:50
+    - name: alarm.default.alarm-settings
+      value: |-
+        rules:
+          # Rule unique name, must be ended with `_rule`.
+          service_resp_time_rule:
+            metrics-name: service_resp_time
+            op: ">"
+            threshold: 1000
+            period: 10
+            count: 3
+            silence-period: 5
+            message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
+          service_sla_rule:
+            # Metrics value need to be long, double or int
+            metrics-name: service_sla
+            op: "<"
+            threshold: 8000
+            # The length of time to evaluate the metrics
+            period: 10
+            # How many times after the metrics match the condition, will trigger alarm
+            count: 2
+            # How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
+            silence-period: 3
+            message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
+          service_resp_time_percentile_rule:
+            # Metrics value need to be long, double or int
+            metrics-name: service_percentile
+            op: ">"
+            threshold: 1000,1000,1000,1000,1000
+            period: 10
+            count: 3
+            silence-period: 5
+            message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
+          service_instance_resp_time_rule:
+            metrics-name: service_instance_resp_time
+            op: ">"
+            threshold: 1000
+            period: 10
+            count: 2
+            silence-period: 5
+            message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
+          database_access_resp_time_rule:
+            metrics-name: database_access_resp_time
+            threshold: 1000
+            op: ">"
+            period: 10
+            count: 2
+            message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes
+          endpoint_relation_resp_time_rule:
+            metrics-name: endpoint_relation_resp_time
+            threshold: 1000
+            op: ">"
+            period: 10
+            count: 2
+            message: Response time of endpoint relation {name} is more than 1000ms in 2 minutes of last 10 minutes
+        #  Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
+        #  Because the number of endpoint is much more than service and instance.
+        #
+        #  endpoint_resp_time_rule:
+        #    metrics-name: endpoint_resp_time
+        #    op: ">"
+        #    threshold: 1000
+        #    period: 10
+        #    count: 2
+        #    silence-period: 5
+        #    message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
+
+        webhooks:
+        #  - http://127.0.0.1/notify/
+        #  - http://127.0.0.1/go-wechat/
+    - name: core.default.apdexThreshold
+      value: |-
+        # 0.1 is only for testing
+        default: 0.1
+        # example:
+        # the threshold of service "tomcat" is 1s
+        # tomcat: 1000
+        # the threshold of service "springboot1" is 50ms
+        # springboot1: 50
+    - name: agent-analyzer.default.uninstrumentedGateways
+      value: |-
+        #gateways:
+        #  - name: proxy0
+        #    instances:
+        #      - host: 127.0.0.1 # the host/ip of this gateway instance
+        #        port: 9099 # the port of this gateway instance, defaults to 80
\ No newline at end of file
diff --git a/test/e2e/resource.yaml b/test/e2e/resource.yaml
new file mode 100644
index 0000000..9425256
--- /dev/null
+++ b/test/e2e/resource.yaml
@@ -0,0 +1,62 @@
+# 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.
+#
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: songs-deployment
+  namespace: skywalking-system
+  labels:
+    app: songs
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: songs
+  template:
+    metadata:
+      labels:
+        swck-java-agent-injected: "true"
+        app: songs
+      annotations:
+        strategy.skywalking.apache.org/agent.Overlay: "true"
+        agent.skywalking.apache.org/agent.service_name: "agent::songs"
+        agent.skywalking.apache.org/collector.backend_service: "oap-service:11800"
+        agent.skywalking.apache.org/agent.instance_name: "songs"
+    spec:
+      containers:
+        - name: songs
+          image: ghcr.io/apache/skywalking-showcase/songs-service:7c17079-agentless
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 80
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: songs
+  namespace: skywalking-system
+spec:
+  selector:
+    app: songs
+  ports:
+    - protocol: TCP
+      port: 80
+      targetPort: 80
\ No newline at end of file
diff --git a/test/e2e/satellite-hpa-demo.yaml b/test/e2e/satellite-hpa-demo.yaml
index 08b5e50..dfcbf38 100644
--- a/test/e2e/satellite-hpa-demo.yaml
+++ b/test/e2e/satellite-hpa-demo.yaml
@@ -32,9 +32,6 @@ spec:
         name: skywalking.apache.org|satellite_service_grpc_connect_count
         selector:
           matchLabels:
-            "service.str.0": "satellite"
-            "service.byte.1": "3a"
-            "service.byte.2": "3a"
             "service.str.3": "satellite"
             "service.byte.4": "2d"
             "service.str.5": "service"
diff --git a/test/e2e/skywalking-components-with-satellite.yaml b/test/e2e/skywalking-components-with-satellite.yaml
index 08d6406..71d2611 100644
--- a/test/e2e/skywalking-components-with-satellite.yaml
+++ b/test/e2e/skywalking-components-with-satellite.yaml
@@ -21,9 +21,9 @@ metadata:
   name: skywalking-system
   namespace: skywalking-system
 spec:
-  version: 8.9.1
+  version: 9.0.0
   instances: 1
-  image: ghcr.io/apache/skywalking/oap:e74adec05fd8a93ee945bcc4a3c7fcbb3761c5c7
+  image: apache/skywalking-oap-server:9.0.0
   config:
     - name: SW_METER_ANALYZER_ACTIVE_FILES
       value: satellite
@@ -55,9 +55,9 @@ metadata:
   name: skywalking-system
   namespace: skywalking-system
 spec:
-  version: 8.9.1
+  version: 9.0.0
   instances: 1
-  image: apache/skywalking-ui:8.9.1
+  image: apache/skywalking-ui:9.0.0
   OAPServerAddress: http://skywalking-system-oap.skywalking-system:12800
   service:
     template:
diff --git a/test/e2e/skywalking-components-with-storage.yaml b/test/e2e/skywalking-components-with-storage.yaml
index 168876e..1dd0777 100644
--- a/test/e2e/skywalking-components-with-storage.yaml
+++ b/test/e2e/skywalking-components-with-storage.yaml
@@ -20,9 +20,9 @@ kind: OAPServer
 metadata:
   name: default
 spec:
-  version: 8.8.1
+  version: 9.0.0
   instances: 1
-  image: apache/skywalking-oap-server:8.8.1
+  image: apache/skywalking-oap-server:9.0.0
   service:
     template:
       type: ClusterIP
@@ -35,9 +35,9 @@ metadata:
   name: skywalking-system
   namespace: skywalking-system
 spec:
-  version: 8.8.1
+  version: 9.0.0
   instances: 1
-  image: apache/skywalking-ui:8.8.1
+  image: apache/skywalking-ui:9.0.0
   OAPServerAddress: http://default-oap.default:12800
   service:
     template:
diff --git a/test/e2e/skywalking-components.yaml b/test/e2e/skywalking-components.yaml
index 45a435f..dbb51b9 100644
--- a/test/e2e/skywalking-components.yaml
+++ b/test/e2e/skywalking-components.yaml
@@ -21,9 +21,9 @@ metadata:
   name: skywalking-system
   namespace: skywalking-system
 spec:
-  version: 8.8.1
+  version: 9.0.0
   instances: 1
-  image: apache/skywalking-oap-server:8.8.1
+  image: apache/skywalking-oap-server:9.0.0
   service:
     template:
       type: ClusterIP
@@ -35,9 +35,9 @@ metadata:
   name: skywalking-system
   namespace: skywalking-system
 spec:
-  version: 8.8.1
+  version: 9.0.0
   instances: 1
-  image: apache/skywalking-ui:8.8.1
+  image: apache/skywalking-ui:9.0.0
   OAPServerAddress: http://skywalking-system-oap.skywalking-system:12800
   service:
     template:
diff --git a/test/e2e/satellite-hpa-demo.yaml b/test/e2e/verify/logs.yaml
similarity index 52%
copy from test/e2e/satellite-hpa-demo.yaml
copy to test/e2e/verify/logs.yaml
index 08b5e50..e98afc2 100644
--- a/test/e2e/satellite-hpa-demo.yaml
+++ b/test/e2e/verify/logs.yaml
@@ -13,31 +13,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-apiVersion: autoscaling/v2beta2
-kind: HorizontalPodAutoscaler
-metadata:
-  name: hpa-demo
-  namespace: skywalking-system
-spec:
-  scaleTargetRef:
-    apiVersion: apps/v1
-    kind: Deployment
-    name: skywalking-system-satellite
-  minReplicas: 1
-  maxReplicas: 3
-  metrics:
-  - type: External
-    external:
-      metric:
-        name: skywalking.apache.org|satellite_service_grpc_connect_count
-        selector:
-          matchLabels:
-            "service.str.0": "satellite"
-            "service.byte.1": "3a"
-            "service.byte.2": "3a"
-            "service.str.3": "satellite"
-            "service.byte.4": "2d"
-            "service.str.5": "service"
-      target:
-        type: Value
-        value: 2
\ No newline at end of file
+{{- contains . }}
+- servicename: agent::songs
+  serviceid: {{ b64enc "agent::songs" }}.1
+  serviceinstancename: songs
+  serviceinstanceid: {{ b64enc "agent::songs" }}.1_{{ b64enc "songs" }}
+  endpointname: null
+  endpointid: null
+  traceid: {{ .traceid }}
+  timestamp: {{ gt .timestamp 0 }}
+  contenttype: TEXT
+  content: |
+    {{ notEmpty .content }}
+  tags:
+  {{- contains .tags }}
+  - key: level
+    value: INFO
+  - key: logger
+    value: {{ notEmpty .value }}
+  - key: thread
+    value: {{ notEmpty .value }}
+  {{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/test/e2e/satellite-hpa-demo.yaml b/test/e2e/verify/service-apdex.yaml
similarity index 52%
copy from test/e2e/satellite-hpa-demo.yaml
copy to test/e2e/verify/service-apdex.yaml
index 08b5e50..fa76e89 100644
--- a/test/e2e/satellite-hpa-demo.yaml
+++ b/test/e2e/verify/service-apdex.yaml
@@ -13,31 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-apiVersion: autoscaling/v2beta2
-kind: HorizontalPodAutoscaler
-metadata:
-  name: hpa-demo
-  namespace: skywalking-system
-spec:
-  scaleTargetRef:
-    apiVersion: apps/v1
-    kind: Deployment
-    name: skywalking-system-satellite
-  minReplicas: 1
-  maxReplicas: 3
-  metrics:
-  - type: External
-    external:
-      metric:
-        name: skywalking.apache.org|satellite_service_grpc_connect_count
-        selector:
-          matchLabels:
-            "service.str.0": "satellite"
-            "service.byte.1": "3a"
-            "service.byte.2": "3a"
-            "service.str.3": "satellite"
-            "service.byte.4": "2d"
-            "service.str.5": "service"
-      target:
-        type: Value
-        value: 2
\ No newline at end of file
+{{- contains . }}
+- key: {{ notEmpty .key }}
+  value: {{ gt .value 0 }}
+{{- end }}
\ No newline at end of file