Repository: spidernet-io/spiderpool (go)

Issue:
add a switch to control creating auto-pool feature based on SpiderSubnet feature
1. allow the user to create SpiderSubnet resource based on a switch `EnabledSpiderSubnet`
2. add a switch to control auto-pool application with `ipam.spidernet.io/subnet` and `ipam.spidernet.io/subnets` annotation. (This switch should based on enable `EnabledSpiderSubnet`)

Pull request:
subnet feature: support to turn on or off the feature of managing automatic-ippool
1. allow the user to create SpiderSubnet resource based on a switch `EnabledSpiderSubnet`
2. add a switch to control auto-pool application with `ipam.spidernet.io/subnet` and `ipam.spidernet.io/subnets` annotation. (This switch should based on enable `EnabledSpiderSubnet`)

Signed-off-by: Icarus9913 [icaruswu66@qq.com](mailto:icaruswu66@qq.com)

**What this PR does / why we need it**:
new feature

**Which issue(s) this PR fixes**:
close #3238 


Patch:
diff --git a/charts/spiderpool/README.md b/charts/spiderpool/README.md
index 0d18b25f4..ba0703e53 100644
--- a/charts/spiderpool/README.md
+++ b/charts/spiderpool/README.md
@@ -127,19 +127,20 @@ helm install spiderpool spiderpool/spiderpool --wait --namespace kube-system \
 
 ### ipam parameters
 
-| Name                                        | Description                                                                                      | Value  |
-| ------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------ |
-| `ipam.enableIPv4`                           | enable ipv4                                                                                      | `true` |
-| `ipam.enableIPv6`                           | enable ipv6                                                                                      | `true` |
-| `ipam.enableStatefulSet`                    | the network mode                                                                                 | `true` |
-| `ipam.enableKubevirtStaticIP`               | the feature to keep kubevirt vm pod static IP                                                    | `true` |
-| `ipam.enableSpiderSubnet`                   | SpiderSubnet feature gate.                                                                       | `true` |
-| `ipam.subnetDefaultFlexibleIPNumber`        | the default flexible IP number of SpiderSubnet feature auto-created IPPools                      | `1`    |
-| `ipam.gc.enabled`                           | enable retrieve IP in spiderippool CR                                                            | `true` |
-| `ipam.gc.gcAll.intervalInSecond`            | the gc all interval duration                                                                     | `600`  |
-| `ipam.gc.statelessPod.zombieOnReadyNode`    | enable reclaim IP for the stateless pod who is over deleting graceful period on a ready node     | `true` |
-| `ipam.gc.statelessPod.zombieOnNotReadyNode` | enable reclaim IP for the stateless pod who is over deleting graceful period on a not-ready node | `true` |
-| `ipam.gc.gcDeletingTimeOutPodDelay`         | the gc delay seconds after the pod times out of deleting graceful period                         | `0`    |
+| Name                                                  | Description                                                                                      | Value  |
+| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------ |
+| `ipam.enableIPv4`                                     | enable ipv4                                                                                      | `true` |
+| `ipam.enableIPv6`                                     | enable ipv6                                                                                      | `true` |
+| `ipam.enableStatefulSet`                              | the network mode                                                                                 | `true` |
+| `ipam.enableKubevirtStaticIP`                         | the feature to keep kubevirt vm pod static IP                                                    | `true` |
+| `ipam.spidersubnet.enable`                            | SpiderSubnet feature.                                                                            | `true` |
+| `ipam.spidersubnet.autoPool.enable`                   | SpiderSubnet Auto IPPool feature.                                                                | `true` |
+| `ipam.spidersubnet.autoPool.defaultRedundantIPNumber` | the default redundant IP number of SpiderSubnet feature auto-created IPPools                     | `1`    |
+| `ipam.gc.enabled`                                     | enable retrieve IP in spiderippool CR                                                            | `true` |
+| `ipam.gc.gcAll.intervalInSecond`                      | the gc all interval duration                                                                     | `600`  |
+| `ipam.gc.statelessPod.zombieOnReadyNode`              | enable reclaim IP for the stateless pod who is over deleting graceful period on a ready node     | `true` |
+| `ipam.gc.statelessPod.zombieOnNotReadyNode`           | enable reclaim IP for the stateless pod who is over deleting graceful period on a not-ready node | `true` |
+| `ipam.gc.gcDeletingTimeOutPodDelay`                   | the gc delay seconds after the pod times out of deleting graceful period                         | `0`    |
 
 ### grafanaDashboard parameters
 
diff --git a/charts/spiderpool/templates/configmap.yaml b/charts/spiderpool/templates/configmap.yaml
index 1b77a6c09..a183bbc31 100644
--- a/charts/spiderpool/templates/configmap.yaml
+++ b/charts/spiderpool/templates/configmap.yaml
@@ -19,9 +19,10 @@ data:
     enableIPv6: {{ .Values.ipam.enableIPv6 }}
     enableStatefulSet: {{ .Values.ipam.enableStatefulSet }}
     enableKubevirtStaticIP: {{ .Values.ipam.enableKubevirtStaticIP }}
