Repository: pingcap/chaos-mesh
Pull request #109 (2020-01-03 15:34:31)

iochaos: add selector for injecting sidecar when using init-request config
Signed-off-by: cwen0 <cwenyin0@gmail.com> 

In this pr, we add a selector in the config of the sidecar, because we need it when we inject sidecar at the starting of the app cluster.  For example, we want to inject sidecar to tikv pod at the starting of tidb cluster, we can apply the config of tikv sidecar  [ tikv-configmap.yaml](https://github.com/pingcap/chaos-mesh/blob/master/examples/chaosfs-configmap/tikv-configmap.yaml) and the selector need to add to the config file.

eg: 
```
apiVersion: v1
kind: ConfigMap
metadata:
  name: chaosfs-tikv
  labels:
    app.kubernetes.io/component: webhook
data:
  chaosfs-tikv.yaml: |
    name: chaosfs-tikv
    selector: 
      labelSelectors:
        "app.kubernetes.io/component": "tikv"
    initContainers:
    - name: inject-scripts
      image: pingcap/chaos-scripts:latest
      imagePullpolicy: Always
      command: ["sh", "-c", "mkdir -p /tmp/scripts; cp -R /scripts/* /tmp/scripts/; mkdir -p /var/lib/tikv/fuse-data"]
    containers:
   .....
``` 

Then add `admission-webhook.pingcap.com/init-request=chaosfs-tikv` to the annotation of the tidb cluster namespace and start the tidb cluster. The tikv pod created next will be injected into the sidecar container. 

cwen0: @mahjonp PTAL again, thanks!

Patch:
diff --git a/Makefile b/Makefile
index ad336b15..3c61ae42 100644
--- a/Makefile
+++ b/Makefile
@@ -165,7 +165,7 @@ else
 	@echo "kustomize has been installed"
 endif
 
-install-test-dependency:
+install-test-dependency: install-kubebuilder
 	go get -u github.com/jstemmer/go-junit-report \
 	&& go get github.com/axw/gocov/gocov \
 	&& go get github.com/AlekSi/gocov-xml \
diff --git a/config/crd/bases/pingcap.com_iochaos.yaml b/config/crd/bases/pingcap.com_iochaos.yaml
index 202646ac..a8ad5df8 100644
--- a/config/crd/bases/pingcap.com_iochaos.yaml
+++ b/config/crd/bases/pingcap.com_iochaos.yaml
@@ -46,12 +46,12 @@ spec:
                 pod.
               type: string
             delay:
-              description: "Delay defines the value of I/O chaos action delay. It
-                is required when the action is `PodFailureAction`. A delay string
-                is a possibly signed sequence of decimal numbers, each with optional
-                fraction and a unit suffix, such as \"300ms\". Valid time units are
-                \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\". \n If `Delay`
-                is empty, the operator will generate a value for it randomly."
+              description: "Delay defines the value of I/O chaos action delay. A delay
+                string is a possibly signed sequence of decimal numbers, each with
+                optional fraction and a unit suffix, such as \"300ms\". Valid time
+                units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".
+                \n If `Delay` is empty, the operator will generate a value for it
+                randomly."
               type: string
             duration:
               description: Duration represents the duration of the chaos action. It
@@ -68,7 +68,7 @@ spec:
               type: string
             layer:
               description: 'Layer represents the layer of the I/O action. Supported
-                value: fs / errno / mixed. Default layer: fs'
+                value: fs. Default layer: fs'
               type: string
             methods:
               description: 'Methods defines the I/O methods for injecting I/O chaos
@@ -81,11 +81,11 @@ spec:
                 one / all / fixed / fixed-percent / random-max-percent'
               type: string
             nextRecover:
-              description: Next time when this action will be recovered
+              description: Next time when this action will be recovered.
               format: date-time
               type: string
             nextStart:
-              description: Next time when this action will be applied again
+              description: Next time when this action will be applied again.
               format: date-time
               type: string
             path:
diff --git a/examples/chaosfs-configmap/pd-configmap.yaml b/examples/chaosfs-configmap/pd-configmap.yaml
index ac63edd0..4292bfb2 100644
--- a/examples/chaosfs-configmap/pd-configmap.yaml
+++ b/examples/chaosfs-configmap/pd-configmap.yaml
@@ -8,6 +8,9 @@ metadata:
 data:
   chaosfs-pd.yaml: |
     name: chaosfs-pd
+    selector:
+      labelSelectors:
+        "app.kubernetes.io/component": "pd"
     initContainers:
     - name: inject-scripts
       image: pingcap/chaos-scripts:latest
diff --git a/examples/chaosfs-configmap/tikv-configmap.yaml b/examples/chaosfs-configmap/tikv-configmap.yaml
index 814170a1..11d50f97 100644
--- a/examples/chaosfs-configmap/tikv-configmap.yaml
+++ b/examples/chaosfs-configmap/tikv-configmap.yaml
@@ -8,6 +8,9 @@ metadata:
 data:
   chaosfs-tikv.yaml: |
     name: chaosfs-tikv
+    selector:
+      labelSelectors:
+        "app.kubernetes.io/component": "tikv"
     initContainers:
     - name: inject-scripts
       image: pingcap/chaos-scripts:latest
diff --git a/go.mod b/go.mod
index 4432bcf6..2e791c05 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,7 @@
 module github.com/pingcap/chaos-mesh
 
 require (
+	github.com/AlekSi/gocov-xml v0.0.0-20190121064608-3a14fb1c4737 // indirect
 	github.com/Microsoft/go-winio v0.4.14 // indirect
 	github.com/docker/distribution v2.7.1+incompatible // indirect
 	github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
@@ -15,12 +16,14 @@ require (
 	github.com/hanwen/go-fuse v0.0.0-20190111173210-425e8d5301f6
 	github.com/hashicorp/golang-lru v0.5.3 // indirect
 	github.com/jmoiron/sqlx v1.2.0
+	github.com/jstemmer/go-junit-report v0.9.1 // indirect
 	github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9
 	github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
 	github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b // indirect
+	github.com/matm/gocov-html v0.0.0-20191111163307-9ee104d84c82 // indirect
 	github.com/mgechev/revive v0.0.0-20191225235758-99d1f998c7a6 // indirect
 	github.com/morikuni/aec v1.0.0 // indirect
-	github.com/onsi/ginkgo v1.10.3
+	github.com/onsi/ginkgo v1.11.0
 	github.com/onsi/gomega v1.7.0
 	github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
 	github.com/opencontainers/image-spec v1.0.1 // indirect
@@ -32,7 +35,7 @@ require (
 	go.uber.org/zap v1.12.0 // indirect
 	golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
 	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
-	golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4 // indirect
+	golang.org/x/tools v0.0.0-20200102200121-6de373a2766c // indirect
 	google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6 // indirect
 	google.golang.org/grpc v1.24.0
 	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
diff --git a/go.sum b/go.sum
index baf0cbcf..59630742 100644
--- a/go.sum
+++ b/go.sum
@@ -3,6 +3,8 @@ cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+github.com/AlekSi/gocov-xml v0.0.0-20190121064608-3a14fb1c4737 h1:JZHBkt0GhM+ARQykshqpI49yaWCHQbJonH3XpDTwMZQ=
+github.com/AlekSi/gocov-xml v0.0.0-20190121064608-3a14fb1c4737/go.mod h1:w1KSuh2JgIL3nyRiZijboSUwbbxOrTzWwyWVFUHtXBQ=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
@@ -30,6 +32,8 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/axw/gocov v1.0.0 h1:YsqYR66hUmilVr23tu8USgnJIJvnwh3n7j5zRn7x4LU=
+github.com/axw/gocov v1.0.0/go.mod h1:LvQpEYiwwIb2nYkXY2fDWhg9/AsYqkhmrCshjlUJECE=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -82,6 +86,7 @@ github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5I
 github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
 github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
 github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -222,6 +227,8 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
 github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
 github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9 h1:hJix6idebFclqlfZCHE7EUX7uqLCyb70nHNHH1XKGBg=
 github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
 github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
@@ -250,18 +257,25 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/matm/gocov-html v0.0.0-20191111163307-9ee104d84c82 h1:pMb6HhXFlcC2qHIx7Z++2nRhgQ+5kQx8wLbMqBpuU6U=
+github.com/matm/gocov-html v0.0.0-20191111163307-9ee104d84c82/go.mod h1:zha4ZSIA/qviBBKx3j6tJG/Lx6aIdjOXPWuKAcJchQM=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
 github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
 github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
 github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM=
 github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
+github.com/mgechev/revive v0.0.0-20191225235758-99d1f998c7a6 h1:QnoO2nT85bd+AQ8iWyOqbw4dgY3xlG0Cj3EHDKeauGw=
 github.com/mgechev/revive v0.0.0-20191225235758-99d1f998c7a6/go.mod h1:y1Gpz9YT4ZHbLAj5NQVZot0s9C14YsxYlwWpcEfHEG4=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -280,6 +294,7 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
 github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
 github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -289,6 +304,8 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
 github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
 github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -523,6 +540,8 @@ golang.org/x/tools v0.0.0-20191224055732-dd894d0a8a40 h1:UyP2XDSgSc8ldYCxAK735zQ
 golang.org/x/tools v0.0.0-20191224055732-dd894d0a8a40/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4 h1:Toz2IK7k8rbltAXwNAxKcn9OzqyNfMUhUNjz3sL0NMk=
 golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200102200121-6de373a2766c h1:PBxLbymhzlh6kZuAXmeh8JK2tAJR0GM5Q/W71G2QJ40=
+golang.org/x/tools v0.0.0-20200102200121-6de373a2766c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
diff --git a/pkg/utils/selector.go b/pkg/utils/selector.go
index c0ce8462..5d17ada1 100644
--- a/pkg/utils/selector.go
+++ b/pkg/utils/selector.go
@@ -127,6 +127,69 @@ func SelectPods(ctx context.Context, c client.Client, selector v1alpha1.Selector
 	return pods, nil
 }
 
+// CheckPodMeetSelector checks if this pod meets the selection criteria.
+// TODO: support to check fieldsSelector
+func CheckPodMeetSelector(pod v1.Pod, selector v1alpha1.SelectorSpec) (bool, error) {
+	if len(selector.Pods) > 0 {
+		meet := false
+		for ns, names := range selector.Pods {
+			if pod.Namespace != ns {
+				continue
+			}
+
+			for _, name := range names {
+				if pod.Name == name {
+					meet = true
+				}
+			}
+
+			if !meet {
+				return false, nil
+			}
+		}
+	}
+
+	// check pod labels.
+	if pod.Labels == nil {
+		pod.Labels = make(map[string]string)
+	}
+
+	if selector.LabelSelectors == nil {
+		selector.LabelSelectors = make(map[string]string)
+	}
+
+	if len(selector.LabelSelectors) > 0 {
+		ls := labels.SelectorFromSet(selector.LabelSelectors)
+		podLabels := labels.Set(pod.Labels)
+		if len(pod.Labels) == 0 || !ls.Matches(podLabels) {
+			return false, nil
+		}
+	}
+
+	pods := []v1.Pod{pod}
+	namespaceSelector, err := parseSelector(strings.Join(selector.Namespaces, ","))
+	if err != nil {
+		return false, err
+	}
+
+	pods, err = filterByNamespaces(pods, namespaceSelector)
+	if err != nil {
+		return false, err
+	}
+
+	annotationsSelector, err := parseSelector(label.Label(selector.AnnotationSelectors).String())
+	if err != nil {
+		return false, err
+	}
+	pods = filterByAnnotations(pods, annotationsSelector)
+	pods = filterByPhase(pods, v1.PodRunning)
+	if len(pods) > 0 {
+		return true, nil
+	}
+
+	return false, nil
+}
+
 // GeneratePods generate pods according to mode from pod list
 func GeneratePods(pods []v1.Pod, mode v1alpha1.PodMode, value string) ([]v1.Pod, error) {
 	if len(pods) == 0 {
diff --git a/pkg/webhook/config/config.go b/pkg/webhook/config/config.go
index e5e71859..901421df 100644
--- a/pkg/webhook/config/config.go
+++ b/pkg/webhook/config/config.go
@@ -24,6 +24,7 @@ import (
 	"sync"
 
 	"github.com/ghodss/yaml"
+	"github.com/pingcap/chaos-mesh/api/v1alpha1"
 
 	ctrl "sigs.k8s.io/controller-runtime"
 
@@ -70,6 +71,9 @@ type InjectionConfig struct {
 	// Value defines for the Commands for stating container.
 	// +optional
 	PostStart map[string]ExecAction `json:"postStart,omitempty"`
+
+	// Selector is used to select pods that are used to inject sidecar.
+	Selector *v1alpha1.SelectorSpec `json:"selector,omitempty"`
 }
 
 // FullName returns the full identifier of this sidecar - both the Name, and the Version(), formatted like
diff --git a/pkg/webhook/inject/inject.go b/pkg/webhook/inject/inject.go
index 49bb4d88..0e5a9f10 100644
--- a/pkg/webhook/inject/inject.go
+++ b/pkg/webhook/inject/inject.go
@@ -84,6 +84,24 @@ func Inject(res *v1beta1.AdmissionRequest, cli client.Client, cfg *config.Config
 		}
 	}
 
+	if injectionConfig.Selector != nil {
+		meet, err := utils.CheckPodMeetSelector(pod, *injectionConfig.Selector)
+		if err != nil {
+			log.Error(err, "Failed to check pod selector", "namespace", pod.Namespace)
+			return &v1beta1.AdmissionResponse{
+				Allowed: true,
+			}
+		}
+
+		if !meet {
+			log.Info("Skipping injection, this pod does not meet the selection criteria",
+				"namespace", pod.Namespace, "name", pod.Name)
+			return &v1beta1.AdmissionResponse{
+				Allowed: true,
+			}
+		}
+	}
+
 	annotations := map[string]string{cfg.StatusAnnotationKey(): StatusInjected}
 
 	patchBytes, err := createPatch(&pod, injectionConfig, annotations)


Test patch:
diff --git a/pkg/utils/selector_test.go b/pkg/utils/selector_test.go
index 4d930df1..d89a5126 100644
--- a/pkg/utils/selector_test.go
+++ b/pkg/utils/selector_test.go
@@ -92,6 +92,145 @@ func TestSelectPods(t *testing.T) {
 	}
 }
 
+func TestCheckPodMeetSelector(t *testing.T) {
+	g := NewGomegaWithT(t)
+
+	type TestCase struct {
+		name          string
+		selector      v1alpha1.SelectorSpec
+		pod           v1.Pod
+		expectedValue bool
+	}
+
+	tcs := []TestCase{
+		{
+			name: "meet label",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tikv", "ss": "t1"}),
+			selector: v1alpha1.SelectorSpec{
+				LabelSelectors: map[string]string{"app": "tikv"},
+			},
+			expectedValue: true,
+		},
+		{
+			name: "not meet label",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb", "ss": "t1"}),
+			selector: v1alpha1.SelectorSpec{
+				LabelSelectors: map[string]string{"app": "tikv"},
+			},
+			expectedValue: false,
+		},
+		{
+			name: "pod labels is empty",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, nil),
+			selector: v1alpha1.SelectorSpec{
+				LabelSelectors: map[string]string{"app": "tikv"},
+			},
+			expectedValue: false,
+		},
+		{
+			name:          "selector is empty",
+			pod:           newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb"}),
+			selector:      v1alpha1.SelectorSpec{},
+			expectedValue: true,
+		},
+		{
+			name: "meet namespace",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, nil),
+			selector: v1alpha1.SelectorSpec{
+				Namespaces: []string{metav1.NamespaceDefault},
+			},
+			expectedValue: true,
+		},
+		{
+			name: "meet namespace and meet labels",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tikv"}),
+			selector: v1alpha1.SelectorSpec{
+				Namespaces:     []string{metav1.NamespaceDefault},
+				LabelSelectors: map[string]string{"app": "tikv"},
+			},
+			expectedValue: true,
+		},
+		{
+			name: "meet namespace and not meet labels",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Namespaces:     []string{metav1.NamespaceDefault},
+				LabelSelectors: map[string]string{"app": "tikv"},
+			},
+			expectedValue: false,
+		},
+		{
+			name: "meet pods",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Pods: map[string][]string{
+					metav1.NamespaceDefault: []string{"t1"},
+				},
+			},
+			expectedValue: true,
+		},
+		{
+			name: "meet annotation",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, map[string]string{"an": "n1", "an2": "n2"}, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Namespaces: []string{metav1.NamespaceDefault},
+				AnnotationSelectors: map[string]string{
+					"an": "n1",
+				},
+			},
+			expectedValue: true,
+		},
+		{
+			name: "not meet annotation",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, map[string]string{"an": "n1"}, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Namespaces: []string{metav1.NamespaceDefault},
+				AnnotationSelectors: map[string]string{
+					"an": "n2",
+				},
+			},
+			expectedValue: false,
+		},
+		{
+			name: "meet pod selector",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Pods: map[string][]string{
+					metav1.NamespaceDefault: []string{"t1", "t2"},
+				},
+			},
+			expectedValue: true,
+		},
+		{
+			name: "not meet pod selector",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Pods: map[string][]string{
+					metav1.NamespaceDefault: []string{"t2"},
+				},
+			},
+			expectedValue: false,
+		},
+		{
+			name: "meet pod selector and not meet labels",
+			pod:  newPod("t1", v1.PodRunning, metav1.NamespaceDefault, nil, map[string]string{"app": "tidb"}),
+			selector: v1alpha1.SelectorSpec{
+				Pods: map[string][]string{
+					metav1.NamespaceDefault: []string{"t1", "t2"},
+				},
+				LabelSelectors: map[string]string{"app": "tikv"},
+			},
+			expectedValue: false,
+		},
+	}
+
+	for _, tc := range tcs {
+		meet, err := CheckPodMeetSelector(tc.pod, tc.selector)
+		g.Expect(err).ShouldNot(HaveOccurred(), tc.name)
+		g.Expect(meet).To(Equal(tc.expectedValue), tc.name)
+	}
+}
+
 func TestRandomFixedIndexes(t *testing.T) {
 	g := NewGomegaWithT(t)