Repository: spidernet-io/spiderpool
Pull request #755 (2022-09-23 05:27:10)

Refactor configuration related code
Signed-off-by: iiiceoo <ziqian.xue@daocloud.io>


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=spidernet-io_spiderpool&pullRequest=755)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755) No Coverage information  
[![1.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '1.0%')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list) [1.0% Duplication](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list)


codecov[bot]: # [Codecov](https://codecov.io/gh/spidernet-io/spiderpool/pull/755?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io) Report
> Merging [#755](https://codecov.io/gh/spidernet-io/spiderpool/pull/755?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io) (851675c) into [main](https://codecov.io/gh/spidernet-io/spiderpool/commit/ffcdf94a13b298d99245e8efc1728338763ce56b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io) (ffcdf94) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/spidernet-io/spiderpool/pull/755/graphs/tree.svg?width=650&height=150&src=pr&token=YKXY2E4Q8G&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io)](https://codecov.io/gh/spidernet-io/spiderpool/pull/755?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io)

```diff
@@           Coverage Diff           @@
##             main     #755   +/-   ##
=======================================
  Coverage   80.72%   80.72%           
=======================================
  Files           7        7           
  Lines         581      581           
=======================================
  Hits          469      469           
  Misses         93       93           
  Partials       19       19           
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `80.72% <100.00%> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/spidernet-io/spiderpool/pull/755?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io) | Coverage Δ | |
|---|---|---|
| [pkg/limiter/queue.go](https://codecov.io/gh/spidernet-io/spiderpool/pull/755/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=spidernet-io#diff-cGtnL2xpbWl0ZXIvcXVldWUuZ28=) | `97.22% <100.00%> (ø)` | |

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=spidernet-io_spiderpool&pullRequest=755)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755) No Coverage information  
[![1.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '1.0%')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list) [1.0% Duplication](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=spidernet-io_spiderpool&pullRequest=755)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755) No Coverage information  
[![0.9%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.9%')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list) [0.9% Duplication](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=spidernet-io_spiderpool&pullRequest=755)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=755&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755) No Coverage information  
[![0.9%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.9%')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list) [0.9% Duplication](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=755&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/cmd/spiderpool-agent/cmd/config.go b/cmd/spiderpool-agent/cmd/config.go
index 473e96e48..8e9ec36fa 100644
--- a/cmd/spiderpool-agent/cmd/config.go
+++ b/cmd/spiderpool-agent/cmd/config.go
@@ -19,7 +19,7 @@ import (
 	"github.com/spidernet-io/spiderpool/api/v1/agent/server"
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	"github.com/spidernet-io/spiderpool/pkg/ipam"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
+	ippoolmanagertypes "github.com/spidernet-io/spiderpool/pkg/ippoolmanager/types"
 	"github.com/spidernet-io/spiderpool/pkg/namespacemanager"
 	"github.com/spidernet-io/spiderpool/pkg/nodemanager"
 	"github.com/spidernet-io/spiderpool/pkg/podmanager"
@@ -102,7 +102,8 @@ type AgentContext struct {
 
 	// manager
 	IPAM          ipam.IPAM
-	IPPoolManager ippoolmanager.IPPoolManager
+	CRDManager    ctrl.Manager
+	IPPoolManager ippoolmanagertypes.IPPoolManager
 	WEManager     workloadendpointmanager.WorkloadEndpointManager
 	RIPManager    reservedipmanager.ReservedIPManager
 	NodeManager   nodemanager.NodeManager
@@ -111,7 +112,6 @@ type AgentContext struct {
 	StsManager    statefulsetmanager.StatefulSetManager
 
 	// handler
-	CRDManager        ctrl.Manager
 	HttpServer        *server.Server
 	UnixServer        *server.Server
 	MetricsHttpServer *http.Server
diff --git a/cmd/spiderpool-agent/cmd/daemon.go b/cmd/spiderpool-agent/cmd/daemon.go
index 071699070..be5dbb467 100644
--- a/cmd/spiderpool-agent/cmd/daemon.go
+++ b/cmd/spiderpool-agent/cmd/daemon.go
@@ -17,8 +17,10 @@ import (
 	"github.com/pyroscope-io/client/pyroscope"
 	"go.uber.org/zap"
 
+	"github.com/spidernet-io/spiderpool/pkg/config"
 	"github.com/spidernet-io/spiderpool/pkg/ipam"
 	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
+	"github.com/spidernet-io/spiderpool/pkg/limiter"
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	"github.com/spidernet-io/spiderpool/pkg/namespacemanager"
 	"github.com/spidernet-io/spiderpool/pkg/nodemanager"
@@ -106,14 +108,17 @@ func DaemonMain() {
 
 	logger.Info("Begin to initialize IPAM")
 	ipam, err := ipam.NewIPAM(&ipam.IPAMConfig{
-		EnabledStatefulSet:       agentContext.Cfg.EnableStatefulSet,
 		EnableIPv4:               agentContext.Cfg.EnableIPv4,
 		EnableIPv6:               agentContext.Cfg.EnableIPv6,
 		ClusterDefaultIPv4IPPool: agentContext.Cfg.ClusterDefaultIPv4IPPool,
 		ClusterDefaultIPv6IPPool: agentContext.Cfg.ClusterDefaultIPv6IPPool,
-		LimiterMaxQueueSize:      agentContext.Cfg.LimiterMaxQueueSize,
-		LimiterMaxWaitTime:       time.Duration(agentContext.Cfg.LimiterMaxWaitTime) * time.Second,
-	}, agentContext.IPPoolManager, agentContext.WEManager, agentContext.NSManager, agentContext.PodManager, agentContext.StsManager)
+		EnableSpiderSubnet:       agentContext.Cfg.EnableSpiderSubnet,
+		EnableStatefulSet:        agentContext.Cfg.EnableStatefulSet,
+		LimiterConfig: &limiter.LimiterConfig{
+			MaxQueueSize: agentContext.Cfg.LimiterMaxQueueSize,
+			MaxWaitTime:  time.Duration(agentContext.Cfg.LimiterMaxWaitTime) * time.Second,
+		},
+	}, agentContext.IPPoolManager, agentContext.WEManager, agentContext.NodeManager, agentContext.NSManager, agentContext.PodManager, agentContext.StsManager)
 	agentContext.IPAM = ipam
 
 	go func() {
@@ -219,11 +224,16 @@ func WatchSignal(sigCh chan os.Signal) {
 }
 
 func initAgentServiceManagers(ctx context.Context) {
+	updateCRConfig := config.UpdateCRConfig{
+		MaxConflictRetrys:     agentContext.Cfg.UpdateCRMaxRetrys,
+		ConflictRetryUnitTime: time.Duration(agentContext.Cfg.UpdateCRRetryUnitTime) * time.Millisecond,
+	}
+
 	logger.Debug("Begin to initialize WorkloadEndpoint Manager")
-	retrys := agentContext.Cfg.UpdateCRMaxRetrys
-	unitTime := time.Duration(agentContext.Cfg.UpdateCRRetryUnitTime) * time.Millisecond
-	historySize := agentContext.Cfg.WorkloadEndpointMaxHistoryRecords
-	weManager, err := workloadendpointmanager.NewWorkloadEndpointManager(agentContext.CRDManager.GetClient(), agentContext.CRDManager.GetScheme(), historySize, retrys, unitTime)
+	weManager, err := workloadendpointmanager.NewWorkloadEndpointManager(&workloadendpointmanager.EndpointManagerConfig{
+		UpdateCRConfig:    updateCRConfig,
+		MaxHistoryRecords: agentContext.Cfg.WorkloadEndpointMaxHistoryRecords,
+	}, agentContext.CRDManager)
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
@@ -251,15 +261,19 @@ func initAgentServiceManagers(ctx context.Context) {
 	agentContext.NSManager = nsManager
 
 	logger.Debug("Begin to initialize Pod Manager")
-	podManager, err := podmanager.NewPodManager(agentContext.CRDManager.GetClient(), retrys, unitTime)
+	podManager, err := podmanager.NewPodManager(&podmanager.PodManagerConfig{
+		UpdateCRConfig: updateCRConfig,
+	}, agentContext.CRDManager.GetClient())
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
 	agentContext.PodManager = podManager
 
 	logger.Debug("Begin to initialize IPPool Manager")
-	poolSize := agentContext.Cfg.IPPoolMaxAllocatedIPs
-	ipPoolManager, err := ippoolmanager.NewIPPoolManager(agentContext.CRDManager, agentContext.RIPManager, agentContext.NodeManager, agentContext.NSManager, agentContext.PodManager, poolSize, retrys, unitTime)
+	ipPoolManager, err := ippoolmanager.NewIPPoolManager(&ippoolmanager.IPPoolManagerConfig{
+		UpdateCRConfig:  updateCRConfig,
+		MaxAllocatedIPs: agentContext.Cfg.IPPoolMaxAllocatedIPs,
+	}, agentContext.CRDManager, agentContext.RIPManager)
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
diff --git a/cmd/spiderpool-agent/cmd/unix_server.go b/cmd/spiderpool-agent/cmd/unix_server.go
index 91f177abe..08e6f2233 100644
--- a/cmd/spiderpool-agent/cmd/unix_server.go
+++ b/cmd/spiderpool-agent/cmd/unix_server.go
@@ -55,7 +55,7 @@ func NewAgentOpenAPIUnixServer() (*agentOpenAPIServer.Server, error) {
 // NewAgentOpenAPIUnixClient creates a new instance of the agent OpenAPI unix client.
 func NewAgentOpenAPIUnixClient(unixSocketPath string) (*agentOpenAPIClient.SpiderpoolAgentAPI, error) {
 	if unixSocketPath == "" {
-		return nil, fmt.Errorf("Error: no unix socket path!")
+		return nil, fmt.Errorf("unix socket path must be specified")
 	}
 	transport := &http.Transport{
 		DisableCompression: true,
diff --git a/cmd/spiderpool-controller/cmd/config.go b/cmd/spiderpool-controller/cmd/config.go
index 7d1f5c2fd..c3ce91c8c 100644
--- a/cmd/spiderpool-controller/cmd/config.go
+++ b/cmd/spiderpool-controller/cmd/config.go
@@ -21,13 +21,13 @@ import (
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	"github.com/spidernet-io/spiderpool/pkg/election"
 	"github.com/spidernet-io/spiderpool/pkg/gcmanager"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
+	ippoolmanagertypes "github.com/spidernet-io/spiderpool/pkg/ippoolmanager/types"
 	"github.com/spidernet-io/spiderpool/pkg/namespacemanager"
 	"github.com/spidernet-io/spiderpool/pkg/nodemanager"
 	"github.com/spidernet-io/spiderpool/pkg/podmanager"
 	"github.com/spidernet-io/spiderpool/pkg/reservedipmanager"
 	"github.com/spidernet-io/spiderpool/pkg/statefulsetmanager"
-	"github.com/spidernet-io/spiderpool/pkg/subnetmanager"
+	subnetmanagertypes "github.com/spidernet-io/spiderpool/pkg/subnetmanager/types"
 	"github.com/spidernet-io/spiderpool/pkg/workloadendpointmanager"
 )
 
@@ -123,12 +123,12 @@ type ControllerContext struct {
 
 	// manager
 	CRDManager    ctrl.Manager
+	SubnetManager subnetmanagertypes.SubnetManager
+	IPPoolManager ippoolmanagertypes.IPPoolManager
 	WEPManager    workloadendpointmanager.WorkloadEndpointManager
 	RIPManager    reservedipmanager.ReservedIPManager
 	NodeManager   nodemanager.NodeManager
 	NSManager     namespacemanager.NamespaceManager
-	SubnetManager subnetmanager.SubnetManager
-	IPPoolManager ippoolmanager.IPPoolManager
 	PodManager    podmanager.PodManager
 	GCManager     gcmanager.GCManager
 	StsManager    statefulsetmanager.StatefulSetManager
diff --git a/cmd/spiderpool-controller/cmd/daemon.go b/cmd/spiderpool-controller/cmd/daemon.go
index b395621d0..8aa6be512 100644
--- a/cmd/spiderpool-controller/cmd/daemon.go
+++ b/cmd/spiderpool-controller/cmd/daemon.go
@@ -18,6 +18,7 @@ import (
 	"k8s.io/client-go/rest"
 	ctrl "sigs.k8s.io/controller-runtime"
 
+	"github.com/spidernet-io/spiderpool/pkg/config"
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	"github.com/spidernet-io/spiderpool/pkg/election"
 	"github.com/spidernet-io/spiderpool/pkg/gcmanager"
@@ -177,15 +178,20 @@ func WatchSignal(sigCh chan os.Signal) {
 }
 
 func initControllerServiceManagers(ctx context.Context) {
+	updateCRConfig := config.UpdateCRConfig{
+		MaxConflictRetrys:     controllerContext.Cfg.UpdateCRMaxRetrys,
+		ConflictRetryUnitTime: time.Duration(controllerContext.Cfg.UpdateCRRetryUnitTime) * time.Millisecond,
+	}
+
 	// init spiderpool controller leader election
 	logger.Info("Begin to initialize spiderpool controller leader election")
 	initSpiderControllerLeaderElect(controllerContext.InnerCtx)
 
 	logger.Info("Begin to initialize WorkloadEndpoint Manager")
-	retrys := controllerContext.Cfg.UpdateCRMaxRetrys
-	unitTime := time.Duration(controllerContext.Cfg.UpdateCRRetryUnitTime) * time.Millisecond
-	historySize := controllerContext.Cfg.WorkloadEndpointMaxHistoryRecords
-	wepManager, err := workloadendpointmanager.NewWorkloadEndpointManager(controllerContext.CRDManager.GetClient(), controllerContext.CRDManager.GetScheme(), historySize, retrys, unitTime)
+	wepManager, err := workloadendpointmanager.NewWorkloadEndpointManager(&workloadendpointmanager.EndpointManagerConfig{
+		UpdateCRConfig:    updateCRConfig,
+		MaxHistoryRecords: controllerContext.Cfg.WorkloadEndpointMaxHistoryRecords,
+	}, controllerContext.CRDManager)
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
@@ -219,7 +225,9 @@ func initControllerServiceManagers(ctx context.Context) {
 	controllerContext.NSManager = nsManager
 
 	logger.Info("Begin to initialize Pod Manager")
-	podManager, err := podmanager.NewPodManager(controllerContext.CRDManager.GetClient(), retrys, unitTime)
+	podManager, err := podmanager.NewPodManager(&podmanager.PodManagerConfig{
+		UpdateCRConfig: updateCRConfig,
+	}, controllerContext.CRDManager.GetClient())
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
@@ -232,27 +240,13 @@ func initControllerServiceManagers(ctx context.Context) {
 	}
 	controllerContext.StsManager = statefulSetManager
 
-	if controllerContext.Cfg.EnableSpiderSubnet {
-		logger.Info("Begin to initialize Subnet Manager")
-		subnetManager, err := subnetmanager.NewSubnetManager(controllerContext.CRDManager, controllerContext.Cfg.EnableSpiderSubnet)
-		if err != nil {
-			logger.Fatal(err.Error())
-		}
-		controllerContext.SubnetManager = subnetManager
-
-		logger.Info("Begin to set up Subnet webhook")
-		err = controllerContext.SubnetManager.SetupWebhook()
-		if err != nil {
-			logger.Fatal(err.Error())
-		}
-	} else {
-		logger.Info("Feature SpiderSubnet is disabled")
-	}
-
 	logger.Info("Begin to initialize IPPool Manager")
-	poolSize := controllerContext.Cfg.IPPoolMaxAllocatedIPs
-	ipPoolManager, err := ippoolmanager.NewIPPoolManager(controllerContext.CRDManager, controllerContext.RIPManager, controllerContext.NodeManager,
-		controllerContext.NSManager, controllerContext.PodManager, poolSize, retrys, unitTime)
+	ipPoolManager, err := ippoolmanager.NewIPPoolManager(&ippoolmanager.IPPoolManagerConfig{
+		UpdateCRConfig:      updateCRConfig,
+		EnableSpiderSubnet:  controllerContext.Cfg.EnableSpiderSubnet,
+		MaxAllocatedIPs:     controllerContext.Cfg.IPPoolMaxAllocatedIPs,
+		LeaderRetryElectGap: time.Duration(controllerContext.Cfg.LeaseRetryGap) * time.Second,
+	}, controllerContext.CRDManager, controllerContext.RIPManager)
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
@@ -264,8 +258,7 @@ func initControllerServiceManagers(ctx context.Context) {
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
-	leaderRetryElectGap := time.Duration(controllerContext.Cfg.LeaseRetryGap) * time.Second
-	err = controllerContext.IPPoolManager.SetupInformer(crdClient, controllerContext.Leader, &leaderRetryElectGap)
+	err = controllerContext.IPPoolManager.SetupInformer(crdClient, controllerContext.Leader)
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
@@ -276,6 +269,26 @@ func initControllerServiceManagers(ctx context.Context) {
 	if err != nil {
 		logger.Fatal(err.Error())
 	}
+
+	if controllerContext.Cfg.EnableSpiderSubnet {
+		logger.Info("Begin to initialize Subnet Manager")
+		subnetManager, err := subnetmanager.NewSubnetManager(&subnetmanager.SubnetManagerConfig{
+			EnableSpiderSubnet: controllerContext.Cfg.EnableSpiderSubnet,
+		}, controllerContext.CRDManager)
+		if err != nil {
+			logger.Fatal(err.Error())
+		}
+		controllerContext.SubnetManager = subnetManager
+		ipPoolManager.InjectSubnetManager(controllerContext.SubnetManager)
+
+		logger.Info("Begin to set up Subnet webhook")
+		err = controllerContext.SubnetManager.SetupWebhook()
+		if err != nil {
+			logger.Fatal(err.Error())
+		}
+	} else {
+		logger.Info("Feature SpiderSubnet is disabled")
+	}
 }
 
 func initGCManager(ctx context.Context) {
diff --git a/pkg/config/config.go b/pkg/config/config.go
new file mode 100644
index 000000000..ef9a4cd7d
--- /dev/null
+++ b/pkg/config/config.go
@@ -0,0 +1,11 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package config
+
+import "time"
+
+type UpdateCRConfig struct {
+	MaxConflictRetrys     int
+	ConflictRetryUnitTime time.Duration
+}
diff --git a/pkg/gcmanager/gc_manager.go b/pkg/gcmanager/gc_manager.go
index b5903f33d..915548b5f 100644
--- a/pkg/gcmanager/gc_manager.go
+++ b/pkg/gcmanager/gc_manager.go
@@ -12,7 +12,7 @@ import (
 	"k8s.io/client-go/kubernetes"
 
 	"github.com/spidernet-io/spiderpool/pkg/election"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
+	ippoolmanagertypes "github.com/spidernet-io/spiderpool/pkg/ippoolmanager/types"
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	"github.com/spidernet-io/spiderpool/pkg/podmanager"
 	"github.com/spidernet-io/spiderpool/pkg/statefulsetmanager"
@@ -61,7 +61,7 @@ type SpiderGC struct {
 	gcIPPoolIPSignal chan *PodEntry
 
 	wepMgr    workloadendpointmanager.WorkloadEndpointManager
-	ippoolMgr ippoolmanager.IPPoolManager
+	ippoolMgr ippoolmanagertypes.IPPoolManager
 	podMgr    podmanager.PodManager
 	stsMgr    statefulsetmanager.StatefulSetManager
 
@@ -70,7 +70,7 @@ type SpiderGC struct {
 
 func NewGCManager(ctx context.Context, clientSet *kubernetes.Clientset, config *GarbageCollectionConfig,
 	wepManager workloadendpointmanager.WorkloadEndpointManager,
-	ippoolManager ippoolmanager.IPPoolManager,
+	ippoolManager ippoolmanagertypes.IPPoolManager,
 	podManager podmanager.PodManager,
 	stsManager statefulsetmanager.StatefulSetManager,
 	spiderControllerLeader election.SpiderLeaseElector) (GCManager, error) {
diff --git a/pkg/gcmanager/scanAll_IPPool.go b/pkg/gcmanager/scanAll_IPPool.go
index 17c225513..e88b245b0 100644
--- a/pkg/gcmanager/scanAll_IPPool.go
+++ b/pkg/gcmanager/scanAll_IPPool.go
@@ -12,10 +12,10 @@ import (
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 
 	"github.com/spidernet-io/spiderpool/pkg/constant"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
 	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	metrics "github.com/spidernet-io/spiderpool/pkg/metric"
+	"github.com/spidernet-io/spiderpool/pkg/types"
 )
 
 // monitorGCSignal will monitor signal from CLI, DefaultGCInterval
@@ -162,7 +162,7 @@ func (s *SpiderGC) executeScanAll(ctx context.Context) {
 				if !isCurrentContainerID {
 					wrappedLog := scanAllLogger.With(zap.String("gc-reason", "IPPoolAllocation containerID is different with wep current containerID"))
 					// release IP but no need to remove wep finalizer
-					err = s.ippoolMgr.ReleaseIP(ctx, pool.Name, []ippoolmanager.IPAndCID{{
+					err = s.ippoolMgr.ReleaseIP(ctx, pool.Name, []types.IPAndCID{{
 						IP:          poolIP,
 						ContainerID: poolIPAllocation.ContainerID},
 					})
@@ -183,7 +183,7 @@ func (s *SpiderGC) executeScanAll(ctx context.Context) {
 func (s *SpiderGC) releaseSingleIPAndRemoveWEPFinalizer(ctx context.Context, poolName, poolIP string, poolIPAllocation spiderpoolv1.PoolIPAllocation) error {
 	log := logutils.FromContext(ctx)
 
-	singleIP := []ippoolmanager.IPAndCID{{IP: poolIP, ContainerID: poolIPAllocation.ContainerID}}
+	singleIP := []types.IPAndCID{{IP: poolIP, ContainerID: poolIPAllocation.ContainerID}}
 	err := s.ippoolMgr.ReleaseIP(ctx, poolName, singleIP)
 	if nil != err {
 		metrics.IPGCFailureCounts.Add(ctx, 1)
diff --git a/pkg/ipam/ipam_config.go b/pkg/ipam/config.go
similarity index 95%
rename from pkg/ipam/ipam_config.go
rename to pkg/ipam/config.go
index 504855d63..a9173a063 100644
--- a/pkg/ipam/ipam_config.go
+++ b/pkg/ipam/config.go
@@ -6,21 +6,23 @@ package ipam
 import (
 	"context"
 	"fmt"
-	"time"
 
 	"github.com/spidernet-io/spiderpool/pkg/constant"
+	"github.com/spidernet-io/spiderpool/pkg/limiter"
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	utilerrors "k8s.io/apimachinery/pkg/util/errors"
 )
 
 type IPAMConfig struct {
-	EnabledStatefulSet       bool
 	EnableIPv4               bool
 	EnableIPv6               bool
 	ClusterDefaultIPv4IPPool []string
 	ClusterDefaultIPv6IPPool []string
-	LimiterMaxQueueSize      int
-	LimiterMaxWaitTime       time.Duration
+
+	EnableSpiderSubnet bool
+	EnableStatefulSet  bool
+
+	LimiterConfig *limiter.LimiterConfig
 }
 
 func (c *IPAMConfig) getClusterDefaultPool(ctx context.Context, nic string, cleanGateway bool) (*ToBeAllocated, error) {
diff --git a/pkg/ipam/convert.go b/pkg/ipam/convert.go
index bf8ba8fa0..f9426ef70 100644
--- a/pkg/ipam/convert.go
+++ b/pkg/ipam/convert.go
@@ -11,7 +11,6 @@ import (
 
 	"github.com/spidernet-io/spiderpool/api/v1/agent/models"
 	"github.com/spidernet-io/spiderpool/pkg/constant"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
 	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
 	"github.com/spidernet-io/spiderpool/pkg/types"
 )
@@ -253,17 +252,17 @@ func genIPAssignmentAnnotation(ips []*models.IPConfig) (map[string]string, error
 	return podAnnotations, nil
 }
 
-func GroupIPDetails(containerID string, details []spiderpoolv1.IPAllocationDetail) map[string][]ippoolmanager.IPAndCID {
-	poolToIPAndCIDs := map[string][]ippoolmanager.IPAndCID{}
+func GroupIPDetails(containerID string, details []spiderpoolv1.IPAllocationDetail) map[string][]types.IPAndCID {
+	poolToIPAndCIDs := map[string][]types.IPAndCID{}
 	for _, d := range details {
 		if d.IPv4 != nil {
-			poolToIPAndCIDs[*d.IPv4Pool] = append(poolToIPAndCIDs[*d.IPv4Pool], ippoolmanager.IPAndCID{
+			poolToIPAndCIDs[*d.IPv4Pool] = append(poolToIPAndCIDs[*d.IPv4Pool], types.IPAndCID{
 				IP:          strings.Split(*d.IPv4, "/")[0],
 				ContainerID: containerID,
 			})
 		}
 		if d.IPv6 != nil {
-			poolToIPAndCIDs[*d.IPv6Pool] = append(poolToIPAndCIDs[*d.IPv6Pool], ippoolmanager.IPAndCID{
+			poolToIPAndCIDs[*d.IPv6Pool] = append(poolToIPAndCIDs[*d.IPv6Pool], types.IPAndCID{
 				IP:          strings.Split(*d.IPv6, "/")[0],
 				ContainerID: containerID,
 			})
diff --git a/pkg/ipam/ipam.go b/pkg/ipam/ipam.go
index b58347fca..2ad039d13 100644
--- a/pkg/ipam/ipam.go
+++ b/pkg/ipam/ipam.go
@@ -15,13 +15,15 @@ import (
 
 	"github.com/spidernet-io/spiderpool/api/v1/agent/models"
 	"github.com/spidernet-io/spiderpool/pkg/constant"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
+	ippoolmanagertypes "github.com/spidernet-io/spiderpool/pkg/ippoolmanager/types"
 	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
 	"github.com/spidernet-io/spiderpool/pkg/limiter"
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	"github.com/spidernet-io/spiderpool/pkg/namespacemanager"
+	"github.com/spidernet-io/spiderpool/pkg/nodemanager"
 	"github.com/spidernet-io/spiderpool/pkg/podmanager"
 	"github.com/spidernet-io/spiderpool/pkg/statefulsetmanager"
+	"github.com/spidernet-io/spiderpool/pkg/types"
 	"github.com/spidernet-io/spiderpool/pkg/workloadendpointmanager"
 )
 
@@ -32,16 +34,17 @@ type IPAM interface {
 }
 
 type ipam struct {
-	ipamConfig    *IPAMConfig
+	config        *IPAMConfig
 	ipamLimiter   limiter.Limiter
-	ipPoolManager ippoolmanager.IPPoolManager
+	ipPoolManager ippoolmanagertypes.IPPoolManager
 	weManager     workloadendpointmanager.WorkloadEndpointManager
+	nodeManager   nodemanager.NodeManager
 	nsManager     namespacemanager.NamespaceManager
 	podManager    podmanager.PodManager
 	stsManager    statefulsetmanager.StatefulSetManager
 }
 
-func NewIPAM(c *IPAMConfig, ipPoolManager ippoolmanager.IPPoolManager, weManager workloadendpointmanager.WorkloadEndpointManager,
+func NewIPAM(c *IPAMConfig, ipPoolManager ippoolmanagertypes.IPPoolManager, weManager workloadendpointmanager.WorkloadEndpointManager, nodeManager nodemanager.NodeManager,
 	nsManager namespacemanager.NamespaceManager, podManager podmanager.PodManager, stsManager statefulsetmanager.StatefulSetManager) (IPAM, error) {
 	if c == nil {
 		return nil, errors.New("IPAM config must be specified")
@@ -52,6 +55,9 @@ func NewIPAM(c *IPAMConfig, ipPoolManager ippoolmanager.IPPoolManager, weManager
 	if weManager == nil {
 		return nil, errors.New("EndpointManager must be specified")
 	}
+	if nodeManager == nil {
+		return nil, errors.New("NodeManager must be specified")
+	}
 	if nsManager == nil {
 		return nil, errors.New("NamespaceManager must be specified")
 	}
@@ -62,12 +68,13 @@ func NewIPAM(c *IPAMConfig, ipPoolManager ippoolmanager.IPPoolManager, weManager
 		return nil, errors.New("StatefulSetManager must be specified")
 	}
 
-	ipamLimiter := limiter.NewLimiter(c.LimiterMaxQueueSize, c.LimiterMaxWaitTime)
+	ipamLimiter := limiter.NewLimiter(c.LimiterConfig)
 	return &ipam{
-		ipamConfig:    c,
+		config:        c,
 		ipamLimiter:   ipamLimiter,
 		ipPoolManager: ipPoolManager,
 		weManager:     weManager,
+		nodeManager:   nodeManager,
 		nsManager:     nsManager,
 		podManager:    podManager,
 		stsManager:    stsManager,
@@ -93,7 +100,7 @@ func (i *ipam) Allocate(ctx context.Context, addArgs *models.IpamAddArgs) (*mode
 	}
 
 	ownerControllerType, _ := podmanager.GetOwnerControllerType(pod)
-	if i.ipamConfig.EnabledStatefulSet && ownerControllerType == constant.OwnerStatefulSet {
+	if i.config.EnableStatefulSet && ownerControllerType == constant.OwnerStatefulSet {
 		addResp, err := i.retrieveStsIPAllocation(ctx, *addArgs.ContainerID, *addArgs.IfName, pod, endpoint)
 		if err != nil {
 			return nil, fmt.Errorf("failed to retrieve the IP allocation of StatefulSet: %v", err)
@@ -222,7 +229,7 @@ func (i *ipam) genToBeAllocatedSet(ctx context.Context, nic string, defaultIPV4I
 	}
 	logger.Sugar().Infof("Preliminary IPPool candidates: %s", preliminary)
 
-	if err := i.ipamConfig.checkIPVersionEnable(ctx, preliminary); err != nil {
+	if err := i.config.checkIPVersionEnable(ctx, preliminary); err != nil {
 		return nil, err
 	}
 
@@ -376,7 +383,7 @@ func (i *ipam) getPoolCandidates(ctx context.Context, nic string, netConfV4Pool,
 	}
 
 	// configmap
-	t, err = i.ipamConfig.getClusterDefaultPool(ctx, nic, cleanGateway)
+	t, err = i.config.getClusterDefaultPool(ctx, nic, cleanGateway)
 	if err != nil {
 		return nil, err
 	}
@@ -426,7 +433,7 @@ func (i *ipam) filterPoolCandidates(ctx context.Context, tt []*ToBeAllocated, po
 		for _, c := range t.PoolCandidates {
 			var selectedPools []string
 			for _, pool := range c.Pools {
-				eligible, err := i.ipPoolManager.SelectByPod(ctx, c.IPVersion, pool, pod)
+				eligible, err := i.selectByPod(ctx, c.IPVersion, pool, pod)
 				if err != nil {
 					return nil, err
 				}
@@ -444,6 +451,68 @@ func (i *ipam) filterPoolCandidates(ctx context.Context, tt []*ToBeAllocated, po
 	return tt, nil
 }
 
+func (i *ipam) selectByPod(ctx context.Context, version types.IPVersion, poolName string, pod *corev1.Pod) (bool, error) {
+	logger := logutils.FromContext(ctx)
+
+	ipPool, err := i.ipPoolManager.GetIPPoolByName(ctx, poolName)
+	if err != nil {
+		logger.Sugar().Warnf("Failed to get IPPool %s: %v", poolName, err)
+		return false, err
+	}
+
+	if ipPool.DeletionTimestamp != nil {
+		logger.Sugar().Warnf("IPPool %s is terminating", poolName)
+		return false, nil
+	}
+
+	if *ipPool.Spec.Disable {
+		logger.Sugar().Warnf("IPPool %s is disable", poolName)
+		return false, nil
+	}
+
+	if *ipPool.Spec.IPVersion != version {
+		logger.Sugar().Warnf("IPPool %s has different version with specified via input", poolName)
+		return false, nil
+	}
+
+	// TODO(iiiceoo): Check whether there are any unused IP
+
+	if ipPool.Spec.NodeAffinity != nil {
+		nodeMatched, err := i.nodeManager.MatchLabelSelector(ctx, pod.Spec.NodeName, ipPool.Spec.NodeAffinity)
+		if err != nil {
+			return false, err
+		}
+		if !nodeMatched {
+			logger.Sugar().Infof("Unmatched Node selector, IPPool %s is filtered", poolName)
+			return false, nil
+		}
+	}
+
+	if ipPool.Spec.NamespaceAffinity != nil {
+		nsMatched, err := i.nsManager.MatchLabelSelector(ctx, pod.Namespace, ipPool.Spec.NamespaceAffinity)
+		if err != nil {
+			return false, err
+		}
+		if !nsMatched {
+			logger.Sugar().Infof("Unmatched Namespace selector, IPPool %s is filtered", poolName)
+			return false, nil
+		}
+	}
+
+	if ipPool.Spec.PodAffinity != nil {
+		podMatched, err := i.podManager.MatchLabelSelector(ctx, pod.Namespace, pod.Name, ipPool.Spec.PodAffinity)
+		if err != nil {
+			return false, err
+		}
+		if !podMatched {
+			logger.Sugar().Infof("Unmatched Pod selector, IPPool %s is filtered", poolName)
+			return false, nil
+		}
+	}
+
+	return true, nil
+}
+
 func (i *ipam) verifyPoolCandidates(ctx context.Context, tt []*ToBeAllocated) error {
 	for _, t := range tt {
 		var allPools []string
@@ -472,7 +541,7 @@ func (i *ipam) Release(ctx context.Context, delArgs *models.IpamDelArgs) error {
 	}
 
 	ownerControllerType, _ := podmanager.GetOwnerControllerType(pod)
-	if i.ipamConfig.EnabledStatefulSet && ownerControllerType == constant.OwnerStatefulSet {
+	if i.config.EnableStatefulSet && ownerControllerType == constant.OwnerStatefulSet {
 		isValidStsPod, err := i.stsManager.IsValidStatefulSetPod(ctx, pod.Namespace, pod.Name, ownerControllerType)
 		if err != nil {
 			return err
@@ -520,7 +589,7 @@ func (i *ipam) release(ctx context.Context, containerID string, details []spider
 	wg.Add(len(poolToIPAndCIDs))
 
 	for pool, ipAndCIDs := range poolToIPAndCIDs {
-		go func(pool string, ipAndCIDs []ippoolmanager.IPAndCID) {
+		go func(pool string, ipAndCIDs []types.IPAndCID) {
 			defer wg.Done()
 
 			_, err := i.ipamLimiter.AcquireTicket(ctx, pool)
diff --git a/pkg/ippoolmanager/config.go b/pkg/ippoolmanager/config.go
new file mode 100644
index 000000000..01ba8616b
--- /dev/null
+++ b/pkg/ippoolmanager/config.go
@@ -0,0 +1,17 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package ippoolmanager
+
+import (
+	"time"
+
+	"github.com/spidernet-io/spiderpool/pkg/config"
+)
+
+type IPPoolManagerConfig struct {
+	config.UpdateCRConfig
+	EnableSpiderSubnet  bool
+	MaxAllocatedIPs     int
+	LeaderRetryElectGap time.Duration
+}
diff --git a/pkg/ippoolmanager/ippool_informer.go b/pkg/ippoolmanager/ippool_informer.go
index 64f1def6e..1128f355b 100644
--- a/pkg/ippoolmanager/ippool_informer.go
+++ b/pkg/ippoolmanager/ippool_informer.go
@@ -24,15 +24,11 @@ import (
 var informerLogger *zap.Logger
 
 // SetupInformer will set up SpiderIPPool informer in circle
-func (im *ipPoolManager) SetupInformer(client crdclientset.Interface, controllerLeader election.SpiderLeaseElector, leaderRetryElectGap *time.Duration) error {
+func (im *ipPoolManager) SetupInformer(client crdclientset.Interface, controllerLeader election.SpiderLeaseElector) error {
 	if controllerLeader == nil {
 		return fmt.Errorf("failed to start SpiderIPPool informer, controller leader must be specified")
 	}
 
-	if leaderRetryElectGap == nil {
-		return fmt.Errorf("failed to start SpiderIPPool informer, leaderRetryElectGap must be specified")
-	}
-
 	informerLogger = logutils.Logger.Named("SpiderIPPool-Informer")
 
 	im.leader = controllerLeader
@@ -41,7 +37,7 @@ func (im *ipPoolManager) SetupInformer(client crdclientset.Interface, controller
 	go func() {
 		for {
 			if !im.leader.IsElected() {
-				time.Sleep(*leaderRetryElectGap)
+				time.Sleep(im.config.LeaderRetryElectGap)
 				continue
 			}
 
@@ -64,7 +60,7 @@ func (im *ipPoolManager) SetupInformer(client crdclientset.Interface, controller
 						return
 					}
 
-					time.Sleep(*leaderRetryElectGap)
+					time.Sleep(im.config.LeaderRetryElectGap)
 				}
 			}()
 
diff --git a/pkg/ippoolmanager/ippool_manager.go b/pkg/ippoolmanager/ippool_manager.go
index a5632bdec..56cafb511 100644
--- a/pkg/ippoolmanager/ippool_manager.go
+++ b/pkg/ippoolmanager/ippool_manager.go
@@ -23,76 +23,52 @@ import (
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	"github.com/spidernet-io/spiderpool/pkg/election"
 	spiderpoolip "github.com/spidernet-io/spiderpool/pkg/ip"
+	ippoolmanagertypes "github.com/spidernet-io/spiderpool/pkg/ippoolmanager/types"
 	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
-	crdclientset "github.com/spidernet-io/spiderpool/pkg/k8s/client/clientset/versioned"
-	"github.com/spidernet-io/spiderpool/pkg/logutils"
-	"github.com/spidernet-io/spiderpool/pkg/namespacemanager"
-	"github.com/spidernet-io/spiderpool/pkg/nodemanager"
 	"github.com/spidernet-io/spiderpool/pkg/podmanager"
 	"github.com/spidernet-io/spiderpool/pkg/reservedipmanager"
+	subnetmanagertypes "github.com/spidernet-io/spiderpool/pkg/subnetmanager/types"
 	"github.com/spidernet-io/spiderpool/pkg/types"
 )
 
-type IPPoolManager interface {
-	SetupWebhook() error
-	SetupInformer(client crdclientset.Interface, controllerLeader election.SpiderLeaseElector, leaderRetryElectGap *time.Duration) error
-	GetIPPoolByName(ctx context.Context, poolName string) (*spiderpoolv1.SpiderIPPool, error)
-	ListIPPools(ctx context.Context, opts ...client.ListOption) (*spiderpoolv1.SpiderIPPoolList, error)
-	AllocateIP(ctx context.Context, poolName, containerID, nic string, pod *corev1.Pod) (*models.IPConfig, *spiderpoolv1.SpiderIPPool, error)
-	ReleaseIP(ctx context.Context, poolName string, ipAndCIDs []IPAndCID) error
-	SelectByPod(ctx context.Context, version types.IPVersion, poolName string, pod *corev1.Pod) (bool, error)
-	CheckVlanSame(ctx context.Context, poolNameList []string) (map[types.Vlan][]string, bool, error)
-	RemoveFinalizer(ctx context.Context, poolName string) error
-	UpdateAllocatedIPs(ctx context.Context, containerID string, pod *corev1.Pod, oldIPConfig models.IPConfig) error
-}
-
 type ipPoolManager struct {
-	client                client.Client
-	runtimeMgr            ctrl.Manager
-	rIPManager            reservedipmanager.ReservedIPManager
-	nodeManager           nodemanager.NodeManager
-	nsManager             namespacemanager.NamespaceManager
-	podManager            podmanager.PodManager
-	maxAllocatedIPs       int
-	maxConflictRetrys     int
-	conflictRetryUnitTime time.Duration
+	config        *IPPoolManagerConfig
+	client        client.Client
+	runtimeMgr    ctrl.Manager
+	rIPManager    reservedipmanager.ReservedIPManager
+	subnetManager subnetmanagertypes.SubnetManager
 
 	// leader only serves for Spiderpool controller SpiderIPPool informer, it will be set by SetupInformer
 	leader election.SpiderLeaseElector
 }
 
-func NewIPPoolManager(mgr ctrl.Manager, rIPManager reservedipmanager.ReservedIPManager, nodeManager nodemanager.NodeManager,
-	nsManager namespacemanager.NamespaceManager, podManager podmanager.PodManager,
-	maxAllocatedIPs, maxConflictRetrys int, conflictRetryUnitTime time.Duration) (IPPoolManager, error) {
+func NewIPPoolManager(c *IPPoolManagerConfig, mgr ctrl.Manager, rIPManager reservedipmanager.ReservedIPManager) (ippoolmanagertypes.IPPoolManager, error) {
+	if c == nil {
+		return nil, errors.New("ippool manager config must be specified")
+	}
 	if mgr == nil {
 		return nil, errors.New("k8s manager must be specified")
 	}
 	if rIPManager == nil {
-		return nil, errors.New("ReservedIPManager must be specified")
-	}
-	if nodeManager == nil {
-		return nil, errors.New("NodeManager must be specified")
-	}
-	if nsManager == nil {
-		return nil, errors.New("NamespaceManager must be specified")
-	}
-	if podManager == nil {
-		return nil, errors.New("PodManager must be specified")
+		return nil, errors.New("reserved IP manager must be specified")
 	}
 
 	return &ipPoolManager{
-		client:                mgr.GetClient(),
-		runtimeMgr:            mgr,
-		rIPManager:            rIPManager,
-		nodeManager:           nodeManager,
-		nsManager:             nsManager,
-		podManager:            podManager,
-		maxAllocatedIPs:       maxAllocatedIPs,
-		maxConflictRetrys:     maxConflictRetrys,
-		conflictRetryUnitTime: conflictRetryUnitTime,
+		config:     c,
+		client:     mgr.GetClient(),
+		runtimeMgr: mgr,
+		rIPManager: rIPManager,
 	}, nil
 }
 
+func (im *ipPoolManager) InjectSubnetManager(subnetManager subnetmanagertypes.SubnetManager) {
+	if subnetManager == nil {
+		return
+	}
+
+	im.subnetManager = subnetManager
+}
+
 func (im *ipPoolManager) GetIPPoolByName(ctx context.Context, poolName string) (*spiderpoolv1.SpiderIPPool, error) {
 	var ipPool spiderpoolv1.SpiderIPPool
 	if err := im.client.Get(ctx, apitypes.NamespacedName{Name: poolName}, &ipPool); err != nil {
@@ -115,7 +91,7 @@ func (im *ipPoolManager) AllocateIP(ctx context.Context, poolName, containerID,
 	var ipConfig *models.IPConfig
 	var usedIPPool *spiderpoolv1.SpiderIPPool
 	rand.Seed(time.Now().UnixNano())
-	for i := 0; i <= im.maxConflictRetrys; i++ {
+	for i := 0; i <= im.config.MaxConflictRetrys; i++ {
 		ipPool, err := im.GetIPPoolByName(ctx, poolName)
 		if err != nil {
 			return nil, nil, err
@@ -146,18 +122,18 @@ func (im *ipPoolManager) AllocateIP(ctx context.Context, poolName, containerID,
 		}
 
 		*ipPool.Status.AllocatedIPCount++
-		if *ipPool.Status.AllocatedIPCount > int64(im.maxAllocatedIPs) {
-			return nil, nil, fmt.Errorf("threshold of IP allocations(<=%d) for IPPool exceeded: %w", im.maxAllocatedIPs, constant.ErrIPUsedOut)
+		if *ipPool.Status.AllocatedIPCount > int64(im.config.MaxAllocatedIPs) {
+			return nil, nil, fmt.Errorf("threshold of IP allocations(<=%d) for IPPool exceeded: %w", im.config.MaxAllocatedIPs, constant.ErrIPUsedOut)
 		}
 
 		if err := im.client.Status().Update(ctx, ipPool); err != nil {
 			if !apierrors.IsConflict(err) {
 				return nil, nil, err
 			}
-			if i == im.maxConflictRetrys {
-				return nil, nil, fmt.Errorf("insufficient retries(<=%d) to allocate IP from IPPool %s", im.maxConflictRetrys, poolName)
+			if i == im.config.MaxAllocatedIPs {
+				return nil, nil, fmt.Errorf("insufficient retries(<=%d) to allocate IP from IPPool %s", im.config.MaxConflictRetrys, poolName)
 			}
-			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.conflictRetryUnitTime)
+			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.config.ConflictRetryUnitTime)
 			continue
 		}
 
@@ -204,14 +180,9 @@ func (im *ipPoolManager) genRandomIP(ctx context.Context, ipPool *spiderpoolv1.S
 	return availableIPs[rand.Int()%len(availableIPs)], nil
 }
 
-type IPAndCID struct {
-	IP          string
-	ContainerID string
-}
-
-func (im *ipPoolManager) ReleaseIP(ctx context.Context, poolName string, ipAndCIDs []IPAndCID) error {
+func (im *ipPoolManager) ReleaseIP(ctx context.Context, poolName string, ipAndCIDs []types.IPAndCID) error {
 	rand.Seed(time.Now().UnixNano())
-	for i := 0; i <= im.maxConflictRetrys; i++ {
+	for i := 0; i <= im.config.MaxConflictRetrys; i++ {
 		ipPool, err := im.GetIPPoolByName(ctx, poolName)
 		if err != nil {
 			return err
@@ -243,10 +214,10 @@ func (im *ipPoolManager) ReleaseIP(ctx context.Context, poolName string, ipAndCI
 			if !apierrors.IsConflict(err) {
 				return err
 			}
-			if i == im.maxConflictRetrys {
-				return fmt.Errorf("insufficient retries(<=%d) to release IP %+v from IPPool %s", im.maxConflictRetrys, ipAndCIDs, poolName)
+			if i == im.config.MaxConflictRetrys {
+				return fmt.Errorf("insufficient retries(<=%d) to release IP %+v from IPPool %s", im.config.MaxConflictRetrys, ipAndCIDs, poolName)
 			}
-			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.conflictRetryUnitTime)
+			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.config.ConflictRetryUnitTime)
 			continue
 		}
 		break
@@ -255,68 +226,6 @@ func (im *ipPoolManager) ReleaseIP(ctx context.Context, poolName string, ipAndCI
 	return nil
 }
 
-func (im *ipPoolManager) SelectByPod(ctx context.Context, version types.IPVersion, poolName string, pod *corev1.Pod) (bool, error) {
-	logger := logutils.FromContext(ctx)
-
-	ipPool, err := im.GetIPPoolByName(ctx, poolName)
-	if err != nil {
-		logger.Sugar().Warnf("Failed to get IPPool %s: %v", poolName, err)
-		return false, err
-	}
-
-	if ipPool.DeletionTimestamp != nil {
-		logger.Sugar().Warnf("IPPool %s is terminating", poolName)
-		return false, nil
-	}
-
-	if *ipPool.Spec.Disable {
-		logger.Sugar().Warnf("IPPool %s is disable", poolName)
-		return false, nil
-	}
-
-	if *ipPool.Spec.IPVersion != version {
-		logger.Sugar().Warnf("IPPool %s has different version with specified via input", poolName)
-		return false, nil
-	}
-
-	// TODO(iiiceoo): Check whether there are any unused IP
-
-	if ipPool.Spec.NodeAffinity != nil {
-		nodeMatched, err := im.nodeManager.MatchLabelSelector(ctx, pod.Spec.NodeName, ipPool.Spec.NodeAffinity)
-		if err != nil {
-			return false, err
-		}
-		if !nodeMatched {
-			logger.Sugar().Infof("Unmatched Node selector, IPPool %s is filtered", poolName)
-			return false, nil
-		}
-	}
-
-	if ipPool.Spec.NamespaceAffinity != nil {
-		nsMatched, err := im.nsManager.MatchLabelSelector(ctx, pod.Namespace, ipPool.Spec.NamespaceAffinity)
-		if err != nil {
-			return false, err
-		}
-		if !nsMatched {
-			logger.Sugar().Infof("Unmatched Namespace selector, IPPool %s is filtered", poolName)
-			return false, nil
-		}
-	}
-
-	if ipPool.Spec.PodAffinity != nil {
-		podMatched, err := im.podManager.MatchLabelSelector(ctx, pod.Namespace, pod.Name, ipPool.Spec.PodAffinity)
-		if err != nil {
-			return false, err
-		}
-		if !podMatched {
-			logger.Sugar().Infof("Unmatched Pod selector, IPPool %s is filtered", poolName)
-			return false, nil
-		}
-	}
-
-	return true, nil
-}
-
 // TODO(iiiceoo): Refactor
 func (im *ipPoolManager) CheckVlanSame(ctx context.Context, poolNameList []string) (map[types.Vlan][]string, bool, error) {
 	vlanToPools := map[types.Vlan][]string{}
@@ -337,7 +246,7 @@ func (im *ipPoolManager) CheckVlanSame(ctx context.Context, poolNameList []strin
 }
 
 func (im *ipPoolManager) RemoveFinalizer(ctx context.Context, poolName string) error {
-	for i := 0; i <= im.maxConflictRetrys; i++ {
+	for i := 0; i <= im.config.MaxConflictRetrys; i++ {
 		ipPool, err := im.GetIPPoolByName(ctx, poolName)
 		if err != nil {
 			return err
@@ -352,10 +261,10 @@ func (im *ipPoolManager) RemoveFinalizer(ctx context.Context, poolName string) e
 			if !apierrors.IsConflict(err) {
 				return err
 			}
-			if i == im.maxConflictRetrys {
-				return fmt.Errorf("insufficient retries(<=%d) to remove finalizer '%s' from IPPool %s", im.maxConflictRetrys, constant.SpiderFinalizer, poolName)
+			if i == im.config.MaxConflictRetrys {
+				return fmt.Errorf("insufficient retries(<=%d) to remove finalizer '%s' from IPPool %s", im.config.MaxConflictRetrys, constant.SpiderFinalizer, poolName)
 			}
-			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.conflictRetryUnitTime)
+			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.config.ConflictRetryUnitTime)
 			continue
 		}
 		break
@@ -366,7 +275,7 @@ func (im *ipPoolManager) RemoveFinalizer(ctx context.Context, poolName string) e
 
 // UpdateAllocatedIPs serves for StatefulSet pod re-create
 func (im *ipPoolManager) UpdateAllocatedIPs(ctx context.Context, containerID string, pod *corev1.Pod, oldIPConfig models.IPConfig) error {
-	for i := 0; i <= im.maxConflictRetrys; i++ {
+	for i := 0; i <= im.config.MaxConflictRetrys; i++ {
 		pool, err := im.GetIPPoolByName(ctx, oldIPConfig.IPPool)
 		if nil != err {
 			return err
@@ -396,11 +305,11 @@ func (im *ipPoolManager) UpdateAllocatedIPs(ctx context.Context, containerID str
 				return err
 			}
 
-			if i == im.maxConflictRetrys {
-				return fmt.Errorf("insufficient retries(<=%d) to re-allocate StatefulSet pod '%s/%s' SpiderIPPool IP '%s'", im.maxConflictRetrys, pod.Namespace, pod.Name, singleIP)
+			if i == im.config.MaxConflictRetrys {
+				return fmt.Errorf("insufficient retries(<=%d) to re-allocate StatefulSet pod '%s/%s' SpiderIPPool IP '%s'", im.config.MaxConflictRetrys, pod.Namespace, pod.Name, singleIP)
 			}
 
-			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.conflictRetryUnitTime)
+			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * im.config.ConflictRetryUnitTime)
 			continue
 		}
 	}
diff --git a/pkg/ippoolmanager/types/interface.go b/pkg/ippoolmanager/types/interface.go
new file mode 100644
index 000000000..b0fcaf1cb
--- /dev/null
+++ b/pkg/ippoolmanager/types/interface.go
@@ -0,0 +1,31 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package types
+
+import (
+	"context"
+
+	corev1 "k8s.io/api/core/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+
+	"github.com/spidernet-io/spiderpool/api/v1/agent/models"
+	"github.com/spidernet-io/spiderpool/pkg/election"
+	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
+	crdclientset "github.com/spidernet-io/spiderpool/pkg/k8s/client/clientset/versioned"
+	subnetmanagertypes "github.com/spidernet-io/spiderpool/pkg/subnetmanager/types"
+	"github.com/spidernet-io/spiderpool/pkg/types"
+)
+
+type IPPoolManager interface {
+	SetupWebhook() error
+	SetupInformer(client crdclientset.Interface, controllerLeader election.SpiderLeaseElector) error
+	InjectSubnetManager(subnetManager subnetmanagertypes.SubnetManager)
+	GetIPPoolByName(ctx context.Context, poolName string) (*spiderpoolv1.SpiderIPPool, error)
+	ListIPPools(ctx context.Context, opts ...client.ListOption) (*spiderpoolv1.SpiderIPPoolList, error)
+	AllocateIP(ctx context.Context, poolName, containerID, nic string, pod *corev1.Pod) (*models.IPConfig, *spiderpoolv1.SpiderIPPool, error)
+	ReleaseIP(ctx context.Context, poolName string, ipAndCIDs []types.IPAndCID) error
+	CheckVlanSame(ctx context.Context, poolNameList []string) (map[types.Vlan][]string, bool, error)
+	RemoveFinalizer(ctx context.Context, poolName string) error
+	UpdateAllocatedIPs(ctx context.Context, containerID string, pod *corev1.Pod, oldIPConfig models.IPConfig) error
+}
diff --git a/pkg/limiter/config.go b/pkg/limiter/config.go
new file mode 100644
index 000000000..a4e7d39dd
--- /dev/null
+++ b/pkg/limiter/config.go
@@ -0,0 +1,11 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package limiter
+
+import "time"
+
+type LimiterConfig struct {
+	MaxQueueSize int
+	MaxWaitTime  time.Duration
+}
diff --git a/pkg/limiter/queue.go b/pkg/limiter/queue.go
index 455f42f59..12b5da17c 100644
--- a/pkg/limiter/queue.go
+++ b/pkg/limiter/queue.go
@@ -20,12 +20,12 @@ type Limiter interface {
 	Start(ctx context.Context) error
 }
 
-func NewLimiter(maxQueueSize int, maxWaitTime time.Duration) Limiter {
+func NewLimiter(c *LimiterConfig) Limiter {
 	q := &queue{
 		cond:           sync.NewCond(&lock.Mutex{}),
-		maxQueueSize:   maxQueueSize,
-		maxWaitTime:    maxWaitTime,
-		elements:       make([]*e, 0, maxQueueSize),
+		maxQueueSize:   c.MaxQueueSize,
+		maxWaitTime:    c.MaxWaitTime,
+		elements:       make([]*e, 0, c.MaxQueueSize),
 		grantedTickets: map[string]int{},
 	}
 
diff --git a/pkg/namespacemanager/namespace_manager.go b/pkg/namespacemanager/namespace_manager.go
index ac387eaf5..52b300d56 100644
--- a/pkg/namespacemanager/namespace_manager.go
+++ b/pkg/namespacemanager/namespace_manager.go
@@ -28,13 +28,13 @@ type namespaceManager struct {
 	client client.Client
 }
 
-func NewNamespaceManager(c client.Client) (NamespaceManager, error) {
-	if c == nil {
+func NewNamespaceManager(client client.Client) (NamespaceManager, error) {
+	if client == nil {
 		return nil, errors.New("k8s client must be specified")
 	}
 
 	return &namespaceManager{
-		client: c,
+		client: client,
 	}, nil
 }
 
diff --git a/pkg/nodemanager/node_manager.go b/pkg/nodemanager/node_manager.go
index 6fbdd8324..8abe2b6b8 100644
--- a/pkg/nodemanager/node_manager.go
+++ b/pkg/nodemanager/node_manager.go
@@ -23,12 +23,12 @@ type nodeManager struct {
 	client client.Client
 }
 
-func NewNodeManager(c client.Client) (NodeManager, error) {
-	if c == nil {
+func NewNodeManager(client client.Client) (NodeManager, error) {
+	if client == nil {
 		return nil, errors.New("k8s client must be specified")
 	}
 	return &nodeManager{
-		client: c,
+		client: client,
 	}, nil
 }
 
diff --git a/pkg/podmanager/config.go b/pkg/podmanager/config.go
new file mode 100644
index 000000000..02e583bbe
--- /dev/null
+++ b/pkg/podmanager/config.go
@@ -0,0 +1,10 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package podmanager
+
+import "github.com/spidernet-io/spiderpool/pkg/config"
+
+type PodManagerConfig struct {
+	config.UpdateCRConfig
+}
diff --git a/pkg/podmanager/pod_manager.go b/pkg/podmanager/pod_manager.go
index f3e0a34fe..fd04566dc 100644
--- a/pkg/podmanager/pod_manager.go
+++ b/pkg/podmanager/pod_manager.go
@@ -25,20 +25,21 @@ type PodManager interface {
 }
 
 type podManager struct {
-	client                client.Client
-	maxConflictRetrys     int
-	conflictRetryUnitTime time.Duration
+	config *PodManagerConfig
+	client client.Client
 }
 
-func NewPodManager(c client.Client, maxConflictRetrys int, conflictRetryUnitTime time.Duration) (PodManager, error) {
+func NewPodManager(c *PodManagerConfig, client client.Client) (PodManager, error) {
 	if c == nil {
+		return nil, errors.New("pod manager config must be specified")
+	}
+	if client == nil {
 		return nil, errors.New("k8s client must be specified")
 	}
 
 	return &podManager{
-		client:                c,
-		maxConflictRetrys:     maxConflictRetrys,
-		conflictRetryUnitTime: conflictRetryUnitTime,
+		config: c,
+		client: client,
 	}, nil
 }
 
@@ -62,7 +63,7 @@ func (pm *podManager) ListPods(ctx context.Context, opts ...client.ListOption) (
 
 func (pm *podManager) MergeAnnotations(ctx context.Context, namespace, podName string, annotations map[string]string) error {
 	rand.Seed(time.Now().UnixNano())
-	for i := 0; i <= pm.maxConflictRetrys; i++ {
+	for i := 0; i <= pm.config.MaxConflictRetrys; i++ {
 		pod, err := pm.GetPodByName(ctx, namespace, podName)
 		if err != nil {
 			return err
@@ -79,10 +80,10 @@ func (pm *podManager) MergeAnnotations(ctx context.Context, namespace, podName s
 			if !apierrors.IsConflict(err) {
 				return err
 			}
-			if i == pm.maxConflictRetrys {
-				return fmt.Errorf("insufficient retries(<=%d) to merge Pod annotations", pm.maxConflictRetrys)
+			if i == pm.config.MaxConflictRetrys {
+				return fmt.Errorf("insufficient retries(<=%d) to merge Pod annotations", pm.config.MaxConflictRetrys)
 			}
-			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * pm.conflictRetryUnitTime)
+			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * pm.config.ConflictRetryUnitTime)
 			continue
 		}
 		break
diff --git a/pkg/reservedipmanager/reservedip_manager.go b/pkg/reservedipmanager/reservedip_manager.go
index fadfe4b5b..a81f43c4f 100644
--- a/pkg/reservedipmanager/reservedip_manager.go
+++ b/pkg/reservedipmanager/reservedip_manager.go
@@ -31,7 +31,7 @@ type reservedIPManager struct {
 
 func NewReservedIPManager(mgr ctrl.Manager) (ReservedIPManager, error) {
 	if mgr == nil {
-		return nil, errors.New("runtime manager must be specified")
+		return nil, errors.New("k8s manager must be specified")
 	}
 
 	return &reservedIPManager{
diff --git a/pkg/reservedipmanager/reservedip_validate.go b/pkg/reservedipmanager/reservedip_validate.go
index 4adc62e3b..47d8cd789 100644
--- a/pkg/reservedipmanager/reservedip_validate.go
+++ b/pkg/reservedipmanager/reservedip_validate.go
@@ -8,12 +8,11 @@ import (
 	"fmt"
 	"strconv"
 
-	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
-
 	"k8s.io/apimachinery/pkg/util/validation/field"
 
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	spiderpoolip "github.com/spidernet-io/spiderpool/pkg/ip"
+	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
 	"github.com/spidernet-io/spiderpool/pkg/types"
 )
 
diff --git a/pkg/subnetmanager/config.go b/pkg/subnetmanager/config.go
new file mode 100644
index 000000000..d04c7543c
--- /dev/null
+++ b/pkg/subnetmanager/config.go
@@ -0,0 +1,8 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package subnetmanager
+
+type SubnetManagerConfig struct {
+	EnableSpiderSubnet bool
+}
diff --git a/pkg/subnetmanager/subnet_manager.go b/pkg/subnetmanager/subnet_manager.go
index a381193bc..a810e4420 100644
--- a/pkg/subnetmanager/subnet_manager.go
+++ b/pkg/subnetmanager/subnet_manager.go
@@ -12,29 +12,27 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
+	subnetmanagertypes "github.com/spidernet-io/spiderpool/pkg/subnetmanager/types"
 )
 
-type SubnetManager interface {
-	SetupWebhook() error
-	GetSubnetByName(ctx context.Context, subnetName string) (*spiderpoolv1.SpiderSubnet, error)
-	ListSubnets(ctx context.Context, opts ...client.ListOption) (*spiderpoolv1.SpiderSubnetList, error)
-}
-
 type subnetManager struct {
-	client             client.Client
-	runtimeMgr         ctrl.Manager
-	enableSpiderSubnet bool
+	config     *SubnetManagerConfig
+	client     client.Client
+	runtimeMgr ctrl.Manager
 }
 
-func NewSubnetManager(mgr ctrl.Manager, enableSpiderSubnet bool) (SubnetManager, error) {
+func NewSubnetManager(c *SubnetManagerConfig, mgr ctrl.Manager) (subnetmanagertypes.SubnetManager, error) {
+	if c == nil {
+		return nil, errors.New("subnet manager config must be specified")
+	}
 	if mgr == nil {
 		return nil, errors.New("k8s manager must be specified")
 	}
 
 	return &subnetManager{
-		client:             mgr.GetClient(),
-		runtimeMgr:         mgr,
-		enableSpiderSubnet: enableSpiderSubnet,
+		config:     c,
+		client:     mgr.GetClient(),
+		runtimeMgr: mgr,
 	}, nil
 }
 
diff --git a/pkg/subnetmanager/types/interface.go b/pkg/subnetmanager/types/interface.go
new file mode 100644
index 000000000..9f40088c6
--- /dev/null
+++ b/pkg/subnetmanager/types/interface.go
@@ -0,0 +1,18 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package types
+
+import (
+	"context"
+
+	"sigs.k8s.io/controller-runtime/pkg/client"
+
+	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
+)
+
+type SubnetManager interface {
+	SetupWebhook() error
+	GetSubnetByName(ctx context.Context, subnetName string) (*spiderpoolv1.SpiderSubnet, error)
+	ListSubnets(ctx context.Context, opts ...client.ListOption) (*spiderpoolv1.SpiderSubnetList, error)
+}
diff --git a/pkg/types/types.go b/pkg/types/types.go
new file mode 100644
index 000000000..5df11fca0
--- /dev/null
+++ b/pkg/types/types.go
@@ -0,0 +1,9 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package types
+
+type IPAndCID struct {
+	IP          string
+	ContainerID string
+}
diff --git a/pkg/workloadendpointmanager/config.go b/pkg/workloadendpointmanager/config.go
new file mode 100644
index 000000000..963ada5e9
--- /dev/null
+++ b/pkg/workloadendpointmanager/config.go
@@ -0,0 +1,11 @@
+// Copyright 2022 Authors of spidernet-io
+// SPDX-License-Identifier: Apache-2.0
+
+package workloadendpointmanager
+
+import "github.com/spidernet-io/spiderpool/pkg/config"
+
+type EndpointManagerConfig struct {
+	config.UpdateCRConfig
+	MaxHistoryRecords int
+}
diff --git a/pkg/workloadendpointmanager/workloadendpoint_manager.go b/pkg/workloadendpointmanager/workloadendpoint_manager.go
index efdb81337..ddfdca520 100644
--- a/pkg/workloadendpointmanager/workloadendpoint_manager.go
+++ b/pkg/workloadendpointmanager/workloadendpoint_manager.go
@@ -16,14 +16,15 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	apitypes "k8s.io/apimachinery/pkg/types"
+	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 
 	"github.com/spidernet-io/spiderpool/pkg/constant"
-	"github.com/spidernet-io/spiderpool/pkg/ippoolmanager"
 	spiderpoolv1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v1"
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	"github.com/spidernet-io/spiderpool/pkg/podmanager"
+	"github.com/spidernet-io/spiderpool/pkg/types"
 )
 
 type WorkloadEndpointManager interface {
@@ -34,34 +35,30 @@ type WorkloadEndpointManager interface {
 	PatchIPAllocation(ctx context.Context, allocation *spiderpoolv1.PodIPAllocation, we *spiderpoolv1.SpiderEndpoint) (*spiderpoolv1.SpiderEndpoint, error)
 	ClearCurrentIPAllocation(ctx context.Context, containerID string, we *spiderpoolv1.SpiderEndpoint) error
 	RemoveFinalizer(ctx context.Context, namespace, podName string) error
-	ListAllHistoricalIPs(ctx context.Context, namespace, podName string) (map[string][]ippoolmanager.IPAndCID, error)
+	ListAllHistoricalIPs(ctx context.Context, namespace, podName string) (map[string][]types.IPAndCID, error)
 	IsIPBelongWEPCurrent(ctx context.Context, namespace, podName, poolIP string) (bool, error)
 	CheckCurrentContainerID(ctx context.Context, namespace, podName, containerID string) (bool, error)
 	UpdateCurrentStatus(ctx context.Context, containerID string, pod *corev1.Pod) error
 }
 
 type workloadEndpointManager struct {
-	client                client.Client
-	scheme                *runtime.Scheme
-	maxHistoryRecords     int
-	maxConflictRetrys     int
-	conflictRetryUnitTime time.Duration
+	config *EndpointManagerConfig
+	client client.Client
+	scheme *runtime.Scheme
 }
 
-func NewWorkloadEndpointManager(c client.Client, scheme *runtime.Scheme, maxHistoryRecords, maxConflictRetrys int, conflictRetryUnitTime time.Duration) (WorkloadEndpointManager, error) {
+func NewWorkloadEndpointManager(c *EndpointManagerConfig, mgr ctrl.Manager) (WorkloadEndpointManager, error) {
 	if c == nil {
-		return nil, errors.New("k8s client must be specified")
+		return nil, errors.New("endpoint manager config must be specified")
 	}
-	if scheme == nil {
-		return nil, errors.New("object scheme must be specified")
+	if mgr == nil {
+		return nil, errors.New("k8s manager must be specified")
 	}
 
 	return &workloadEndpointManager{
-		client:                c,
-		scheme:                scheme,
-		maxHistoryRecords:     maxHistoryRecords,
-		maxConflictRetrys:     maxConflictRetrys,
-		conflictRetryUnitTime: conflictRetryUnitTime,
+		config: c,
+		client: mgr.GetClient(),
+		scheme: mgr.GetScheme(),
 	}, nil
 }
 
@@ -132,9 +129,9 @@ func (em *workloadEndpointManager) MarkIPAllocation(ctx context.Context, contain
 
 	we.Status.Current = allocation
 	we.Status.History = append([]spiderpoolv1.PodIPAllocation{*allocation}, we.Status.History...)
-	if len(we.Status.History) > em.maxHistoryRecords {
-		logger.Sugar().Warnf("threshold of historical IP allocation records(<=%d) exceeded", em.maxHistoryRecords)
-		we.Status.History = we.Status.History[:em.maxHistoryRecords]
+	if len(we.Status.History) > em.config.MaxHistoryRecords {
+		logger.Sugar().Warnf("threshold of historical IP allocation records(<=%d) exceeded", em.config.MaxHistoryRecords)
+		we.Status.History = we.Status.History[:em.config.MaxHistoryRecords]
 	}
 
 	if err := em.client.Status().Update(ctx, we); err != nil {
@@ -197,7 +194,7 @@ func (em *workloadEndpointManager) ClearCurrentIPAllocation(ctx context.Context,
 
 // RemoveFinalizer removes a specific finalizer field in finalizers string array.
 func (em *workloadEndpointManager) RemoveFinalizer(ctx context.Context, namespace, podName string) error {
-	for i := 0; i <= em.maxConflictRetrys; i++ {
+	for i := 0; i <= em.config.MaxConflictRetrys; i++ {
 		we, err := em.GetEndpointByName(ctx, namespace, podName)
 		if err != nil {
 			return err
@@ -212,10 +209,10 @@ func (em *workloadEndpointManager) RemoveFinalizer(ctx context.Context, namespac
 			if !apierrors.IsConflict(err) {
 				return err
 			}
-			if i == em.maxConflictRetrys {
-				return fmt.Errorf("insufficient retries(<=%d) to remove finalizer '%s' from Endpoint %s", em.maxConflictRetrys, constant.SpiderFinalizer, podName)
+			if i == em.config.MaxConflictRetrys {
+				return fmt.Errorf("insufficient retries(<=%d) to remove finalizer '%s' from Endpoint %s", em.config.MaxConflictRetrys, constant.SpiderFinalizer, podName)
 			}
-			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * em.conflictRetryUnitTime)
+			time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * em.config.ConflictRetryUnitTime)
 			continue
 		}
 		break
@@ -225,13 +222,13 @@ func (em *workloadEndpointManager) RemoveFinalizer(ctx context.Context, namespac
 }
 
 // ListAllHistoricalIPs collect wep history IPs and classify them with each pool name.
-func (em *workloadEndpointManager) ListAllHistoricalIPs(ctx context.Context, namespace, podName string) (map[string][]ippoolmanager.IPAndCID, error) {
+func (em *workloadEndpointManager) ListAllHistoricalIPs(ctx context.Context, namespace, podName string) (map[string][]types.IPAndCID, error) {
 	wep, err := em.GetEndpointByName(ctx, namespace, podName)
 	if err != nil {
 		return nil, err
 	}
 
-	recordHistoryIPs := func(historyIPs map[string][]ippoolmanager.IPAndCID, poolName, ipAndCIDR *string, podName, podNS, containerID string) {
+	recordHistoryIPs := func(historyIPs map[string][]types.IPAndCID, poolName, ipAndCIDR *string, podName, podNS, containerID string) {
 		if poolName != nil {
 			if ipAndCIDR == nil {
 				logutils.Logger.Sugar().Errorf("WEP data broken, pod '%s/%s' containerID '%s' used ippool '%s' with no ip", podNS, podName, containerID, *poolName)
@@ -242,15 +239,15 @@ func (em *workloadEndpointManager) ListAllHistoricalIPs(ctx context.Context, nam
 
 			ips, ok := historyIPs[*poolName]
 			if !ok {
-				ips = []ippoolmanager.IPAndCID{{IP: ip, ContainerID: containerID}}
+				ips = []types.IPAndCID{{IP: ip, ContainerID: containerID}}
 			} else {
-				ips = append(ips, ippoolmanager.IPAndCID{IP: ip, ContainerID: containerID})
+				ips = append(ips, types.IPAndCID{IP: ip, ContainerID: containerID})
 			}
 			historyIPs[*poolName] = ips
 		}
 	}
 
-	wepHistoryIPs := make(map[string][]ippoolmanager.IPAndCID)
+	wepHistoryIPs := make(map[string][]types.IPAndCID)
 
 	// circle to traverse each allocation
 	for _, PodIPAllocation := range wep.Status.History {
@@ -328,7 +325,7 @@ func (r *workloadEndpointManager) Delete(ctx context.Context, sep *spiderpoolv1.
 
 // UpdateCurrentStatus serves for StatefulSet pod re-create
 func (em *workloadEndpointManager) UpdateCurrentStatus(ctx context.Context, containerID string, pod *corev1.Pod) error {
-	for i := 0; i <= em.maxConflictRetrys; i++ {
+	for i := 0; i <= em.config.MaxConflictRetrys; i++ {
 		sep, err := em.GetEndpointByName(ctx, pod.Namespace, pod.Name)
 		if nil != err {
 			return err
@@ -355,11 +352,11 @@ func (em *workloadEndpointManager) UpdateCurrentStatus(ctx context.Context, cont
 					return err
 				}
 
-				if i == em.maxConflictRetrys {
-					return fmt.Errorf("insufficient retries(<=%d) to re-allocate StatefulSet SpiderEndpoint '%s/%s'", em.maxConflictRetrys, pod.Namespace, pod.Name)
+				if i == em.config.MaxConflictRetrys {
+					return fmt.Errorf("insufficient retries(<=%d) to re-allocate StatefulSet SpiderEndpoint '%s/%s'", em.config.MaxConflictRetrys, pod.Namespace, pod.Name)
 				}
 
-				time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * em.conflictRetryUnitTime)
+				time.Sleep(time.Duration(rand.Intn(1<<(i+1))) * em.config.ConflictRetryUnitTime)
 				continue
 			}
 		}


Test patch:
diff --git a/pkg/limiter/queue_test.go b/pkg/limiter/queue_test.go
index abf60b76c..2e78278d6 100644
--- a/pkg/limiter/queue_test.go
+++ b/pkg/limiter/queue_test.go
@@ -19,15 +19,14 @@ import (
 var _ = Describe("Queue", Label("unitest", "queue_test"), func() {
 	var ctx context.Context
 	var cancel context.CancelFunc
-	var maxQueueSize int
-	var maxWaitTime time.Duration
+	var config *limiter.LimiterConfig
 	var queue limiter.Limiter
 
 	var queuers int
 	var workHours time.Duration
 
 	JustBeforeEach(func() {
-		queue = limiter.NewLimiter(maxQueueSize, maxWaitTime)
+		queue = limiter.NewLimiter(config)
 		go func() {
 			defer GinkgoRecover()
 			err := queue.Start(ctx)
@@ -39,9 +38,10 @@ var _ = Describe("Queue", Label("unitest", "queue_test"), func() {
 		BeforeEach(func() {
 			ctx, cancel = context.WithCancel(context.Background())
 			DeferCleanup(cancel)
-
-			maxQueueSize = 3
-			maxWaitTime = 2 * time.Second
+			config = &limiter.LimiterConfig{
+				MaxQueueSize: 3,
+				MaxWaitTime:  2 * time.Second,
+			}
 			queuers = 3
 			workHours = 1 * time.Second
 		})
@@ -108,8 +108,10 @@ var _ = Describe("Queue", Label("unitest", "queue_test"), func() {
 			ctx, cancel = context.WithCancel(context.Background())
 			DeferCleanup(cancel)
 
-			maxQueueSize = 200
-			maxWaitTime = 5 * time.Second
+			config = &limiter.LimiterConfig{
+				MaxQueueSize: 200,
+				MaxWaitTime:  5 * time.Second,
+			}
 			queuers = 200
 			workHours = 50 * time.Millisecond
 
@@ -157,7 +159,7 @@ var _ = Describe("Queue", Label("unitest", "queue_test"), func() {
 				}
 			}
 
-			GinkgoWriter.Printf("%d queuers who take %v to work queue in a queue with a maximum waiting time %v\n", queuers, workHours, maxWaitTime)
+			GinkgoWriter.Printf("%d queuers who take %v to work queue in a queue with a maximum waiting time %v\n", queuers, workHours, config.MaxWaitTime)
 			GinkgoWriter.Printf("%d queuers completed their work without conflict\n", checkin)
 			GinkgoWriter.Printf("%d queuers work concurrently due to waiting timeout\n", checkinTimeout)
 		})
@@ -168,8 +170,10 @@ var _ = Describe("Queue", Label("unitest", "queue_test"), func() {
 			ctx, cancel = context.WithCancel(context.Background())
 			DeferCleanup(cancel)
 
-			maxQueueSize = 3
-			maxWaitTime = 2 * time.Second
+			config = &limiter.LimiterConfig{
+				MaxQueueSize: 3,
+				MaxWaitTime:  2 * time.Second,
+			}
 			queuers = 3
 			workHours = 1 * time.Second
 		})