-    enableSpiderSubnet: {{ .Values.ipam.enableSpiderSubnet }}
-    {{- if .Values.ipam.enableSpiderSubnet }}
-    clusterSubnetDefaultFlexibleIPNumber: {{ .Values.ipam.subnetDefaultFlexibleIPNumber }}
+    enableSpiderSubnet: {{ .Values.ipam.spidersubnet.enable }}
+    enableAutoPoolForApplication: {{ .Values.ipam.spidersubnet.autoPool.enable }}
+    {{- if and .Values.ipam.spidersubnet.enable .Values.ipam.spidersubnet.autoPool.enable }}
+    clusterSubnetDefaultFlexibleIPNumber: {{ .Values.ipam.spidersubnet.autoPool.defaultRedundantIPNumber }}
     {{- else}}
     clusterSubnetDefaultFlexibleIPNumber: 0
     {{- end }}
diff --git a/charts/spiderpool/templates/pod.yaml b/charts/spiderpool/templates/pod.yaml
index 01aced2ba..0191dcf7a 100644
--- a/charts/spiderpool/templates/pod.yaml
+++ b/charts/spiderpool/templates/pod.yaml
@@ -112,7 +112,7 @@ spec:
       value: {{ toJson .Values.clusterDefaultPool.ipv4IPRanges | quote }}
     - name: SPIDERPOOL_INIT_DEFAULT_IPV4_IPPOOL_GATEWAY
       value: {{ .Values.clusterDefaultPool.ipv4Gateway | quote }}
-    {{- if .Values.ipam.enableSpiderSubnet }}
+    {{- if .Values.ipam.spidersubnet.enable }}
     - name: SPIDERPOOL_INIT_DEFAULT_IPV4_SUBNET_NAME
       value: {{ .Values.clusterDefaultPool.ipv4SubnetName | quote }}
     {{- end }}
@@ -126,7 +126,7 @@ spec:
       value: {{ toJson .Values.clusterDefaultPool.ipv6IPRanges | quote }}
     - name: SPIDERPOOL_INIT_DEFAULT_IPV6_IPPOOL_GATEWAY
       value: {{ .Values.clusterDefaultPool.ipv6Gateway | quote }}
-    {{- if .Values.ipam.enableSpiderSubnet }}
+    {{- if .Values.ipam.spidersubnet.enable }}
     - name: SPIDERPOOL_INIT_DEFAULT_IPV6_SUBNET_NAME
       value: {{ .Values.clusterDefaultPool.ipv6SubnetName | quote }}
     {{- end }}
diff --git a/charts/spiderpool/values.yaml b/charts/spiderpool/values.yaml
index 4ba75a49e..abc0126d5 100644
--- a/charts/spiderpool/values.yaml
+++ b/charts/spiderpool/values.yaml
@@ -53,11 +53,16 @@ ipam:
   ## @param ipam.enableKubevirtStaticIP the feature to keep kubevirt vm pod static IP
   enableKubevirtStaticIP: true
 
-  ## @param ipam.enableSpiderSubnet SpiderSubnet feature gate.
-  enableSpiderSubnet: true
+  spidersubnet:
+    ## @param ipam.spidersubnet.enable SpiderSubnet feature.
+    enable: true
 
-  ## @param ipam.subnetDefaultFlexibleIPNumber the default flexible IP number of SpiderSubnet feature auto-created IPPools
-  subnetDefaultFlexibleIPNumber: 1
+    autoPool:
+      ## @param ipam.spidersubnet.autoPool.enable SpiderSubnet Auto IPPool feature.
+      enable: true
+
+      ## @param ipam.spidersubnet.autoPool.defaultRedundantIPNumber the default redundant IP number of SpiderSubnet feature auto-created IPPools
+      defaultRedundantIPNumber: 1
 
   gc:
     ## @param ipam.gc.enabled enable retrieve IP in spiderippool CR
diff --git a/cmd/spiderpool-agent/cmd/config.go b/cmd/spiderpool-agent/cmd/config.go
index 90d71c470..6270875a2 100644
--- a/cmd/spiderpool-agent/cmd/config.go
+++ b/cmd/spiderpool-agent/cmd/config.go
@@ -29,6 +29,7 @@ import (
 	"github.com/spidernet-io/spiderpool/pkg/reservedipmanager"
 	"github.com/spidernet-io/spiderpool/pkg/statefulsetmanager"
 	"github.com/spidernet-io/spiderpool/pkg/subnetmanager"
+	spiderpooltypes "github.com/spidernet-io/spiderpool/pkg/types"
 	"github.com/spidernet-io/spiderpool/pkg/workloadendpointmanager"
 )
 
@@ -97,13 +98,7 @@ type Config struct {
 	MultusClusterNetwork string
 
 	// configmap
-	IpamUnixSocketPath                string `yaml:"ipamUnixSocketPath"`
-	EnableIPv4                        bool   `yaml:"enableIPv4"`
-	EnableIPv6                        bool   `yaml:"enableIPv6"`
-	EnableStatefulSet                 bool   `yaml:"enableStatefulSet"`
-	EnableKubevirtStaticIP            bool   `yaml:"enableKubevirtStaticIP"`
-	EnableSpiderSubnet                bool   `yaml:"enableSpiderSubnet"`
-	ClusterSubnetDefaultFlexibleIPNum int    `yaml:"clusterSubnetDefaultFlexibleIPNumber"`
+	spiderpooltypes.SpiderpoolConfigmapConfig
 }
 
 type AgentContext struct {
@@ -194,7 +189,7 @@ func (ac *AgentContext) LoadConfigmap() error {
 		return fmt.Errorf("failed to read configmap file, error: %v", err)
 	}
 
-	err = yaml.Unmarshal(configmapBytes, &ac.Cfg)
+	err = yaml.Unmarshal(configmapBytes, &ac.Cfg.SpiderpoolConfigmapConfig)
 	if nil != err {
 		return fmt.Errorf("failed to parse configmap, error: %v", err)
 	}
diff --git a/cmd/spiderpool-agent/cmd/daemon.go b/cmd/spiderpool-agent/cmd/daemon.go
index c61c8a469..f1c7aa98b 100644
--- a/cmd/spiderpool-agent/cmd/daemon.go
+++ b/cmd/spiderpool-agent/cmd/daemon.go
@@ -145,6 +145,7 @@ func DaemonMain() {
 		EnableIPv4:                           agentContext.Cfg.EnableIPv4,
 		EnableIPv6:                           agentContext.Cfg.EnableIPv6,
 		EnableSpiderSubnet:                   agentContext.Cfg.EnableSpiderSubnet,
+		EnableAutoPoolForApplication:         agentContext.Cfg.EnableAutoPoolForApplication,
 		EnableStatefulSet:                    agentContext.Cfg.EnableStatefulSet,
 		EnableKubevirtStaticIP:               agentContext.Cfg.EnableKubevirtStaticIP,
 		EnableReleaseConflictIPsForStateless: agentContext.Cfg.EnableReleaseConflictIPsForStateless,
diff --git a/cmd/spiderpool-controller/cmd/config.go b/cmd/spiderpool-controller/cmd/config.go
index 8989f2dfd..c6475eb63 100644
--- a/cmd/spiderpool-controller/cmd/config.go
+++ b/cmd/spiderpool-controller/cmd/config.go
@@ -30,6 +30,7 @@ import (
 	"github.com/spidernet-io/spiderpool/pkg/reservedipmanager"
 	"github.com/spidernet-io/spiderpool/pkg/statefulsetmanager"
 	"github.com/spidernet-io/spiderpool/pkg/subnetmanager"
+	spiderpooltypes "github.com/spidernet-io/spiderpool/pkg/types"
 	"github.com/spidernet-io/spiderpool/pkg/workloadendpointmanager"
 )
 
@@ -150,20 +151,14 @@ type Config struct {
 	WorkQueueMaxRetries              int
 	WorkQueueRequeueDelayDuration    int
 
+	EnableCoordinator               bool
 	CoordinatorInformerResyncPeriod int
 
 	EnableMultusConfig               bool
 	MultusConfigInformerResyncPeriod int
 
-	EnableCoordinator bool
-
 	// configmap
-	EnableIPv4                        bool `yaml:"enableIPv4"`
-	EnableIPv6                        bool `yaml:"enableIPv6"`
-	EnableStatefulSet                 bool `yaml:"enableStatefulSet"`
-	EnableKubevirtStaticIP            bool `yaml:"enableKubevirtStaticIP"`
-	EnableSpiderSubnet                bool `yaml:"enableSpiderSubnet"`
-	ClusterSubnetDefaultFlexibleIPNum int  `yaml:"clusterSubnetDefaultFlexibleIPNumber"`
+	spiderpooltypes.SpiderpoolConfigmapConfig
 }
 
 type ControllerContext struct {
@@ -266,7 +261,7 @@ func (cc *ControllerContext) LoadConfigmap() error {
 		return fmt.Errorf("failed to read configmap file, error: %v", err)
 	}
 
-	err = yaml.Unmarshal(configmapBytes, &cc.Cfg)
+	err = yaml.Unmarshal(configmapBytes, &cc.Cfg.SpiderpoolConfigmapConfig)
 	if nil != err {
 		return fmt.Errorf("failed to parse configmap, error: %v", err)
 	}
diff --git a/cmd/spiderpool-controller/cmd/daemon.go b/cmd/spiderpool-controller/cmd/daemon.go
index df6a2a74e..b01dc387a 100644
--- a/cmd/spiderpool-controller/cmd/daemon.go
+++ b/cmd/spiderpool-controller/cmd/daemon.go
@@ -365,8 +365,8 @@ func initControllerServiceManagers(ctx context.Context) {
 			logger.Fatal(err.Error())
 		}
 
-		logger.Sugar().Debugf("Begin to initialize cluster Subnet default flexible IP number to %d", controllerContext.Cfg.ClusterSubnetDefaultFlexibleIPNum)
-		*applicationinformers.ClusterSubnetDefaultFlexibleIPNumber = controllerContext.Cfg.ClusterSubnetDefaultFlexibleIPNum
+		logger.Sugar().Debugf("Begin to initialize cluster Subnet AutoPool default redimdamt IP number to %d", controllerContext.Cfg.ClusterSubnetAutoPoolDefaultRedundantIPNumber)
+		*applicationinformers.ClusterSubnetAutoPoolDefaultRedundantIPNumber = controllerContext.Cfg.ClusterSubnetAutoPoolDefaultRedundantIPNumber
 	} else {
 		logger.Info("Feature SpiderSubnet is disabled")
 	}
@@ -488,6 +488,7 @@ func setupInformers(k8sClient *kubernetes.Clientset) {
 		ippoolmanager.IPPoolControllerConfig{
 			IPPoolControllerWorkers:       controllerContext.Cfg.IPPoolInformerWorkers,
 			EnableSpiderSubnet:            controllerContext.Cfg.EnableSpiderSubnet,
+			EnableAutoPoolForApplication:  controllerContext.Cfg.EnableAutoPoolForApplication,
 			LeaderRetryElectGap:           time.Duration(controllerContext.Cfg.LeaseRetryGap) * time.Second,
 			MaxWorkqueueLength:            controllerContext.Cfg.IPPoolInformerMaxWorkQueueLength,
 			WorkQueueRequeueDelayDuration: time.Duration(controllerContext.Cfg.WorkQueueRequeueDelayDuration) * time.Second,
@@ -516,27 +517,31 @@ func setupInformers(k8sClient *kubernetes.Clientset) {
 			logger.Fatal(err.Error())
 		}
 
-		logger.Info("Begin to set up auto-created IPPool controller")
-		subnetAppController, err := applicationcontroller.NewSubnetAppController(
-			controllerContext.CRDManager.GetClient(),
-			controllerContext.CRDManager.GetAPIReader(),
-			controllerContext.SubnetManager,
-			applicationcontroller.SubnetAppControllerConfig{
-				EnableIPv4:                    controllerContext.Cfg.EnableIPv4,
-				EnableIPv6:                    controllerContext.Cfg.EnableIPv6,
-				AppControllerWorkers:          controllerContext.Cfg.SubnetAppControllerWorkers,
-				MaxWorkqueueLength:            controllerContext.Cfg.SubnetInformerMaxWorkqueueLength,
-				WorkQueueMaxRetries:           controllerContext.Cfg.WorkQueueMaxRetries,
-				WorkQueueRequeueDelayDuration: time.Duration(controllerContext.Cfg.WorkQueueRequeueDelayDuration) * time.Second,
-				LeaderRetryElectGap:           time.Duration(controllerContext.Cfg.LeaseRetryGap) * time.Second,
-			})
-		if nil != err {
-			logger.Fatal(err.Error())
-		}
+		if controllerContext.Cfg.EnableAutoPoolForApplication {
+			logger.Info("Begin to set up auto-created IPPool controller")
+			subnetAppController, err := applicationcontroller.NewSubnetAppController(
+				controllerContext.CRDManager.GetClient(),
+				controllerContext.CRDManager.GetAPIReader(),
+				controllerContext.SubnetManager,
+				applicationcontroller.SubnetAppControllerConfig{
+					EnableIPv4:                    controllerContext.Cfg.EnableIPv4,
+					EnableIPv6:                    controllerContext.Cfg.EnableIPv6,
+					AppControllerWorkers:          controllerContext.Cfg.SubnetAppControllerWorkers,
+					MaxWorkqueueLength:            controllerContext.Cfg.SubnetInformerMaxWorkqueueLength,
+					WorkQueueMaxRetries:           controllerContext.Cfg.WorkQueueMaxRetries,
+					WorkQueueRequeueDelayDuration: time.Duration(controllerContext.Cfg.WorkQueueRequeueDelayDuration) * time.Second,
+					LeaderRetryElectGap:           time.Duration(controllerContext.Cfg.LeaseRetryGap) * time.Second,
+				})
+			if nil != err {
+				logger.Fatal(err.Error())
+			}
 
-		err = subnetAppController.SetupInformer(controllerContext.InnerCtx, controllerContext.ClientSet, controllerContext.Leader)
-		if nil != err {
-			logger.Fatal(err.Error())
+			err = subnetAppController.SetupInformer(controllerContext.InnerCtx, controllerContext.ClientSet, controllerContext.Leader)
+			if nil != err {
+				logger.Fatal(err.Error())
+			}
+		} else {
+			logger.Sugar().Info("SpiderSubnet AutoPool feature is off")
 		}
 	}
 
diff --git a/docs/usage/install/upgrade-zh_CN.md b/docs/usage/install/upgrade-zh_CN.md
index a5bb6e529..06c7a69c0 100644
--- a/docs/usage/install/upgrade-zh_CN.md
+++ b/docs/usage/install/upgrade-zh_CN.md
@@ -51,13 +51,13 @@
 您可以通过 `--set` 在升级时去更新 Spiderpool 配置，可用的 values 参数，请查看 [values](https://github.com/spidernet-io/spiderpool/tree/main/charts/spiderpool/README.md) 说明文档。 以下示例展示了如何开启 Spiderpool 的 [SpiderSubnet 功能](../spider-subnet-zh_CN.md)
 
 ```bash
-helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.enableSpiderSubnet=true
+helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.spidersubnet.enable=true
 ```
 
 同时您也可以使用 `--reuse-values` 重用上一个 release 的值并合并来自命令行的任何覆盖。但仅当 Spiderpool chart 版本保持不变时，才可以安全地使用 `--reuse-values` 标志，例如，当使用 helm upgrade 来更改 Spiderpool 配置而不升级 Spiderpool 组件。 `--reuse-values` 使用，参考如下示例：
 
 ```bash
-helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.enableSpiderSubnet=true --reuse-values
+helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.spidersubnet.enable=true --reuse-values
 ```
 
 相反，如果 Spiderpool chart 版本发生了变化，您想重用现有安装中的值，请将旧值保存在值文件中，检查该文件中是否有任何重命名或弃用的值，然后将其传递给 helm upgrade 命令，您可以使用以下命令检索并保存现有安装中的值：
diff --git a/docs/usage/install/upgrade.md b/docs/usage/install/upgrade.md
index 1d492a377..c22f7f17d 100644
--- a/docs/usage/install/upgrade.md
+++ b/docs/usage/install/upgrade.md
@@ -51,13 +51,13 @@ It is recommended to always upgrade to the latest and maintained patch version o
 You can use `--set` to update the Spiderpool configuration when upgrading. For available values parameters, please see the [values](https://github.com/spidernet-io/spiderpool/tree/main/charts/spiderpool/README.md) documentation. The following example shows how to enable Spiderpool's [SpiderSubnet function](../spider-subnet.md)
 
 ```bash
-helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.enableSpiderSubnet=true
+helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.spidersubnet.enable=true
 ```
 
 You can also use `--reuse-values` to reuse the values from the previous release and merge any overrides from the command line. However, it is only safe to use the `--reuse-values` flag if the Spiderpool chart version remains unchanged, e.g. when using helm upgrade to change the Spiderpool configuration without upgrading the Spiderpool components. For `--reuse-values` usage, see the following example:
 
 ```bash
-helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.enableSpiderSubnet=true --reuse-values
+helm upgrade spiderpool spiderpool/spiderpool -n kube-system --version [upgraded-version] --set ipam.spidersubnet.enable=true --reuse-values
 ```
 
 Conversely, if the Spiderpool chart version has changed and you want to reuse the values from the existing installation, save the old values in a values file, check that file for any renamed or deprecated values, and pass it to helm upgrade command, you can retrieve and save values from existing installations using.
diff --git a/docs/usage/spider-subnet-zh_CN.md b/docs/usage/spider-subnet-zh_CN.md
index 35e4d00dc..0d9d39e8f 100644
--- a/docs/usage/spider-subnet-zh_CN.md
+++ b/docs/usage/spider-subnet-zh_CN.md
@@ -32,7 +32,7 @@ SpiderSubnet 功能还支持众多的控制器，如：ReplicaSet、Deployment
 
 ### 安装 Spiderpool
 
-可参考 [安装](./readme-zh_CN.md) 安装 Spiderpool. 其中，务必确保 helm 安装选项 `ipam.enableSpiderSubnet=true`
+可参考 [安装教程](./readme-zh_CN.md) 来安装 Spiderpool. 请务必确保 helm 安装选项 `--ipam.spidersubnet.enable=true --ipam.spidersubnet.autoPool.enable=true`. 其中，`ipam.spidersubnet.autoPool.enable` 提供 `自动创建 IPPool` 的能力。
 
 ### 安装 CNI 配置
 
diff --git a/docs/usage/spider-subnet.md b/docs/usage/spider-subnet.md
index c44b8207e..2dafca2cd 100644
--- a/docs/usage/spider-subnet.md
+++ b/docs/usage/spider-subnet.md
@@ -33,7 +33,7 @@ This feature does not support the bare Pod.
 
 ### Install Spiderpool
 
-Refer to [Installation](./readme.md) to install Spiderpool. And make sure that the helm installs the option `ipam.enableSpiderSubnet=true`.
+Refer to [Installation](./readme.md) to install Spiderpool. And make sure that the helm installs the option `--ipam.spidersubnet.enable=true --ipam.spidersubnet.autoPool.enable=true`. The `ipam.spidersubnet.autoPool.enable` provide the `Automatically create IPPool` ability.
 
 ### Install CNI
 
diff --git a/pkg/applicationcontroller/applicationinformers/utils.go b/pkg/applicationcontroller/applicationinformers/utils.go
index 4e2c798a0..3337cb4c4 100644
--- a/pkg/applicationcontroller/applicationinformers/utils.go
+++ b/pkg/applicationcontroller/applicationinformers/utils.go
@@ -34,8 +34,8 @@ import (
 	"github.com/spidernet-io/spiderpool/pkg/types"
 )
 
-// ClusterSubnetDefaultFlexibleIPNumber is a singleton recording cluster default Subnet flexible IP number.
-var ClusterSubnetDefaultFlexibleIPNumber = new(int)
+// ClusterSubnetAutoPoolDefaultRedundantIPNumber is a singleton recording cluster subnet AutoPool default redundant IP number.
+var ClusterSubnetAutoPoolDefaultRedundantIPNumber = new(int)
 
 var errInvalidInput = func(str string) error {
 	return fmt.Errorf("invalid input '%s'", str)
@@ -229,8 +229,8 @@ func GetSubnetAnnoConfig(podAnnotations map[string]string, log *zap.Logger) (*ty
 			subnetAnnoConfig.AssignIPNum = ipNum
 		}
 	} else {
-		log.Sugar().Debugf("no specified IPPool IP number, default to use cluster default subnet flexible IP number: %d", *ClusterSubnetDefaultFlexibleIPNumber)
-		subnetAnnoConfig.FlexibleIPNum = ptr.To(*ClusterSubnetDefaultFlexibleIPNumber)
+		log.Sugar().Debugf("no specified IPPool IP number, default to use cluster subnet AutoPool default redundant IP number: %d", *ClusterSubnetAutoPoolDefaultRedundantIPNumber)
+		subnetAnnoConfig.FlexibleIPNum = ptr.To(*ClusterSubnetAutoPoolDefaultRedundantIPNumber)
 	}
 
 	// annotation: "ipam.spidernet.io/reclaim-ippool", reclaim IPPool or not (default true)
@@ -519,3 +519,14 @@ func AutoPoolIPVersionLabelValue(ipVersion types.IPVersion) string {
 
 	return constant.LabelValueIPVersionV6
 }
+
+// HasSubnetsAnnotation checks the given annotation whether contains 'ipam.spidernet.io/subnets' or 'ipam.spidernet.io/subnet' key-value pair
+func HasSubnetsAnnotation(anno map[string]string) bool {
+	_, ok := anno[constant.AnnoSpiderSubnets]
+	if ok {
+		return true
+	}
+
+	_, ok = anno[constant.AnnoSpiderSubnet]
+	return ok
+}
diff --git a/pkg/ipam/config.go b/pkg/ipam/config.go
index 02d950589..5bd07ca6d 100644
--- a/pkg/ipam/config.go
+++ b/pkg/ipam/config.go
@@ -19,6 +19,8 @@ type IPAMConfig struct {
 	EnableIPv6 bool
 
 	EnableSpiderSubnet                   bool
+	EnableAutoPoolForApplication         bool
+	EnableSpiderSubnetAutoPool           bool
 	EnableStatefulSet                    bool
 	EnableKubevirtStaticIP               bool
 	EnableReleaseConflictIPsForStateless bool
diff --git a/pkg/ipam/pool_selections.go b/pkg/ipam/pool_selections.go
index 741b611df..21cc2bbc9 100644
--- a/pkg/ipam/pool_selections.go
+++ b/pkg/ipam/pool_selections.go
@@ -30,12 +30,19 @@ func (i *ipam) getPoolCandidates(ctx context.Context, addArgs *models.IpamAddArg
 	// If feature SpiderSubnet is enabled, select IPPool candidates through the
 	// Pod annotations "ipam.spidernet.io/subnet" or "ipam.spidernet.io/subnets". (expect orphan Pod controller)
 	if i.config.EnableSpiderSubnet {
-		fromSubnet, err := i.getPoolFromSubnetAnno(ctx, pod, *addArgs.IfName, addArgs.CleanGateway, podController)
-		if nil != err {
-			return nil, fmt.Errorf("failed to get IPPool candidates from Subnet: %v", err)
-		}
-		if fromSubnet != nil {
-			return ToBeAllocateds{fromSubnet}, nil
+		if i.config.EnableAutoPoolForApplication {
+			fromSubnet, err := i.getPoolFromSubnetAnno(ctx, pod, *addArgs.IfName, addArgs.CleanGateway, podController)
+			if nil != err {
+				return nil, fmt.Errorf("failed to get IPPool candidates from Subnet: %v", err)
+			}
+			if fromSubnet != nil {
+				return ToBeAllocateds{fromSubnet}, nil
+			}
+		} else {
+			hasSubnetsAnnotation := applicationinformers.HasSubnetsAnnotation(pod.Annotations)
+			if hasSubnetsAnnotation {
+				return nil, fmt.Errorf("it's invalid to use '%s' or '%s' annotation when Auto-Pool feature is disabled", constant.AnnoSpiderSubnets, constant.AnnoSpiderSubnet)
+			}
 		}
 	}
 
diff --git a/pkg/ippoolmanager/ippool_informer.go b/pkg/ippoolmanager/ippool_informer.go
index 61b7a2201..09ec4ad5f 100644
--- a/pkg/ippoolmanager/ippool_informer.go
+++ b/pkg/ippoolmanager/ippool_informer.go
@@ -50,6 +50,7 @@ type IPPoolController struct {
 type IPPoolControllerConfig struct {
 	IPPoolControllerWorkers       int
 	EnableSpiderSubnet            bool
+	EnableAutoPoolForApplication  bool
 	MaxWorkqueueLength            int
 	WorkQueueMaxRetries           int
 	LeaderRetryElectGap           time.Duration
@@ -267,7 +268,7 @@ func (ic *IPPoolController) processNextWorkItem() bool {
 
 func (ic *IPPoolController) handleIPPool(ctx context.Context, pool *spiderpoolv2beta1.SpiderIPPool) (err error) {
 	// checkout the Auto-created IPPools whether need to scale or clean up legacies
-	if ic.EnableSpiderSubnet && IsAutoCreatedIPPool(pool) {
+	if ic.EnableSpiderSubnet && ic.EnableAutoPoolForApplication && IsAutoCreatedIPPool(pool) {
 		err := ic.cleanAutoIPPoolLegacy(ctx, pool)
 		if nil != err {
 			return err
diff --git a/pkg/types/k8s.go b/pkg/types/k8s.go
index 1c9804611..2caa44659 100644
--- a/pkg/types/k8s.go
+++ b/pkg/types/k8s.go
@@ -107,3 +107,14 @@ type AutoPoolProperty struct {
 	// AnnoPoolIPNumberVal serves for AutoPool annotation to explain whether it is IP number flexible or fixed.
 	AnnoPoolIPNumberVal string
 }
+
+type SpiderpoolConfigmapConfig struct {
+	IpamUnixSocketPath                            string `yaml:"ipamUnixSocketPath"`
+	EnableIPv4                                    bool   `yaml:"enableIPv4"`
+	EnableIPv6                                    bool   `yaml:"enableIPv6"`
+	EnableStatefulSet                             bool   `yaml:"enableStatefulSet"`
+	EnableKubevirtStaticIP                        bool   `yaml:"enableKubevirtStaticIP"`
+	EnableSpiderSubnet                            bool   `yaml:"enableSpiderSubnet"`
+	EnableAutoPoolForApplication                  bool   `yaml:"enableAutoPoolForApplication"`
+	ClusterSubnetAutoPoolDefaultRedundantIPNumber int    `yaml:"clusterSubnetAutoPoolDefaultRedundantIPNumber"`
+}


Test patch:
diff --git a/pkg/applicationcontroller/applicationinformers/utils_test.go b/pkg/applicationcontroller/applicationinformers/utils_test.go
index 0ef533f35..e62544b73 100644
--- a/pkg/applicationcontroller/applicationinformers/utils_test.go
+++ b/pkg/applicationcontroller/applicationinformers/utils_test.go
@@ -631,4 +631,28 @@ var _ = Describe("Utils", func() {
 			Expect(labelValue).To(Equal(constant.LabelValueIPVersionV6))
 		})
 	})
+
+	Context("HasSubnetsAnnotation", func() {
+		var anno map[string]string
+		BeforeEach(func() {
+			anno = make(map[string]string)
+		})
+
+		It("has 'ipam.spidernet.io/subnets' annotation", func() {
+			anno[constant.AnnoSpiderSubnets] = "subnet-demo1"
+			hasSubnetsAnnotation := HasSubnetsAnnotation(anno)
+			Expect(hasSubnetsAnnotation).To(BeTrue())
+		})
+
+		It("has 'ipam.spidernet.io/subnet' annotation", func() {
+			anno[constant.AnnoSpiderSubnet] = "subnet-demo2"
+			hasSubnetsAnnotation := HasSubnetsAnnotation(anno)
+			Expect(hasSubnetsAnnotation).To(BeTrue())
+		})
+
+		It("no subnets/subnet annotation", func() {
+			hasSubnetsAnnotation := HasSubnetsAnnotation(anno)
+			Expect(hasSubnetsAnnotation).To(BeFalse())
+		})
+	})
 })
diff --git a/test/Makefile b/test/Makefile
index d3e27f568..1dc9c46d1 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -248,9 +248,9 @@ setup_spiderpool:
 			HELM_OPTION+=" --set multus.enableMultusConfig=false " ; \
 		fi ; \
 		if [ "$(E2E_SPIDERPOOL_ENABLE_SUBNET)" == "true" ] ; then \
-		    HELM_OPTION+=" --set ipam.enableSpiderSubnet=true " ; \
+		    HELM_OPTION+=" --set ipam.spidersubnet.enable=true " ; \
 		else \
-		    HELM_OPTION+=" --set ipam.enableSpiderSubnet=false " ; \
+		    HELM_OPTION+=" --set ipam.spidersubnet.enable=false " ; \
 		fi ; \
 		if [ "$(INSTALL_SRIOV)" == "true" ] ; then \
 			HELM_OPTION+=" --set sriov.install=true " ; \
diff --git a/test/doc/subnet.md b/test/doc/subnet.md
index 5d55dde90..97df0c1bb 100644
--- a/test/doc/subnet.md
+++ b/test/doc/subnet.md
@@ -25,3 +25,4 @@
 | I00021  | Pod works correctly when multiple NICs are specified by annotations for applications of the same name                               | p3       |       | done    |       |
 | I00022  | Dirty data in the subnet should be recycled.                                                                                        | p3       |       | done    |       |
 | I00023  | SpiderSubnet feature doesn't support orphan pod                                                                                     | p2       |       | done    |       |
+| I00024  | The Pod would not be setup and no auto Pools created when the SpiderSubnet AutoPool feature is disabled                             | p2       |       | done    |       |
diff --git a/test/e2e/subnet/subnet_test.go b/test/e2e/subnet/subnet_test.go
index a1fa85ba6..a99356ff9 100644
--- a/test/e2e/subnet/subnet_test.go
+++ b/test/e2e/subnet/subnet_test.go
@@ -15,6 +15,7 @@ import (
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	"github.com/spidernet-io/e2eframework/tools"
+	"gopkg.in/yaml.v2"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	api_errors "k8s.io/apimachinery/pkg/api/errors"
@@ -22,6 +23,7 @@ import (
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
+	"github.com/spidernet-io/spiderpool/pkg/applicationcontroller/applicationinformers"
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	"github.com/spidernet-io/spiderpool/pkg/ip"
 	spiderpool "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v2beta1"
@@ -1994,4 +1996,93 @@ var _ = Describe("test subnet", Label("subnet"), func() {
 		_, err = frame.WaitPodStarted(podName, namespace, ctx)
 		Expect(err).To(HaveOccurred())
 	})
+
+	Context("The Pod would not be setup and no auto Pools created when the SpiderSubnet AutoPool feature is disabled", Label("I00024"), Serial, func() {
+		const configYamlStr = "conf.yml"
+		BeforeEach(func() {
+			// make sure configmap 'enableAutoPoolForApplication' is 'false'
+			configmap, err := frame.GetConfigmap(common.SpiderPoolConfigmapName, common.SpiderPoolConfigmapNameSpace)
+			Expect(err).NotTo(HaveOccurred())
+			var cmConfig types.SpiderpoolConfigmapConfig
+			configStr, ok := configmap.Data[configYamlStr]
+			Expect(ok).To(BeTrue())
+			err = yaml.Unmarshal([]byte(configStr), &cmConfig)
+			Expect(err).NotTo(HaveOccurred())
+
+			if cmConfig.EnableAutoPoolForApplication == true {
+				GinkgoWriter.Printf("try to update ConfigMap spiderpool-conf EnableAutoPoolForApplication to be false")
+				cmConfig.EnableAutoPoolForApplication = false
+				marshal, err := yaml.Marshal(cmConfig)
+				Expect(err).NotTo(HaveOccurred())
+
+				configmap.Data[configYamlStr] = string(marshal)
+				err = frame.KClient.Update(context.TODO(), configmap)
+				Expect(err).NotTo(HaveOccurred())
+			}
+
+			DeferCleanup(func() {
+				// change the configmap 'enableAutoPoolForApplication' back to be 'true'
+				configmap, err := frame.GetConfigmap(common.SpiderPoolConfigmapName, common.SpiderPoolConfigmapNameSpace)
+				Expect(err).NotTo(HaveOccurred())
+				var cmConfig types.SpiderpoolConfigmapConfig
+				configStr, ok := configmap.Data[configYamlStr]
+				Expect(ok).To(BeTrue())
+				err = yaml.Unmarshal([]byte(configStr), &cmConfig)
+				Expect(err).NotTo(HaveOccurred())
+
+				if cmConfig.EnableAutoPoolForApplication == false {
+					GinkgoWriter.Printf("try to update ConfigMap spiderpool-conf EnableAutoPoolForApplication to be true in the end")
+					cmConfig.EnableAutoPoolForApplication = true
+					marshal, err := yaml.Marshal(cmConfig)
+					Expect(err).NotTo(HaveOccurred())
+
+					configmap.Data[configYamlStr] = string(marshal)
+					err = frame.KClient.Update(context.TODO(), configmap)
+					Expect(err).NotTo(HaveOccurred())
+				}
+			})
+		})
+
+		It("The Pod would not start up", func() {
+			depName := "dep-" + tools.RandomName()
+			GinkgoWriter.Printf("Generate a new deploy object %v/%v. \n", namespace, depName)
+			subnetAnno := types.AnnoSubnetItem{}
+			if frame.Info.IpV4Enabled {
+				subnetAnno.IPv4 = []string{v4SubnetName}
+			}
+			if frame.Info.IpV6Enabled {
+				subnetAnno.IPv6 = []string{v6SubnetName}
+			}
+			subnetAnnoMarshal, err := json.Marshal(subnetAnno)
+			Expect(err).NotTo(HaveOccurred())
+
+			GinkgoWriter.Println("Using the annotation 'ipam.spidernet.io/subnet' to specify auto pool for application")
+			newDeployObject := common.GenerateExampleDeploymentYaml(depName, namespace, 1)
+			newDeployObject.Spec.Template.Annotations = map[string]string{
+				constant.AnnoSpiderSubnet: string(subnetAnnoMarshal),
+			}
+
+			ctx, cancel := context.WithTimeout(context.Background(), common.PodStartTimeout)
+			defer cancel()
+			podList, err := common.CreateDeployUntilExpectedReplicas(frame, newDeployObject, ctx)
+			Expect(err).NotTo(HaveOccurred())
+
+			// Get the Pod creation failure Event
+			GinkgoWriter.Println("The Pod would not start up due to AutoPool for application feature is disabled")
+			for _, pod := range podList.Items {
+				Expect(frame.WaitExceptEventOccurred(ctx, common.OwnerPod, pod.Name, pod.Namespace, common.CNIFailedToSetUpNetwork)).To(Succeed())
+			}
+
+			// make sure no auto ippools created
+			autoPoolMatchLabels := client.MatchingLabels{
+				constant.LabelIPPoolOwnerApplicationGV:        applicationinformers.ApplicationLabelGV(appsv1.SchemeGroupVersion.String()),
+				constant.LabelIPPoolOwnerApplicationKind:      constant.KindDeployment,
+				constant.LabelIPPoolOwnerApplicationNamespace: namespace,
+				constant.LabelIPPoolOwnerApplicationName:      newDeployObject.Name,
+			}
+			poolList, err := common.GetAllIppool(frame, autoPoolMatchLabels)
+			Expect(err).NotTo(HaveOccurred())
+			Expect(poolList.Items).To(HaveLen(0))
+		})
+	})
 })