Repository: spidernet-io/spiderpool
Pull request #1338 (2023-02-19 15:40:56)

doc
---
name: Pull request
about: Tell us about your contribution
labels: ["pr/release/none-required"]
---

---
## Thanks for contributing !

Before submitting a pull request, make sure you read about our Contribution notice here: <https://spidernet-io.github.io/spiderpool/contributing/development/pullrequest/#need-review>

**What this PR does / why we need it**:

**Which issue(s) this PR fixes**:

**Special notes for your reviewer**:

**make sure your commit is signed off**


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information


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=1338)

[![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=1338&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=1338&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=spidernet-io_spiderpool&pullRequest=1338&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=1338&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=1338&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=spidernet-io_spiderpool&pullRequest=1338&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=1338) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=spidernet-io_spiderpool&pullRequest=1338&metric=duplicated_lines_density&view=list) No Duplication information



Patch:
diff --git a/.github/workflows/lint-markdown.yaml b/.github/workflows/lint-markdown.yaml
index b90d32dd4..565ab7f71 100644
--- a/.github/workflows/lint-markdown.yaml
+++ b/.github/workflows/lint-markdown.yaml
@@ -45,6 +45,6 @@ jobs:
           config_file: '.github/markdownlint.yaml'
           ignore_path: '.github/markdownlintignore'
 
-      - name: Run Spell Lint
-        run: |
-          make lint-markdown-spell
+      #- name: Run Spell Lint
+      #  run: |
+      #    make lint-markdown-spell
diff --git a/CODEOWNERS b/CODEOWNERS
index 20e7ca08f..fcfe8f7ed 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -18,10 +18,10 @@
 /LICENSE @weizhoublue
 /Makefile* @weizhoublue
 /README.md @weizhoublue
+/README-zh_CN.md @weizhoublue
 /go.sum @weizhoublue
 /VERSION @weizhoublue
 /AUTHORS @weizhoublue
 /.licenserc.yaml @weizhoublue
 /codecov.yml @weizhoublue
 /.golangci.yaml @weizhoublue
-/MAINTAINERS.md @weizhoublue
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
deleted file mode 100644
index 6ea067c7f..000000000
--- a/MAINTAINERS.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Maintainers
-
-Official list of Maintainers.
-
-Please keep the below list sorted in ascending order.
-
-## Maintainers
-
-| Maintainer  | GitHub ID    | Affiliation | Email                     |
-|-------------|--------------|-------------|---------------------------|
-| weizhou lan | @weizhoblue  | DaoCloud    | <weizhou.lan@daocloud.io> |
-| ziqian xue  | @iiiceoo     | DaoCloud    | <ziqian.xue@daocloud.io>  |
-| kun wu      | @Icarus9913  | DaoCloud    | <kun.wu@daocloud.io>      |
-| tao yang    | @ty-dc       | DaoCloud    | <tao.yang@daocloud.io>    |
-| haifeng yao | @windsonsea  | DaoCloud    | <haifeng.yao@daocloud.io> |
diff --git a/README-zh_CN.md b/README-zh_CN.md
new file mode 100644
index 000000000..011c2afdc
--- /dev/null
+++ b/README-zh_CN.md
@@ -0,0 +1,183 @@
+# Spiderpool
+
+[![Go Report Card](https://goreportcard.com/badge/github.com/spidernet-io/spiderpool)](https://goreportcard.com/report/github.com/spidernet-io/spiderpool)
+[![CodeFactor](https://www.codefactor.io/repository/github/spidernet-io/spiderpool/badge)](https://www.codefactor.io/repository/github/spidernet-io/spiderpool)
+[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=spidernet-io_spiderpool&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=spidernet-io_spiderpool)
+[![codecov](https://codecov.io/gh/spidernet-io/spiderpool/branch/main/graph/badge.svg?token=YKXY2E4Q8G)](https://codecov.io/gh/spidernet-io/spiderpool)
+[![Auto Version Release](https://github.com/spidernet-io/spiderpool/actions/workflows/auto-version-release.yaml/badge.svg)](https://github.com/spidernet-io/spiderpool/actions/workflows/auto-version-release.yaml)
+[![Auto Nightly CI](https://github.com/spidernet-io/spiderpool/actions/workflows/auto-nightly-ci.yaml/badge.svg)](https://github.com/spidernet-io/spiderpool/actions/workflows/auto-nightly-ci.yaml)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6009/badge)](https://bestpractices.coreinfrastructure.org/projects/6009)
+![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/7e54bfe38fec206e7710c74ad55a5139/raw/spiderpoolcodeline.json)
+![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/93b7ba26a4600fabe100ff640f9b3bd3/raw/spiderpoolcomment.json)
+![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/e1d3c092d1b9f61f1c8e36f09d2809cb/raw/spiderpoole2e.json)
+![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/cd9ef69f5ba8724cb4ff896dca953ef4/raw/spiderpooltodo.json)
+![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/38d00a872e830eedb46870c886549561/raw/spiderpoolperformance.json)
+
+[**English**](./README.md) | **简体中文**
+
+
+## Spiderpool 介绍
+
+Spiderpool 是一个 kubernetes 的 IPAM 插件项目， 其针对 underlay 网络的 IP 地址管理需求而设计，能够为任何兼容第三方 IPAM 插件的 CNI 项目所使用。
+
+为什么希望研发 Spiderpool ? 面对 underlay 网络的很多 IPAM 需求，当前开源社区中并未提供全面、友好、智能的开源解决方案，因此，Spiderpool 克服了 underlay 网络分配 IP 地址的复杂性，
+希望 IP 分配的运维工作像一些 overlay 网络模型一样简单，它包括应用 IP 地址固定、IP 地址自动弹性扩缩容、 多网卡支持、双栈支持等特点，
+本项目希望能够给开源爱好者一个新的 IPAM 选择。
+
+## underlay 网络 和 overlay 网络场景的 IPAM 
+
+云原生网络中出现了两种技术类别，" overlay 网络方案" 和 " underlay网络方案"，
+云原生网络对于它们没有严格的定义，我们可以从很多 CNI 项目的实现原理中，简单抽象出这两种技术流派的特点，它们可以满足不同场景下的需求。
+ Spiderpool 是为 underlay 网络特点而设计，以下对两种方案进行比较，能够更好说明 Spiderpool 的特点和使用场景。
+
+### overlay 网络方案
+
+本方案实现了 POD 网络同宿主机网络的解耦，例如 [Calico](https://github.com/projectcalico/calico) , [Cilium](https://github.com/cilium/cilium) 等 CNI 插件，
+它们或者使用 vxlan 等隧道技术搭建起一个 overlay 网络平面，再借用 NAT 技术实现南北向的通信，它们或者借用 BGP 路由协议打通宿主机网络的路由，使得宿主机的网络能够转发 POD 的
+东西向和南北向流量。
+
+这类技术流派的 IPAM 分配特点是：
+
+1. 子网中的 IP 地址按照节点来分割
+
+    集群中拥有一个或者多个定义了 IP 子网号的 subnet 实例，以一个更小子网掩码长度为单位，把 subnet 分割出更小的 IP block 集合，依据
+    IP 分配或者释放的实际情况，每个 node 都会获取到一个或者多个 IP block。
+
+    这意味着两个特点：第一，每个 node 上的 IPAM 插件只需要在本地的 IP block 中分配和释放 IP 地址时，与其它 node 上的 IPAM 无 IP 分配冲突，IPAM 分配效率更高。
+    第二，某个具体的 IP 地址跟随 IP block 集合，会相对固定的一直在某个 node 上被分配，没法随同 POD 一起被调度漂移。
+
+2. IP 地址资源充沛
+
+    众所周知，IPv6 地址资源非常充沛，而 IPv4 地址资源相比稀缺。因为"overlay 网络方案"下 POD 子网可以独立规划，
+    只要能够合理利用 NAT 技术，kubernetes 单个集群可以拥有充沛的 IP 地址资源。
+    因此，应用不会因为 IP 不够而启动失败，IPAM 组件面临的异常 IP 回收压力较小。
+
+3. 没有应用" IP 地址固定"需求
+
+    对于应用 IP 地址固定需求，有无状态应用和有状态应用的区别：对于 deployment 这类无状态应用，因为 POD name 会随着 POD 重启而变化，
+    应用本身的业务逻辑也是无状态的，因此对于" IP 地址固定" 的需求，只能让所有 POD 副本固定在一个 IP 地址的集合内；对于 statefulset 这
+    类有状态应用，因为 POD name 等信息都是固定的，应用本身的业务逻辑也是有状态的，因此对于" IP 地址固定"需求，要实现单个 POD 和具体 IP 地址的强绑定。
+
+    在" overlay 网络方案"方案下，多是借助了 NAT 技术向集群外部暴露服务的入口和源地址，借助 DNS、clusterIP 等技术来实现集群东西向通信。
+    其次，IPAM 的 IP block 方式把 IP 相对固定到某个节点上，而不能保证应用副本的跟随调度。
+    因此，应用的" IP 地址固定"能力无用武之地，当前社区的主流 CNI 多数不支持" IP 地址固定"，或者支持方法较为简陋。
+
+这个方案的优点是，无论集群部署在什么样的底层网络环境上，CNI 插件的兼容性都非常好，且都能够为 POD 提供子网独立、IP 地址资源充沛的网络。
+
+这个方案的缺点是，对于一些传统应用的云化改造，提出了一些网络改造的挑战，包括 NAT 映射地址的适配和感知等。
+
+### underlay 网络方案
+
+本方案实现了 POD 共享宿主机网络，即 POD 直接获取宿主机网络中的 IP 地址，这样，应用可直接使用自己的 IP 地址进行东西向和南北向通信。
+
+underlay 网络方案的实施，有两种典型的场景，一种是集群部署实施在"传统网络"上，一种是集群部署在 IAAS 环境上，例如公有云。以下总结了"传统网络场景"的 IPAM 特点：
+
+1. 单个 IP 地址应该能够在任一节点上被分配
+
+    这个需求有多方面的原因：随着数据中心的网络设备增加、多集群技术的发展，IPv4 地址资源稀缺，要求 IPAM 提高 IP 资源的使用效率；
+    对于有" IP 地址固定"需求的应用，其 POD 副本可能会调度到集群的任意一个节点上，并且，在故障场景下还会发生节点间的漂移，要求 IP 地址一起漂移。
+
+    因此，在集群中的任意一个节点上，一个 IP 地址应该具备能够被分配给 POD 使用的可能，而不同于"overlay 网络方案"中， IP 地址被 IP block 单位
+    进行分割后，只能在某一个节点上被分配使用。
+
+2. 同一应用的不同副本，能实现跨子网获取 IP 地址
+
+    例如，一个集群中，宿主机1的区域只能使用子网 172.20.1.0/24，而宿主机2的区域只能使用子网 172.20.2.0/24， 在此背景下，
+    当一个应用跨子网部署副本时，要求 IPAM 能够在不同的节点上，为应用分配出子网匹配的 IP 地址。
+
+3. 应用 IP 地址固定
+
+    很多传统应用在云化改造前，是部署在裸金属环境上的，服务之间的网络未引入 NAT 地址转换，微服务架构中需要感知对方的源 IP 或目的 IP ，
+    并且，网络管理员也习惯了使用防火墙等手段来精细管控网络安全。
+
+    因此，应用上云后，无状态应用希望能够实现 IP 范围的固定，有状态应用希望能够实现 IP 地址的唯一对应，这样，能够减少对微服务架构的改造工作。
+
+4. 一个 POD 的多网卡获取不同子网的 IP 地址
+
+    既然是对接 underlay 网络，POD 就会有多网卡需求，以使其通达不同的 underlay 子网，这要求 IPAM 能够给应用的不同网卡分配不同子网下的 IP 地址。
+
+5. IP 地址冲突
+
+    在 underlay 网络中，更加容易出现 IP 冲突，例如，POD 与集群外部的主机 IP 发生了冲突，与其它对接了相同子网的集群冲突，
+    而 IPAM 组件很难感知外部这些冲突的 IP 地址，多需要借助 CNI 插件进行实时的 IP 冲突检测。
+
+6. 已用 IP 地址的释放回收
+
+    因为 underlay 网络 IP 地址资源的稀缺性，且应用有 IP 地址固定需求，所以，"应当"被释放的 IP 地址若未被 IPAM 组件回收，新启动的 POD 可能会因为缺少 IP 地址而失败。
+    这就要求 IPAM 组件拥有更加精准、高效、及时的 IP 回收机制。
+
+这个方案的优势有：无需网络 NAT 映射的引入，对应用的云化网络改造，提出了最大的便利；底层网络的火墙等设备，可对 POD 通信实现相对较为精细的管控；无需隧道技术，
+网络通信的吞吐量和延时性能也相对的提高了。
+
+这个方案的缺点有：IP 地址管理工作相对繁琐，对 IPAM 组件的实现挑战更多；POD 网络规划会受到底层网络的限制。
+
+## 架构
+
+关于 spiderpool 的设计架构，可参考 [设计](./docs/concepts/arch.md)
+
+## 支持 CNI
+
+任何支持第三方 IPAM 插件的 CNI 项目，都可以配合 spiderpool，例如：
+
+* [macvlan CNI](https://github.com/containernetworking/plugins/tree/main/plugins/main/macvlan)
+
+* [vlan CNI](https://github.com/containernetworking/plugins/tree/main/plugins/main/vlan)
+
+* [ipvlan CNI](https://github.com/containernetworking/plugins/tree/main/plugins/main/ipvlan)
+
+* [sriov CNI](https://github.com/k8snetworkplumbingwg/sriov-cni)
+
+* [ovs CNI](https://github.com/k8snetworkplumbingwg/ovs-cni)
+
+* [Multus CNI](https://github.com/k8snetworkplumbingwg/multus-cni)
+
+## 快速开始
+
+快速搭建 spiderpool，启动一个应用，可参考 [例子](./docs/usage/basic.md)
+
+## 核心功能
+
+* 多子网实例设计
+
+    管理员可创建多个子网，不同应用可指定使用不同子网的 IP 地址，且 IPv4 和 IPv6 子网实例解耦，满足 underlay 网络的各种复杂规划。可参考 [例子](./docs/usage/???)
+
+* 自动帮助应用 IP 地址固定，且 IP 地址的固定数量能够自动弹性扩缩
+
+    对于应用 IP 地址固定的需求，当前开源社区，一些项目的做法是在应用的 annotaiton 中 hard code IP 地址，这导致 IP 地址冲突要人工保证、应用扩缩容容时 IP 地址管理成本高，
+    这种做法容易出现运维事故。Spiderpool 提出了 CRD 化管理，解决了如上诸多问题，且让运维工作量最小化。
+
+    对无状态应用，可实现自动固定 IP 地址范围，且能够自动跟随应用副本数进行 IP 资源扩缩容和删除。可参考 [例子](./docs/usage/???)
+
+    对有状态应用，可自动为每个 POD 固定 IP 地址，并且也可固定整体的 IP 扩缩容范围。可参考 [例子](./docs/usage/???)
+
+* 对于没有 IP 地址固定需求的应用，可共同使用一个共享 IP 池。可参考 [例子](./docs/usage/???)
+
+* 对于一个跨子网部署的应用，支持为其不同副本分配不同子网的 IP 地址。可参考 [例子](./docs/usage/ippool-affinity-node.md)
+
+* 应用可设置多个 IP 池，实现 IP 资源的备用效果。可参考 [例子](./docs/usage/ippool-multi.md)
+
+* 设置全局的 IP 预留，使得集群不会分配出这些 IP 地址，这样能避免与集群外部的 IP 冲突。可参考 [例子](./docs/usage/reserved-ip.md)
+
+* 能够为一个具备多网卡的 POD 分配不同子网下的 IP 地址。可参考 [例子](./docs/usage/multi-interfaces-annotation.md)
+
+* 对第三方应用控制器的支持。可参考 [例子](./docs/usage/third-party-controller.md)
+
+* IP 池可配置为全局可共享，也可实现同指定租户的绑定。可参考 [例子](./docs/usage/ippool-affinity-namespace.md)
+
+* 合理的 IP 回收机制设计，可最大保证 IP 资源的可用性。可参考 ？？？
+
+* 以上所有的功能，都能够在 ipv4-only、ipv6-only、dual-stack 场景下工作
+
+## 其它功能
+
+* 指标
+
+* 支持 AMD64 和 ARM64
+
+* 基于 webhook 校验，对于 CR 实例进行强校验，在管理员失误、并发操作等场景下，能够避免出现 IP 泄露、IP 冲突、格式错误等问题。
+
+* 性能
+
+## License
+
+Spiderpool is licensed under the Apache License, Version 2.0. See [LICENSE](./LICENSE) for the full license text.
diff --git a/README.md b/README.md
index 88ec62c72..40dd4cf51 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,10 @@
 ![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/e1d3c092d1b9f61f1c8e36f09d2809cb/raw/spiderpoole2e.json)
 ![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/cd9ef69f5ba8724cb4ff896dca953ef4/raw/spiderpooltodo.json)
 ![badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/weizhoublue/38d00a872e830eedb46870c886549561/raw/spiderpoolperformance.json)
+***
+
+**English** | [**简体中文**](./README-zh_CN.md)
+
 
 ## Status
 
@@ -21,8 +25,6 @@ Currently, the Spiderpool is under beta stage, not ready for production environm
 
 The Spiderpool is an IP Address Management (IPAM) CNI plugin that assigns IP addresses for kubernetes clusters.
 
-Currently, it is under developing stage, not ready for production environment yet.
-
 Any Container Network Interface (CNI) plugin supporting third-party IPAM plugins can use the Spiderpool,
 such as [MacVLAN CNI](https://github.com/containernetworking/plugins/tree/main/plugins/main/macvlan),
 [VLAN CNI](https://github.com/containernetworking/plugins/tree/main/plugins/main/vlan), [IPVLAN CNI](https://github.com/containernetworking/plugins/tree/main/plugins/main/ipvlan) etc.
@@ -99,6 +101,7 @@ Refer to [architecture](docs/concepts/arch.md) for components.
 
 ## Installation
 
+
 Refer to [installation](./docs/usage/install.md).
 
 ## Quick Start
@@ -107,6 +110,7 @@ Refer to [demo](./docs/usage/basic.md).
 
 ## Development
 
+
 [Development guide](docs/develop/pullrequest.md) is a reference point for development helper commands.
 
 ## License
diff --git a/charts/spiderpool/crds/spiderpool.spidernet.io_spidersubnets.yaml b/charts/spiderpool/crds/spiderpool.spidernet.io_spidersubnets.yaml
index 68de22682..5690d9ae5 100644
--- a/charts/spiderpool/crds/spiderpool.spidernet.io_spidersubnets.yaml
+++ b/charts/spiderpool/crds/spiderpool.spidernet.io_spidersubnets.yaml
@@ -71,6 +71,7 @@ spec:
               ips:
                 items:
                   type: string
+                minItems: 1
                 type: array
               routes:
                 items:
@@ -93,6 +94,7 @@ spec:
                 minimum: 0
                 type: integer
             required:
+            - ips
             - subnet
             type: object
           status:
diff --git a/go.mod b/go.mod
index 2ec6ce726..5a687f141 100644
--- a/go.mod
+++ b/go.mod
@@ -32,7 +32,7 @@ require (
 	go.opentelemetry.io/otel/trace v1.13.0 // indirect
 	go.uber.org/atomic v1.10.0
 	go.uber.org/zap v1.24.0
-	golang.org/x/net v0.7.0
+	golang.org/x/net v0.6.0
 	golang.org/x/tools v0.6.0
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 	gopkg.in/yaml.v2 v2.4.0
diff --git a/go.sum b/go.sum
index 100d816f5..f6bdc253d 100644
--- a/go.sum
+++ b/go.sum
@@ -732,8 +732,8 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su
 golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
-golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
diff --git a/pkg/constant/k8s.go b/pkg/constant/k8s.go
index 2b6ddc3a5..52aa32e65 100644
--- a/pkg/constant/k8s.go
+++ b/pkg/constant/k8s.go
@@ -72,13 +72,10 @@ const (
 	LabelIPPoolOwnerApplication    = AnnotationPre + "/owner-application"
 	LabelIPPoolOwnerApplicationUID = AnnotationPre + "/owner-application-uid"
 	LabelIPPoolVersion             = AnnotationPre + "/ippool-version"
-	LabelIPPoolVersionV4           = "IPv4"
-	LabelIPPoolVersionV6           = "IPv6"
 	LabelIPPoolReclaimIPPool       = AnnoSpiderSubnetReclaimIPPool
 	LabelIPPoolInterface           = AnnotationPre + "/interface"
-
-	LabelSubnetCIDR = AnnotationPre + "/subnet-cidr"
-	LabelIPPoolCIDR = AnnotationPre + "/ippool-cidr"
+	LabelIPPoolVersionV4           = "IPv4"
+	LabelIPPoolVersionV6           = "IPv6"
 )
 
 const (
diff --git a/pkg/gcmanager/scanAll_IPPool.go b/pkg/gcmanager/scanAll_IPPool.go
index 7757df37b..58fc47128 100644
--- a/pkg/gcmanager/scanAll_IPPool.go
+++ b/pkg/gcmanager/scanAll_IPPool.go
@@ -16,6 +16,7 @@ import (
 	"github.com/spidernet-io/spiderpool/pkg/logutils"
 	metrics "github.com/spidernet-io/spiderpool/pkg/metric"
 	"github.com/spidernet-io/spiderpool/pkg/types"
+	"github.com/spidernet-io/spiderpool/pkg/workloadendpointmanager"
 )
 
 // monitorGCSignal will monitor signal from CLI, DefaultGCInterval
@@ -158,7 +159,8 @@ func (s *SpiderGC) executeScanAll(ctx context.Context) {
 				}
 
 				// case: The pod in IPPool's ip-allocationDetail is also exist in k8s, but the IP corresponding allocation containerID is different with wep current containerID
-				if endpoint.Status.Current != nil && endpoint.Status.Current.ContainerID != poolIPAllocation.ContainerID {
+				allocation := workloadendpointmanager.RetrieveIPAllocation(poolIPAllocation.ContainerID, poolIPAllocation.NIC, endpoint)
+				if allocation == nil {
 					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, []types.IPAndCID{{
diff --git a/pkg/ip/ip.go b/pkg/ip/ip.go
index 7278be1ef..1d576c227 100644
--- a/pkg/ip/ip.go
+++ b/pkg/ip/ip.go
@@ -80,9 +80,7 @@ func IsIP(version types.IPVersion, s string) error {
 // IPsDiffSet calculates the difference set of two IP address slices.
 // For example, the difference set between [172.18.40.1 172.18.40.2] and
 // [172.18.40.2 172.18.40.3] is [172.18.40.1].
-//
-// If sorted is true, the result set of IP addresses will be sorted.
-func IPsDiffSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
+func IPsDiffSet(ips1, ips2 []net.IP) []net.IP {
 	var ips []net.IP
 	marks := make(map[string]bool)
 	for _, ip := range ips1 {
@@ -101,11 +99,9 @@ func IPsDiffSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
 		ips = append(ips, net.ParseIP(k))
 	}
 
-	if sorted {
-		sort.Slice(ips, func(i, j int) bool {
-			return bytes.Compare(ips[i].To16(), ips[j].To16()) < 0
-		})
-	}
+	sort.Slice(ips, func(i, j int) bool {
+		return bytes.Compare(ips[i].To16(), ips[j].To16()) < 0
+	})
 
 	return ips
 }
@@ -113,9 +109,7 @@ func IPsDiffSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
 // IPsUnionSet calculates the union set of two IP address slices.
 // For example, the union set between [172.18.40.1 172.18.40.2] and
 // [172.18.40.2 172.18.40.3] is [172.18.40.1 172.18.40.2 172.18.40.3].
-//
-// If sorted is true, the result set of IP addresses will be sorted.
-func IPsUnionSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
+func IPsUnionSet(ips1, ips2 []net.IP) []net.IP {
 	var ips []net.IP
 	marks := make(map[string]bool)
 	ips1 = append(ips1, ips2...)
@@ -129,11 +123,9 @@ func IPsUnionSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
 		ips = append(ips, net.ParseIP(k))
 	}
 
-	if sorted {
-		sort.Slice(ips, func(i, j int) bool {
-			return bytes.Compare(ips[i].To16(), ips[j].To16()) < 0
-		})
-	}
+	sort.Slice(ips, func(i, j int) bool {
+		return bytes.Compare(ips[i].To16(), ips[j].To16()) < 0
+	})
 
 	return ips
 }
@@ -141,9 +133,7 @@ func IPsUnionSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
 // IPsIntersectionSet calculates the intersection set of two IP address
 // slices. For example, the intersection set between [172.18.40.1 172.18.40.2]
 // and [172.18.40.2 172.18.40.3] is [172.18.40.2].
-//
-// If sorted is true, the result set of IP addresses will be sorted.
-func IPsIntersectionSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
+func IPsIntersectionSet(ips1, ips2 []net.IP) []net.IP {
 	var ips []net.IP
 	set := make(map[string]bool)
 	for _, ip := range ips1 {
@@ -163,11 +153,9 @@ func IPsIntersectionSet(ips1, ips2 []net.IP, sorted bool) []net.IP {
 		ips = append(ips, net.ParseIP(k))
 	}
 
-	if sorted {
-		sort.Slice(ips, func(i, j int) bool {
-			return bytes.Compare(ips[i].To16(), ips[j].To16()) < 0
-		})
-	}
+	sort.Slice(ips, func(i, j int) bool {
+		return bytes.Compare(ips[i].To16(), ips[j].To16()) < 0
+	})
 
 	return ips
 }
diff --git a/pkg/ip/iprange.go b/pkg/ip/iprange.go
index 2f0d5aed8..905717889 100644
--- a/pkg/ip/iprange.go
+++ b/pkg/ip/iprange.go
@@ -158,7 +158,7 @@ func IsIPRangeOverlap(version types.IPVersion, ipRange1, ipRange2 string) (bool,
 	// verified in IsIPRange above.
 	ips1, _ := ParseIPRange(version, ipRange1)
 	ips2, _ := ParseIPRange(version, ipRange2)
-	if len(ips1) > len(IPsDiffSet(ips1, ips2, false)) {
+	if len(ips1) > len(IPsDiffSet(ips1, ips2)) {
 		return true, nil
 	}
 
diff --git a/pkg/ip/utils.go b/pkg/ip/utils.go
index 7178bfc87..9bb659a04 100644
--- a/pkg/ip/utils.go
+++ b/pkg/ip/utils.go
@@ -5,7 +5,6 @@ package ip
 
 import (
 	"net"
-	"strings"
 
 	"github.com/spidernet-io/spiderpool/pkg/types"
 )
@@ -19,19 +18,7 @@ func AssembleTotalIPs(ipVersion types.IPVersion, ipRanges, excludedIPRanges []st
 	if nil != err {
 		return nil, err
 	}
-	totalIPs := IPsDiffSet(ips, excludeIPs, false)
+	totalIPs := IPsDiffSet(ips, excludeIPs)
 
 	return totalIPs, nil
 }
-
-func CIDRToLabelValue(ipVersion types.IPVersion, subnet string) (string, error) {
-	if err := IsCIDR(ipVersion, subnet); err != nil {
-		return "", err
-	}
-
-	value := strings.Replace(subnet, ".", "-", 3)
-	value = strings.Replace(value, ":", "-", 7)
-	value = strings.Replace(value, "/", "-", 1)
-
-	return value, nil
-}
diff --git a/pkg/ippoolmanager/ippool_informer.go b/pkg/ippoolmanager/ippool_informer.go
index 97f6cdb22..7c4e4f001 100644
--- a/pkg/ippoolmanager/ippool_informer.go
+++ b/pkg/ippoolmanager/ippool_informer.go
@@ -497,7 +497,7 @@ func (ic *IPPoolController) scaleIPPoolIfNeeded(ctx context.Context, pool *spide
 			if nil != err {
 				return fmt.Errorf("%w: failed to parse IP ranges '%v', error: %v", constant.ErrWrongInput, allocatedIPRanges, err)
 			}
-			freeIPs := spiderpoolip.IPsDiffSet(totalIPs, allocatedIPs, true)
+			freeIPs := spiderpoolip.IPsDiffSet(totalIPs, allocatedIPs)
 			discardedIPs := freeIPs[:totalIPCount-desiredIPNum]
 			discardedIPRanges, err := spiderpoolip.ConvertIPsToIPRanges(*pool.Spec.IPVersion, discardedIPs)
 			if nil != err {
@@ -756,7 +756,7 @@ func (ic *IPPoolController) scaleIPPoolWithIPs(ctx context.Context, pool *spider
 			return fmt.Errorf("failed to parse IP ranges '%v', error: %v", pool.Spec.IPs, err)
 		}
 
-		sortedIPRanges, err := spiderpoolip.ConvertIPsToIPRanges(*pool.Spec.IPVersion, spiderpoolip.IPsDiffSet(totalIPs, discardedIPs, false))
+		sortedIPRanges, err := spiderpoolip.ConvertIPsToIPRanges(*pool.Spec.IPVersion, spiderpoolip.IPsDiffSet(totalIPs, discardedIPs))
 		if nil != err {
 			return fmt.Errorf("failed to convert IPs '%v' to IP ranges, error: %v", ipRanges, err)
 		}
@@ -822,7 +822,7 @@ func (ic *IPPoolController) generateIPsFromSubnetWhenScaleUpIP(ctx context.Conte
 		// the subnetPoolAllocatedIPs is greater than pool total IP counts indicates that
 		// the SpiderSubnet updated successfully but the IPPool failed to update in the last procession
 		if len(subnetPoolAllocatedIPs) > len(poolTotalIPs) {
-			lastAllocatedIPs := spiderpoolip.IPsDiffSet(subnetPoolAllocatedIPs, poolTotalIPs, false)
+			lastAllocatedIPs := spiderpoolip.IPsDiffSet(subnetPoolAllocatedIPs, poolTotalIPs)
 			log.Sugar().Warnf("SpiderSubnet '%s' Status ControlledIPPool '%s' has the allocated IPs '%v', try to re-use it!", subnetName, pool.Name, lastAllocatedIPs)
 			if len(lastAllocatedIPs) == desiredIPNum-len(poolTotalIPs) {
 				// last allocated IPs is same with the current allocation request
@@ -853,7 +853,7 @@ func (ic *IPPoolController) generateIPsFromSubnetWhenScaleUpIP(ctx context.Conte
 	}
 
 	if len(reservedIPs) != 0 {
-		freeIPs = spiderpoolip.IPsDiffSet(freeIPs, reservedIPs, true)
+		freeIPs = spiderpoolip.IPsDiffSet(freeIPs, reservedIPs)
 	}
 
 	if len(pool.Spec.ExcludeIPs) != 0 {
@@ -861,7 +861,7 @@ func (ic *IPPoolController) generateIPsFromSubnetWhenScaleUpIP(ctx context.Conte
 		if nil != err {
 			return nil, fmt.Errorf("failed to parse exclude IP ranges '%v', error: %v", pool.Spec.ExcludeIPs, err)
 		}
-		freeIPs = spiderpoolip.IPsDiffSet(freeIPs, excludeIPs, true)
+		freeIPs = spiderpoolip.IPsDiffSet(freeIPs, excludeIPs)
 	}
 
 	// check the filtered subnet free IP number is enough or not
diff --git a/pkg/ippoolmanager/ippool_manager.go b/pkg/ippoolmanager/ippool_manager.go
index 3c515ab4e..04d778f02 100644
--- a/pkg/ippoolmanager/ippool_manager.go
+++ b/pkg/ippoolmanager/ippool_manager.go
@@ -163,7 +163,7 @@ func (im *ipPoolManager) genRandomIP(ctx context.Context, ipPool *spiderpoolv1.S
 		return nil, err
 	}
 
-	availableIPs := spiderpoolip.IPsDiffSet(totalIPs, append(reservedIPs, usedIPs...), false)
+	availableIPs := spiderpoolip.IPsDiffSet(totalIPs, append(reservedIPs, usedIPs...))
 	if len(availableIPs) == 0 {
 		return nil, constant.ErrIPUsedOut
 	}
diff --git a/pkg/ippoolmanager/ippool_mutate.go b/pkg/ippoolmanager/ippool_mutate.go
index a12325d4e..a2cc2a71b 100644
--- a/pkg/ippoolmanager/ippool_mutate.go
+++ b/pkg/ippoolmanager/ippool_mutate.go
@@ -5,12 +5,12 @@ package ippoolmanager
 
 import (
 	"context"
+	"errors"
 	"fmt"
 
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	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"
@@ -29,6 +29,12 @@ func (iw *IPPoolWebhook) mutateIPPool(ctx context.Context, ipPool *spiderpoolv1.
 		return nil
 	}
 
+	if iw.EnableSpiderSubnet {
+		if err := iw.setControllerSubnet(ctx, ipPool); err != nil {
+			return apierrors.NewInternalError(fmt.Errorf("failed to set the reference of the controller Subnet: %v", err))
+		}
+	}
+
 	if !controllerutil.ContainsFinalizer(ipPool, constant.SpiderFinalizer) {
 		controllerutil.AddFinalizer(ipPool, constant.SpiderFinalizer)
 		logger.Sugar().Infof("Add finalizer %s", constant.SpiderFinalizer)
@@ -41,7 +47,7 @@ func (iw *IPPoolWebhook) mutateIPPool(ctx context.Context, ipPool *spiderpoolv1.
 		} else if spiderpoolip.IsIPv6CIDR(ipPool.Spec.Subnet) {
 			version = constant.IPv6
 		} else {
-			return fmt.Errorf("failed to generate 'spec.ipVersion' from 'spec.subnet' %s, nothing to mutate", ipPool.Spec.Subnet)
+			return errors.New("invalid 'spec.ipVersion', noting to mutate")
 		}
 
 		ipPool.Spec.IPVersion = new(types.IPVersion)
@@ -49,25 +55,6 @@ func (iw *IPPoolWebhook) mutateIPPool(ctx context.Context, ipPool *spiderpoolv1.
 		logger.Sugar().Infof("Set 'spec.ipVersion' to %d", version)
 	}
 
-	cidr, err := spiderpoolip.CIDRToLabelValue(*ipPool.Spec.IPVersion, ipPool.Spec.Subnet)
-	if err != nil {
-		return fmt.Errorf("failed to parse 'spec.subnet' %s as a valid label value: %v", ipPool.Spec.Subnet, err)
-	}
-
-	if v, ok := ipPool.Labels[constant.LabelIPPoolCIDR]; !ok || v != cidr {
-		if ipPool.Labels == nil {
-			ipPool.Labels = make(map[string]string)
-		}
-		ipPool.Labels[constant.LabelIPPoolCIDR] = cidr
-		logger.Sugar().Infof("Set label %s: %s", constant.LabelIPPoolCIDR, cidr)
-	}
-
-	if iw.EnableSpiderSubnet {
-		if err := iw.setControllerSubnet(ctx, ipPool); err != nil {
-			return apierrors.NewInternalError(fmt.Errorf("failed to set the reference of the controller Subnet: %v", err))
-		}
-	}
-
 	if len(ipPool.Spec.IPs) > 1 {
 		mergedIPs, err := spiderpoolip.MergeIPRanges(*ipPool.Spec.IPVersion, ipPool.Spec.IPs)
 		if err != nil {
@@ -100,35 +87,29 @@ func (iw *IPPoolWebhook) setControllerSubnet(ctx context.Context, ipPool *spider
 		return nil
 	}
 
-	cidr, err := spiderpoolip.CIDRToLabelValue(*ipPool.Spec.IPVersion, ipPool.Spec.Subnet)
-	if err != nil {
-		return fmt.Errorf("failed to parse CIDR %s as a valid label value: %v", ipPool.Spec.Subnet, err)
-	}
-
 	var subnetList spiderpoolv1.SpiderSubnetList
-	if err := iw.Client.List(
-		ctx,
-		&subnetList,
-		client.MatchingLabels{constant.LabelSubnetCIDR: cidr},
-	); err != nil {
+	if err := iw.Client.List(ctx, &subnetList); err != nil {
 		return fmt.Errorf("failed to list Subnets: %v", err)
 	}
 
-	if len(subnetList.Items) == 0 {
-		return nil
-	}
-
-	subnet := subnetList.Items[0]
-	if !metav1.IsControlledBy(ipPool, &subnet) {
-		if err := ctrl.SetControllerReference(&subnet, ipPool, iw.Scheme); err != nil {
-			return fmt.Errorf("failed to set owner reference: %v", err)
+	for _, subnet := range subnetList.Items {
+		if subnet.Spec.Subnet == ipPool.Spec.Subnet {
+			if !metav1.IsControlledBy(ipPool, &subnet) {
+				if err := ctrl.SetControllerReference(&subnet, ipPool, iw.Scheme); err != nil {
+					return fmt.Errorf("failed to set owner reference: %v", err)
+				}
+				logger.Sugar().Infof("Set owner reference as Subnet %s", subnet.Name)
+			}
+
+			if ipPool.Labels == nil {
+				ipPool.Labels = make(map[string]string)
+			}
+			if v, ok := ipPool.Labels[constant.LabelIPPoolOwnerSpiderSubnet]; !ok || v != subnet.Name {
+				ipPool.Labels[constant.LabelIPPoolOwnerSpiderSubnet] = subnet.Name
+				logger.Sugar().Infof("Set label %s: %s", constant.LabelIPPoolOwnerSpiderSubnet, subnet.Name)
+			}
+			break
 		}
-		logger.Sugar().Infof("Set owner reference as Subnet %s", subnet.Name)
-	}
-
-	if v, ok := ipPool.Labels[constant.LabelIPPoolOwnerSpiderSubnet]; !ok || v != subnet.Name {
-		ipPool.Labels[constant.LabelIPPoolOwnerSpiderSubnet] = subnet.Name
-		logger.Sugar().Infof("Set label %s: %s", constant.LabelIPPoolOwnerSpiderSubnet, subnet.Name)
 	}
 
 	return nil
diff --git a/pkg/ippoolmanager/ippool_subnet_validate.go b/pkg/ippoolmanager/ippool_subnet_validate.go
index 4d08921ac..424bf18a5 100644
--- a/pkg/ippoolmanager/ippool_subnet_validate.go
+++ b/pkg/ippoolmanager/ippool_subnet_validate.go
@@ -66,6 +66,10 @@ func (iw *IPPoolWebhook) validateSubnetControllerExist(ctx context.Context, ipPo
 		return nil, field.InternalError(subnetField, fmt.Errorf("failed to get controller Subnet %s: %v", owner.Name, err))
 	}
 
+	if subnet.Spec.Subnet != ipPool.Spec.Subnet {
+		return nil, field.InternalError(subnetField, fmt.Errorf("invalid controller Subnet %s with different 'spec.subnet' %s", owner.Name, subnet.Spec.Subnet))
+	}
+
 	if subnet.DeletionTimestamp != nil {
 		return nil, field.Forbidden(
 			subnetField,
@@ -86,7 +90,7 @@ func validateSubnetTotalIPsContainsIPPoolTotalIPs(subnet *spiderpoolv1.SpiderSub
 		return field.InternalError(ipsField, fmt.Errorf("failed to assemble the total IP addresses of the Subnet %s: %v", subnet.Name, err))
 	}
 
-	outIPs := spiderpoolip.IPsDiffSet(poolTotalIPs, subnetTotalIPs, false)
+	outIPs := spiderpoolip.IPsDiffSet(poolTotalIPs, subnetTotalIPs)
 	if len(outIPs) > 0 {
 		ranges, _ := spiderpoolip.ConvertIPsToIPRanges(*ipPool.Spec.IPVersion, outIPs)
 		return field.Forbidden(
diff --git a/pkg/ippoolmanager/ippool_validate.go b/pkg/ippoolmanager/ippool_validate.go
index f8adac9d3..df6624781 100644
--- a/pkg/ippoolmanager/ippool_validate.go
+++ b/pkg/ippoolmanager/ippool_validate.go
@@ -9,7 +9,6 @@ import (
 	"strconv"
 
 	"k8s.io/apimachinery/pkg/util/validation/field"
-	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	"github.com/spidernet-io/spiderpool/pkg/constant"
 	spiderpoolip "github.com/spidernet-io/spiderpool/pkg/ip"
@@ -31,7 +30,7 @@ func (iw *IPPoolWebhook) validateCreateIPPool(ctx context.Context, ipPool *spide
 		return field.ErrorList{err}
 	}
 
-	if err := iw.validateIPPoolCIDR(ctx, ipPool); err != nil {
+	if err := iw.validateIPPoolSubnet(ctx, ipPool); err != nil {
 		return field.ErrorList{err}
 	}
 
@@ -161,7 +160,7 @@ func (iw *IPPoolWebhook) validateIPPoolIPVersion(version *types.IPVersion) *fiel
 	return nil
 }
 
-func (iw *IPPoolWebhook) validateIPPoolCIDR(ctx context.Context, ipPool *spiderpoolv1.SpiderIPPool) *field.Error {
+func (iw *IPPoolWebhook) validateIPPoolSubnet(ctx context.Context, ipPool *spiderpoolv1.SpiderIPPool) *field.Error {
 	if err := spiderpoolip.IsCIDR(*ipPool.Spec.IPVersion, ipPool.Spec.Subnet); err != nil {
 		return field.Invalid(
 			subnetField,
@@ -170,11 +169,6 @@ func (iw *IPPoolWebhook) validateIPPoolCIDR(ctx context.Context, ipPool *spiderp
 		)
 	}
 
-	if iw.EnableSpiderSubnet {
-		return nil
-	}
-
-	// TODO(iiiceoo): Use label selector.
 	var ipPoolList spiderpoolv1.SpiderIPPoolList
 	if err := iw.Client.List(ctx, &ipPoolList); err != nil {
 		return field.InternalError(subnetField, fmt.Errorf("failed to list IPPools: %v", err))
@@ -216,18 +210,8 @@ func (iw *IPPoolWebhook) validateIPPoolAvailableIPs(ctx context.Context, ipPool
 		return err
 	}
 
-	cidr, err := spiderpoolip.CIDRToLabelValue(*ipPool.Spec.IPVersion, ipPool.Spec.Subnet)
-	if err != nil {
-		return field.InternalError(ipsField, fmt.Errorf("failed to parse CIDR %s as a valid label value: %v", ipPool.Spec.Subnet, err))
-	}
-
-	// TODO(iiiceoo): The list in validateIPPoolCIDR should be reused.
 	var ipPoolList spiderpoolv1.SpiderIPPoolList
-	if err := iw.Client.List(
-		ctx,
-		&ipPoolList,
-		client.MatchingLabels{constant.LabelIPPoolCIDR: cidr},
-	); err != nil {
+	if err := iw.Client.List(ctx, &ipPoolList); err != nil {
 		return field.InternalError(ipsField, fmt.Errorf("failed to list IPPools: %v", err))
 	}
 
@@ -237,13 +221,13 @@ func (iw *IPPoolWebhook) validateIPPoolAvailableIPs(ctx context.Context, ipPool
 	}
 
 	for _, pool := range ipPoolList.Items {
-		if pool.Name != ipPool.Name {
+		if pool.Spec.Subnet == ipPool.Spec.Subnet && pool.Name != ipPool.Name {
 			existIPs, err := spiderpoolip.AssembleTotalIPs(*pool.Spec.IPVersion, pool.Spec.IPs, pool.Spec.ExcludeIPs)
 			if err != nil {
 				return field.InternalError(ipsField, fmt.Errorf("failed to assemble the total IP addresses of the existing IPPool %s: %v", pool.Name, err))
 			}
 
-			overlapIPs := spiderpoolip.IPsIntersectionSet(newIPs, existIPs, false)
+			overlapIPs := spiderpoolip.IPsIntersectionSet(newIPs, existIPs)
 			if len(overlapIPs) > 0 {
 				overlapRanges, _ := spiderpoolip.ConvertIPsToIPRanges(*pool.Spec.IPVersion, overlapIPs)
 				return field.Forbidden(
@@ -258,6 +242,17 @@ func (iw *IPPoolWebhook) validateIPPoolAvailableIPs(ctx context.Context, ipPool
 }
 
 func (iw *IPPoolWebhook) validateIPPoolIPs(version types.IPVersion, subnet string, ips []string) *field.Error {
+	if len(ips) == 0 {
+		if iw.EnableSpiderSubnet {
+			return nil
+		}
+
+		return field.Required(
+			ipsField,
+			"requires at least one item",
+		)
+	}
+
 	for i, r := range ips {
 		if err := ValidateContainsIPRange(ipsField.Index(i), version, subnet, r); err != nil {
 			return err
diff --git a/pkg/k8s/apis/spiderpool.spidernet.io/v1/spidersubnet_types.go b/pkg/k8s/apis/spiderpool.spidernet.io/v1/spidersubnet_types.go
index d96403acb..035000e76 100644
--- a/pkg/k8s/apis/spiderpool.spidernet.io/v1/spidersubnet_types.go
+++ b/pkg/k8s/apis/spiderpool.spidernet.io/v1/spidersubnet_types.go
@@ -16,7 +16,8 @@ type SubnetSpec struct {
 	// +kubebuilder:validation:Required
 	Subnet string `json:"subnet"`
 
-	// +kubebuilder:validation:Optional
+	// +kubebuilder:validation:MinItems=1
+	// +kubebuilder:validation:Required
 	IPs []string `json:"ips"`
 
 	// +kubebuilder:validation:Optional
diff --git a/pkg/reservedipmanager/reservedip_mutate.go b/pkg/reservedipmanager/reservedip_mutate.go
index cc59435bf..363010575 100644
--- a/pkg/reservedipmanager/reservedip_mutate.go
+++ b/pkg/reservedipmanager/reservedip_mutate.go
@@ -35,7 +35,7 @@ func (rw *ReservedIPWebhook) mutateReservedIP(ctx context.Context, rIP *spiderpo
 		} else if spiderpoolip.IsIPv6IPRange(rIP.Spec.IPs[0]) {
 			version = constant.IPv6
 		} else {
-			return fmt.Errorf("failed to generate 'spec.ipVersion' from 'spec.ips[0]' %s, nothing to mutate", rIP.Spec.IPs[0])
+			return errors.New("invalid 'spec.ipVersion', noting to mutate")
 		}
 
 		rIP.Spec.IPVersion = new(types.IPVersion)
diff --git a/pkg/reservedipmanager/reservedip_validate.go b/pkg/reservedipmanager/reservedip_validate.go
index 6ba4e5e19..f046f0777 100644
--- a/pkg/reservedipmanager/reservedip_validate.go
+++ b/pkg/reservedipmanager/reservedip_validate.go
@@ -5,6 +5,7 @@ package reservedipmanager
 
 import (
 	"context"
+	"fmt"
 	"strconv"
 
 	"k8s.io/apimachinery/pkg/util/validation/field"
@@ -71,7 +72,7 @@ func validateReservedIPShouldNotBeChanged(oldRIP, newRIP *spiderpoolv1.SpiderRes
 }
 
 func (rw *ReservedIPWebhook) validateReservedIPSpec(ctx context.Context, rIP *spiderpoolv1.SpiderReservedIP) *field.Error {
-	return rw.validateReservedIPs(ctx, *rIP.Spec.IPVersion, rIP.Spec.IPs)
+	return rw.validateReservedIPAvailableIP(ctx, *rIP.Spec.IPVersion, rIP)
 }
 
 func (rw *ReservedIPWebhook) validateReservedIPIPVersion(version *types.IPVersion) *field.Error {
@@ -111,13 +112,38 @@ func (rw *ReservedIPWebhook) validateReservedIPIPVersion(version *types.IPVersio
 	return nil
 }
 
-func (rw *ReservedIPWebhook) validateReservedIPs(ctx context.Context, version types.IPVersion, ips []string) *field.Error {
-	for i, r := range ips {
-		if err := spiderpoolip.IsIPRange(version, r); err != nil {
-			return field.Invalid(
-				ipsField.Index(i),
-				ips[i],
-				err.Error(),
+func (rw *ReservedIPWebhook) validateReservedIPAvailableIP(ctx context.Context, version types.IPVersion, rIP *spiderpoolv1.SpiderReservedIP) *field.Error {
+	if len(rIP.Spec.IPs) == 0 {
+		return nil
+	}
+
+	newReservedIPs, err := spiderpoolip.ParseIPRanges(version, rIP.Spec.IPs)
+	if err != nil {
+		return field.Invalid(
+			ipsField,
+			rIP.Spec.IPs,
+			err.Error(),
+		)
+	}
+
+	var rIPList spiderpoolv1.SpiderReservedIPList
+	if err := rw.List(ctx, &rIPList); err != nil {
+		return field.InternalError(ipsField, fmt.Errorf("failed to list ReservedIPs: %v", err))
+	}
+
+	for _, r := range rIPList.Items {
+		if r.Name == rIP.Name || *r.Spec.IPVersion != version {
+			continue
+		}
+
+		existReservedIPs, err := spiderpoolip.ParseIPRanges(version, r.Spec.IPs)
+		if err != nil {
+			return field.InternalError(ipsField, fmt.Errorf("failed to parse 'spec.ips':\n%v\n of the existing ReservedIP %s: %v", r.Spec.IPs, r.Name, err))
+		}
+		if len(spiderpoolip.IPsIntersectionSet(newReservedIPs, existReservedIPs)) > 0 {
+			return field.Forbidden(
+				ipsField,
+				fmt.Sprintf("overlaps with the existing ReservedIP %s", r.Name),
 			)
 		}
 	}
diff --git a/pkg/subnetmanager/controllers/utils.go b/pkg/subnetmanager/controllers/utils.go
index 07716f53e..048f8b1af 100644
--- a/pkg/subnetmanager/controllers/utils.go
+++ b/pkg/subnetmanager/controllers/utils.go
@@ -80,7 +80,7 @@ func GenSubnetFreeIPs(subnet *spiderpoolv1.SpiderSubnet) ([]net.IP, error) {
 	if err != nil {
 		return nil, err
 	}
-	freeIPs := spiderpoolip.IPsDiffSet(totalIPs, usedIPs, true)
+	freeIPs := spiderpoolip.IPsDiffSet(totalIPs, usedIPs)
 
 	return freeIPs, nil
 }
diff --git a/pkg/subnetmanager/subnet_informer.go b/pkg/subnetmanager/subnet_informer.go
index 9e147e9a7..a1e64b548 100644
--- a/pkg/subnetmanager/subnet_informer.go
+++ b/pkg/subnetmanager/subnet_informer.go
@@ -338,7 +338,7 @@ func (sc *SubnetController) syncControlledIPPoolIPs(ctx context.Context, subnet
 			return err
 		}
 
-		validIPs := spiderpoolip.IPsIntersectionSet(subnetTotalIPs, poolTotalIPs, false)
+		validIPs := spiderpoolip.IPsIntersectionSet(subnetTotalIPs, poolTotalIPs)
 		tmpCount += len(validIPs)
 
 		ranges, err := spiderpoolip.ConvertIPsToIPRanges(*pool.Spec.IPVersion, validIPs)
diff --git a/pkg/subnetmanager/subnet_mutate.go b/pkg/subnetmanager/subnet_mutate.go
index c5decbac8..ec26ab629 100644
--- a/pkg/subnetmanager/subnet_mutate.go
+++ b/pkg/subnetmanager/subnet_mutate.go
@@ -5,6 +5,7 @@ package subnetmanager
 
 import (
 	"context"
+	"errors"
 	"fmt"
 
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -37,7 +38,7 @@ func (sw *SubnetWebhook) mutateSubnet(ctx context.Context, subnet *spiderpoolv1.
 		} else if spiderpoolip.IsIPv6CIDR(subnet.Spec.Subnet) {
 			version = constant.IPv6
 		} else {
-			return fmt.Errorf("failed to generate 'spec.ipVersion' from 'spec.subnet' %s, nothing to mutate", subnet.Spec.Subnet)
+			return errors.New("invalid 'spec.ipVersion', noting to mutate")
 		}
 
 		subnet.Spec.IPVersion = new(types.IPVersion)
@@ -45,19 +46,6 @@ func (sw *SubnetWebhook) mutateSubnet(ctx context.Context, subnet *spiderpoolv1.
 		logger.Sugar().Infof("Set 'spec.ipVersion' to %d", version)
 	}
 
-	cidr, err := spiderpoolip.CIDRToLabelValue(*subnet.Spec.IPVersion, subnet.Spec.Subnet)
-	if err != nil {
-		return fmt.Errorf("failed to parse 'spec.subnet' %s as a valid label value: %v", subnet.Spec.Subnet, err)
-	}
-
-	if v, ok := subnet.Labels[constant.LabelSubnetCIDR]; !ok || v != cidr {
-		if subnet.Labels == nil {
-			subnet.Labels = make(map[string]string)
-		}
-		subnet.Labels[constant.LabelSubnetCIDR] = cidr
-		logger.Sugar().Infof("Set label %s: %s", constant.LabelSubnetCIDR, cidr)
-	}
-
 	if len(subnet.Spec.IPs) > 1 {
 		mergedIPs, err := spiderpoolip.MergeIPRanges(*subnet.Spec.IPVersion, subnet.Spec.IPs)
 		if err != nil {
diff --git a/pkg/subnetmanager/subnet_validate.go b/pkg/subnetmanager/subnet_validate.go
index f41534adc..3d8012683 100644
--- a/pkg/subnetmanager/subnet_validate.go
+++ b/pkg/subnetmanager/subnet_validate.go
@@ -32,7 +32,7 @@ func (sw *SubnetWebhook) validateCreateSubnet(ctx context.Context, subnet *spide
 		return field.ErrorList{err}
 	}
 
-	if err := sw.validateSubnetCIDR(ctx, subnet); err != nil {
+	if err := sw.validateSubnetSubnet(ctx, subnet); err != nil {
 		return field.ErrorList{err}
 	}
 
@@ -117,7 +117,7 @@ func validateSubnetIPInUse(subnet *spiderpoolv1.SpiderSubnet) *field.Error {
 		if err != nil {
 			return field.InternalError(controlledIPPoolsField, fmt.Errorf("failed to parse the pre-allocation of the IPPool %s: %v", poolName, err))
 		}
-		invalidIPs := spiderpoolip.IPsDiffSet(poolTotalIPs, totalIPs, false)
+		invalidIPs := spiderpoolip.IPsDiffSet(poolTotalIPs, totalIPs)
 		if len(invalidIPs) > 0 {
 			ranges, _ := spiderpoolip.ConvertIPsToIPRanges(*subnet.Spec.IPVersion, invalidIPs)
 			return field.Forbidden(
@@ -166,7 +166,7 @@ func (sw *SubnetWebhook) validateSubnetIPVersion(version *types.IPVersion) *fiel
 	return nil
 }
 
-func (sw *SubnetWebhook) validateSubnetCIDR(ctx context.Context, subnet *spiderpoolv1.SpiderSubnet) *field.Error {
+func (sw *SubnetWebhook) validateSubnetSubnet(ctx context.Context, subnet *spiderpoolv1.SpiderSubnet) *field.Error {
 	if err := spiderpoolip.IsCIDR(*subnet.Spec.IPVersion, subnet.Spec.Subnet); err != nil {
 		return field.Invalid(
 			subnetField,
@@ -175,7 +175,6 @@ func (sw *SubnetWebhook) validateSubnetCIDR(ctx context.Context, subnet *spiderp
 		)
 	}
 
-	// TODO(iiiceoo): Use label selector.
 	subnetList := spiderpoolv1.SpiderSubnetList{}
 	if err := sw.List(ctx, &subnetList); err != nil {
 		return field.InternalError(subnetField, fmt.Errorf("failed to list Subnets: %v", err))
@@ -206,6 +205,13 @@ func (sw *SubnetWebhook) validateSubnetCIDR(ctx context.Context, subnet *spiderp
 }
 
 func validateSubnetIPs(version types.IPVersion, subnet string, ips []string) *field.Error {
+	if len(ips) == 0 {
+		return field.Required(
+			ipsField,
+			"requires at least one item",
+		)
+	}
+
 	for i, r := range ips {
 		if err := ippoolmanager.ValidateContainsIPRange(ipsField.Index(i), version, subnet, r); err != nil {
 			return err
diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go
index 50f7c6aac..ae24a6fdf 100644
--- a/vendor/golang.org/x/net/html/token.go
+++ b/vendor/golang.org/x/net/html/token.go
@@ -598,11 +598,6 @@ scriptDataDoubleEscapeEnd:
 // readComment reads the next comment token starting with "<!--". The opening
 // "<!--" has already been consumed.
 func (z *Tokenizer) readComment() {
-	// When modifying this function, consider manually increasing the suffixLen
-	// constant in func TestComments, from 6 to e.g. 9 or more. That increase
-	// should only be temporary, not committed, as it exponentially affects the
-	// test running time.
-
 	z.data.start = z.raw.end
 	defer func() {
 		if z.data.end < z.data.start {
@@ -616,7 +611,11 @@ func (z *Tokenizer) readComment() {
 	for {
 		c := z.readByte()
 		if z.err != nil {
-			z.data.end = z.calculateAbruptCommentDataEnd()
+			// Ignore up to two dashes at EOF.
+			if dashCount > 2 {
+				dashCount = 2
+			}
+			z.data.end = z.raw.end - dashCount
 			return
 		}
 		switch c {
@@ -632,15 +631,12 @@ func (z *Tokenizer) readComment() {
 			if dashCount >= 2 {
 				c = z.readByte()
 				if z.err != nil {
-					z.data.end = z.calculateAbruptCommentDataEnd()
+					z.data.end = z.raw.end
 					return
-				} else if c == '>' {
+				}
+				if c == '>' {
 					z.data.end = z.raw.end - len("--!>")
 					return
-				} else if c == '-' {
-					dashCount = 1
-					beginning = false
-					continue
 				}
 			}
 		}
@@ -649,35 +645,6 @@ func (z *Tokenizer) readComment() {
 	}
 }
 
-func (z *Tokenizer) calculateAbruptCommentDataEnd() int {
-	raw := z.Raw()
-	const prefixLen = len("<!--")
-	if len(raw) >= prefixLen {
-		raw = raw[prefixLen:]
-		if hasSuffix(raw, "--!") {
-			return z.raw.end - 3
-		} else if hasSuffix(raw, "--") {
-			return z.raw.end - 2
-		} else if hasSuffix(raw, "-") {
-			return z.raw.end - 1
-		}
-	}
-	return z.raw.end
-}
-
-func hasSuffix(b []byte, suffix string) bool {
-	if len(b) < len(suffix) {
-		return false
-	}
-	b = b[len(b)-len(suffix):]
-	for i := range b {
-		if b[i] != suffix[i] {
-			return false
-		}
-	}
-	return true
-}
-
 // readUntilCloseAngle reads until the next ">".
 func (z *Tokenizer) readUntilCloseAngle() {
 	z.data.start = z.raw.end
diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go
index c1f6b90dc..184ac45fe 100644
--- a/vendor/golang.org/x/net/http2/frame.go
+++ b/vendor/golang.org/x/net/http2/frame.go
@@ -662,15 +662,6 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
 // It is the caller's responsibility not to violate the maximum frame size
 // and to not call other Write methods concurrently.
 func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
-	if err := f.startWriteDataPadded(streamID, endStream, data, pad); err != nil {
-		return err
-	}
-	return f.endWrite()
-}
-
-// startWriteDataPadded is WriteDataPadded, but only writes the frame to the Framer's internal buffer.
-// The caller should call endWrite to flush the frame to the underlying writer.
-func (f *Framer) startWriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
 	if !validStreamID(streamID) && !f.AllowIllegalWrites {
 		return errStreamID
 	}
@@ -700,7 +691,7 @@ func (f *Framer) startWriteDataPadded(streamID uint32, endStream bool, data, pad
 	}
 	f.wbuf = append(f.wbuf, data...)
 	f.wbuf = append(f.wbuf, pad...)
-	return nil
+	return f.endWrite()
 }
 
 // A SettingsFrame conveys configuration parameters that affect how
diff --git a/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go
index 7a1d97669..b184a2771 100644
--- a/vendor/golang.org/x/net/http2/hpack/hpack.go
+++ b/vendor/golang.org/x/net/http2/hpack/hpack.go
@@ -359,7 +359,6 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
 
 	var hf HeaderField
 	wantStr := d.emitEnabled || it.indexed()
-	var undecodedName undecodedString
 	if nameIdx > 0 {
 		ihf, ok := d.at(nameIdx)
 		if !ok {
@@ -367,27 +366,15 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
 		}
 		hf.Name = ihf.Name
 	} else {
-		undecodedName, buf, err = d.readString(buf)
+		hf.Name, buf, err = d.readString(buf, wantStr)
 		if err != nil {
 			return err
 		}
 	}
-	undecodedValue, buf, err := d.readString(buf)
+	hf.Value, buf, err = d.readString(buf, wantStr)
 	if err != nil {
 		return err
 	}
-	if wantStr {
-		if nameIdx <= 0 {
-			hf.Name, err = d.decodeString(undecodedName)
-			if err != nil {
-				return err
-			}
-		}
-		hf.Value, err = d.decodeString(undecodedValue)
-		if err != nil {
-			return err
-		}
-	}
 	d.buf = buf
 	if it.indexed() {
 		d.dynTab.add(hf)
@@ -472,52 +459,46 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
 	return 0, origP, errNeedMore
 }
 
-// readString reads an hpack string from p.
+// readString decodes an hpack string from p.
 //
-// It returns a reference to the encoded string data to permit deferring decode costs
-// until after the caller verifies all data is present.
-func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) {
+// wantStr is whether s will be used. If false, decompression and
+// []byte->string garbage are skipped if s will be ignored
+// anyway. This does mean that huffman decoding errors for non-indexed
+// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
+// is returning an error anyway, and because they're not indexed, the error
+// won't affect the decoding state.
+func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
 	if len(p) == 0 {
-		return u, p, errNeedMore
+		return "", p, errNeedMore
 	}
 	isHuff := p[0]&128 != 0
 	strLen, p, err := readVarInt(7, p)
 	if err != nil {
-		return u, p, err
+		return "", p, err
 	}
 	if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
-		// Returning an error here means Huffman decoding errors
-		// for non-indexed strings past the maximum string length
-		// are ignored, but the server is returning an error anyway
-		// and because the string is not indexed the error will not
-		// affect the decoding state.
-		return u, nil, ErrStringLength
+		return "", nil, ErrStringLength
 	}
 	if uint64(len(p)) < strLen {
-		return u, p, errNeedMore
+		return "", p, errNeedMore
 	}
-	u.isHuff = isHuff
-	u.b = p[:strLen]
-	return u, p[strLen:], nil
-}
-
-type undecodedString struct {
-	isHuff bool
-	b      []byte
-}
-
-func (d *Decoder) decodeString(u undecodedString) (string, error) {
-	if !u.isHuff {
-		return string(u.b), nil
+	if !isHuff {
+		if wantStr {
+			s = string(p[:strLen])
+		}
+		return s, p[strLen:], nil
 	}
-	buf := bufPool.Get().(*bytes.Buffer)
-	buf.Reset() // don't trust others
-	var s string
-	err := huffmanDecode(buf, d.maxStrLen, u.b)
-	if err == nil {
+
+	if wantStr {
+		buf := bufPool.Get().(*bytes.Buffer)
+		buf.Reset() // don't trust others
+		defer bufPool.Put(buf)
+		if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+			buf.Reset()
+			return "", nil, err
+		}
 		s = buf.String()
+		buf.Reset() // be nice to GC
 	}
-	buf.Reset() // be nice to GC
-	bufPool.Put(buf)
-	return s, err
+	return s, p[strLen:], nil
 }
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
index 8cb14f3c9..9bd7035bf 100644
--- a/vendor/golang.org/x/net/http2/server.go
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -843,13 +843,8 @@ type frameWriteResult struct {
 // and then reports when it's done.
 // At most one goroutine can be running writeFrameAsync at a time per
 // serverConn.
-func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {
-	var err error
-	if wd == nil {
-		err = wr.write.writeFrame(sc)
-	} else {
-		err = sc.framer.endWrite()
-	}
+func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
+	err := wr.write.writeFrame(sc)
 	sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}
 }
 
@@ -1256,16 +1251,9 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
 		sc.writingFrameAsync = false
 		err := wr.write.writeFrame(sc)
 		sc.wroteFrame(frameWriteResult{wr: wr, err: err})
-	} else if wd, ok := wr.write.(*writeData); ok {
-		// Encode the frame in the serve goroutine, to ensure we don't have
-		// any lingering asynchronous references to data passed to Write.
-		// See https://go.dev/issue/58446.
-		sc.framer.startWriteDataPadded(wd.streamID, wd.endStream, wd.p, nil)
-		sc.writingFrameAsync = true
-		go sc.writeFrameAsync(wr, wd)
 	} else {
 		sc.writingFrameAsync = true
-		go sc.writeFrameAsync(wr, nil)
+		go sc.writeFrameAsync(wr)
 	}
 }
 
diff --git a/vendor/modules.txt b/vendor/modules.txt
index cde1bbf66..86fcf2442 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -514,7 +514,7 @@ golang.org/x/crypto/scrypt
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.7.0
+# golang.org/x/net v0.6.0
 ## explicit; go 1.17
 golang.org/x/net/context
 golang.org/x/net/context/ctxhttp


Test patch:
diff --git a/pkg/ip/ip_test.go b/pkg/ip/ip_test.go
index b8e735885..49d13a408 100644
--- a/pkg/ip/ip_test.go
+++ b/pkg/ip/ip_test.go
@@ -190,7 +190,6 @@ var _ = Describe("IP", Label("ip_test"), func() {
 					net.IPv4(172, 18, 40, 2),
 					net.IPv4(172, 18, 40, 3),
 				},
-				true,
 			)
 			Expect(ips).To(Equal([]net.IP{net.IPv4(172, 18, 40, 1)}))
 		})
@@ -205,7 +204,6 @@ var _ = Describe("IP", Label("ip_test"), func() {
 					net.ParseIP("abcd:1234::2"),
 					net.ParseIP("abcd:1234::3"),
 				},
-				true,
 			)
 			Expect(ips).To(Equal([]net.IP{net.ParseIP("abcd:1234::1")}))
 		})
@@ -222,7 +220,6 @@ var _ = Describe("IP", Label("ip_test"), func() {
 					net.IPv4(172, 18, 40, 2),
 					net.IPv4(172, 18, 40, 3),
 				},
-				true,
 			)
 			Expect(ips).To(Equal(
 				[]net.IP{
@@ -243,7 +240,6 @@ var _ = Describe("IP", Label("ip_test"), func() {
 					net.ParseIP("abcd:1234::2"),
 					net.ParseIP("abcd:1234::3"),
 				},
-				true,
 			)
 			Expect(ips).To(Equal(
 				[]net.IP{
@@ -266,7 +262,6 @@ var _ = Describe("IP", Label("ip_test"), func() {
 					net.IPv4(172, 18, 40, 2),
 					net.IPv4(172, 18, 40, 3),
 				},
-				true,
 			)
 			Expect(ips).To(Equal([]net.IP{net.IPv4(172, 18, 40, 2)}))
 		})
@@ -281,7 +276,6 @@ var _ = Describe("IP", Label("ip_test"), func() {
 					net.ParseIP("abcd:1234::2"),
 					net.ParseIP("abcd:1234::3"),
 				},
-				true,
 			)
 			Expect(ips).To(Equal([]net.IP{net.ParseIP("abcd:1234::2")}))
 		})
diff --git a/pkg/ip/utils_test.go b/pkg/ip/utils_test.go
index afad9ef6d..6631300c1 100644
--- a/pkg/ip/utils_test.go
+++ b/pkg/ip/utils_test.go
@@ -65,32 +65,4 @@ var _ = Describe("IP utils", Label("ip_utils_test"), func() {
 			Expect(ips).To(Equal([]net.IP{net.ParseIP("abcd:1234::1")}))
 		})
 	})
-
-	Describe("Test CIDRToLabelValue", func() {
-		When("Verifying", func() {
-			It("inputs invalid IP version", func() {
-				cidr, err := spiderpoolip.CIDRToLabelValue(constant.InvalidIPVersion, "172.18.40.0/24")
-				Expect(err).To(MatchError(spiderpoolip.ErrInvalidIPVersion))
-				Expect(cidr).To(BeEmpty())
-			})
-
-			It("inputs invalid CIDR address", func() {
-				cidr, err := spiderpoolip.CIDRToLabelValue(constant.IPv4, constant.InvalidCIDR)
-				Expect(err).To(MatchError(spiderpoolip.ErrInvalidCIDRFormat))
-				Expect(cidr).To(BeEmpty())
-			})
-		})
-
-		It("parses IPv4 CIDR address", func() {
-			cidr, err := spiderpoolip.CIDRToLabelValue(constant.IPv4, "172.18.40.0/24")
-			Expect(err).NotTo(HaveOccurred())
-			Expect(cidr).To(Equal("172-18-40-0-24"))
-		})
-
-		It("parses IPv6 CIDR address", func() {
-			cidr, err := spiderpoolip.CIDRToLabelValue(constant.IPv6, "abcd:1234::/120")
-			Expect(err).NotTo(HaveOccurred())
-			Expect(cidr).To(Equal("abcd-1234---120"))
-		})
-	})
 })
diff --git a/pkg/ippoolmanager/ippool_webhook_test.go b/pkg/ippoolmanager/ippool_webhook_test.go
index 7bf02efbb..a77a0c827 100644
--- a/pkg/ippoolmanager/ippool_webhook_test.go
+++ b/pkg/ippoolmanager/ippool_webhook_test.go
@@ -22,7 +22,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/manager"
 
 	"github.com/spidernet-io/spiderpool/pkg/constant"
-	spiderpoolip "github.com/spidernet-io/spiderpool/pkg/ip"
 	"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"
@@ -64,8 +63,7 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					APIVersion: fmt.Sprintf("%s/%s", constant.SpiderpoolAPIGroup, constant.SpiderpoolAPIVersionV1),
 				},
 				ObjectMeta: metav1.ObjectMeta{
-					Name:   subnetName,
-					Labels: map[string]string{},
+					Name: subnetName,
 				},
 				Spec: spiderpoolv1.SubnetSpec{},
 			}
@@ -89,8 +87,7 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					APIVersion: fmt.Sprintf("%s/%s", constant.SpiderpoolAPIGroup, constant.SpiderpoolAPIVersionV1),
 				},
 				ObjectMeta: metav1.ObjectMeta{
-					Name:   existIPPoolName,
-					Labels: map[string]string{},
+					Name: existIPPoolName,
 				},
 				Spec: spiderpoolv1.IPPoolSpec{},
 			}
@@ -126,74 +123,14 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				Expect(err).NotTo(HaveOccurred())
 			})
 
-			It("adds finalizer", func() {
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
-
-				ctx := context.TODO()
-				err := ipPoolWebhook.Default(ctx, ipPoolT)
-				Expect(err).NotTo(HaveOccurred())
-
-				contains := controllerutil.ContainsFinalizer(ipPoolT, constant.SpiderFinalizer)
-				Expect(contains).To(BeTrue())
-			})
-
-			It("failed to parse 'spec.subnet' as a valid label value", func() {
-				ipPoolT.Spec.IPVersion = pointer.Int64(constant.InvalidIPVersion)
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
-
-				ctx := context.TODO()
-				err := ipPoolWebhook.Default(ctx, ipPoolT)
-				Expect(err).NotTo(HaveOccurred())
-
-				v, ok := ipPoolT.Labels[constant.LabelIPPoolCIDR]
-				Expect(ok).To(BeFalse())
-				Expect(v).To(BeEmpty())
-			})
-
-			It("sets CIDR label", func() {
-				subnet := "172.18.40.0/24"
-				ipPoolT.Spec.Subnet = subnet
-
-				ctx := context.TODO()
-				err := ipPoolWebhook.Default(ctx, ipPoolT)
-				Expect(err).NotTo(HaveOccurred())
-
-				cidr, err := spiderpoolip.CIDRToLabelValue(*ipPoolT.Spec.IPVersion, subnet)
-				Expect(err).NotTo(HaveOccurred())
-				Expect(cidr).NotTo(BeEmpty())
-
-				v, ok := ipPoolT.Labels[constant.LabelIPPoolCIDR]
-				Expect(ok).To(BeTrue())
-				Expect(v).To(Equal(cidr))
-			})
-
-			It("is orphan IPPool", func() {
-				ipPoolWebhook.EnableSpiderSubnet = true
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
-
-				ctx := context.TODO()
-				err := ipPoolWebhook.Default(ctx, ipPoolT)
-				Expect(err).NotTo(HaveOccurred())
-
-				owner := metav1.GetControllerOf(ipPoolT)
-				Expect(owner).To(BeNil())
-			})
-
 			It("failed to list Subnets due to some unknown errors", func() {
 				patches := gomonkey.ApplyMethodReturn(fakeClient, "List", constant.ErrUnknown)
 				defer patches.Reset()
 
-				ipVersion := constant.IPv4
-				subnet := "172.18.40.0/24"
-				cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-				Expect(err).NotTo(HaveOccurred())
-				Expect(cidr).NotTo(BeEmpty())
-
 				ipPoolWebhook.EnableSpiderSubnet = true
 				subnetT.SetUID(uuid.NewUUID())
-				subnetT.Labels[constant.LabelSubnetCIDR] = cidr
-				subnetT.Spec.IPVersion = pointer.Int64(ipVersion)
-				subnetT.Spec.Subnet = subnet
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+				subnetT.Spec.Subnet = "172.18.40.0/24"
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						"172.18.40.1-172.18.40.2",
@@ -202,10 +139,12 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				)
 
 				ctx := context.TODO()
-				err = fakeClient.Create(ctx, subnetT)
+				err := fakeClient.Create(ctx, subnetT)
 				Expect(err).NotTo(HaveOccurred())
 
-				ipPoolT.Spec.Subnet = subnet
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+				ipPoolT.Spec.Subnet = "172.18.40.0/24"
+
 				err = ipPoolWebhook.Default(ctx, ipPoolT)
 				Expect(err).NotTo(HaveOccurred())
 
@@ -221,17 +160,10 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				patches := gomonkey.ApplyFuncReturn(controllerutil.SetControllerReference, constant.ErrUnknown)
 				defer patches.Reset()
 
-				ipVersion := constant.IPv4
-				subnet := "172.18.40.0/24"
-				cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-				Expect(err).NotTo(HaveOccurred())
-				Expect(cidr).NotTo(BeEmpty())
-
 				ipPoolWebhook.EnableSpiderSubnet = true
 				subnetT.SetUID(uuid.NewUUID())
-				subnetT.Labels[constant.LabelSubnetCIDR] = cidr
-				subnetT.Spec.IPVersion = pointer.Int64(ipVersion)
-				subnetT.Spec.Subnet = subnet
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+				subnetT.Spec.Subnet = "172.18.40.0/24"
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						"172.18.40.1-172.18.40.2",
@@ -240,10 +172,12 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				)
 
 				ctx := context.TODO()
-				err = fakeClient.Create(ctx, subnetT)
+				err := fakeClient.Create(ctx, subnetT)
 				Expect(err).NotTo(HaveOccurred())
 
-				ipPoolT.Spec.Subnet = subnet
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+				ipPoolT.Spec.Subnet = "172.18.40.0/24"
+
 				err = ipPoolWebhook.Default(ctx, ipPoolT)
 				Expect(err).NotTo(HaveOccurred())
 
@@ -256,17 +190,10 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			It("sets the reference of the controller Subnet", func() {
-				ipVersion := constant.IPv4
-				subnet := "172.18.50.0/24"
-				cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-				Expect(err).NotTo(HaveOccurred())
-				Expect(cidr).NotTo(BeEmpty())
-
 				ipPoolWebhook.EnableSpiderSubnet = true
 				subnetT.SetUID(uuid.NewUUID())
-				subnetT.Labels[constant.LabelSubnetCIDR] = cidr
-				subnetT.Spec.IPVersion = pointer.Int64(ipVersion)
-				subnetT.Spec.Subnet = subnet
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+				subnetT.Spec.Subnet = "172.18.50.0/24"
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						"172.18.50.1-172.18.50.2",
@@ -275,14 +202,22 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				)
 
 				ctx := context.TODO()
-				err = fakeClient.Create(ctx, subnetT)
+				err := fakeClient.Create(ctx, subnetT)
 				Expect(err).NotTo(HaveOccurred())
 
-				ipPoolT.Spec.Subnet = subnet
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+				ipPoolT.Spec.Subnet = "172.18.50.0/24"
+
 				err = ipPoolWebhook.Default(ctx, ipPoolT)
 				Expect(err).NotTo(HaveOccurred())
 
 				controlled := metav1.IsControlledBy(ipPoolT, subnetT)
+
+				// TODO(Icarus9913): maybe fail
+				ownerReference := metav1.GetControllerOf(ipPoolT)
+				fmt.Printf("The SpiderIPPool '%+v' corresponding owner reference: '%+v'", ipPoolT, ownerReference)
+				fmt.Printf("Print SpiderSubnet details: '%+v'", subnetT)
+
 				Expect(controlled).To(BeTrue())
 
 				v, ok := ipPoolT.Labels[constant.LabelIPPoolOwnerSpiderSubnet]
@@ -293,6 +228,17 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				Expect(err).NotTo(HaveOccurred())
 			})
 
+			It("adds finalizer", func() {
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+
+				ctx := context.TODO()
+				err := ipPoolWebhook.Default(ctx, ipPoolT)
+				Expect(err).NotTo(HaveOccurred())
+
+				contains := controllerutil.ContainsFinalizer(ipPoolT, constant.SpiderFinalizer)
+				Expect(contains).To(BeTrue())
+			})
+
 			It("failed to set 'spec.ipVersion' due to the invalid 'spec.subnet'", func() {
 				ipPoolT.Spec.Subnet = constant.InvalidCIDR
 
@@ -322,7 +268,6 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 
 			It("failed to merge 'spec.ips' due to the invalid 'spec.ipVersion'", func() {
 				ipPoolT.Spec.IPVersion = pointer.Int64(constant.InvalidIPVersion)
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
 				ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
 					[]string{
 						"172.18.40.10",
@@ -345,7 +290,6 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 
 			It("failed to merge 'spec.ips' due to the invalid 'spec.ips'", func() {
 				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
 				ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
 					[]string{
 						constant.InvalidIPRange,
@@ -369,7 +313,7 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			It("merges IPv4 'spec.ips'", func() {
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 				ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
 					[]string{
 						"172.18.40.10",
@@ -390,7 +334,7 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			It("merges IPv6 'spec.ips'", func() {
-				ipPoolT.Spec.Subnet = "abcd:1234::/120"
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv6)
 				ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
 					[]string{
 						"abcd:1234::a",
@@ -412,7 +356,6 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 
 			It("failed to merge 'spec.excludeIPs' due to the invalid 'spec.ipVersion'", func() {
 				ipPoolT.Spec.IPVersion = pointer.Int64(constant.InvalidIPVersion)
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
 				ipPoolT.Spec.ExcludeIPs = append(ipPoolT.Spec.ExcludeIPs,
 					[]string{
 						"172.18.40.10",
@@ -435,7 +378,6 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 
 			It("failed to merge 'spec.excludeIPs' due to the invalid 'spec.ips'", func() {
 				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
 				ipPoolT.Spec.ExcludeIPs = append(ipPoolT.Spec.ExcludeIPs,
 					[]string{
 						constant.InvalidIPRange,
@@ -459,7 +401,7 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			It("merges IPv4 'spec.excludeIPs'", func() {
-				ipPoolT.Spec.Subnet = "172.18.40.0/24"
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 				ipPoolT.Spec.ExcludeIPs = append(ipPoolT.Spec.ExcludeIPs,
 					[]string{
 						"172.18.40.10",
@@ -480,7 +422,7 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			It("merges IPv6 'spec.excludeIPs'", func() {
-				ipPoolT.Spec.Subnet = "abcd:1234::/120"
+				ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv6)
 				ipPoolT.Spec.ExcludeIPs = append(ipPoolT.Spec.ExcludeIPs,
 					[]string{
 						"abcd:1234::a",
@@ -680,6 +622,40 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			When("Validating 'spec.ips'", func() {
+				It("inputs empty 'spec.ips' while feature SpiderSubnet is enabled", func() {
+					ipPoolWebhook.EnableSpiderSubnet = true
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+					subnetT.Spec.IPs = append(subnetT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, subnetT)
+					Expect(err).NotTo(HaveOccurred())
+
+					err = controllerutil.SetControllerReference(subnetT, ipPoolT, scheme)
+					Expect(err).NotTo(HaveOccurred())
+
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
+
+					err = ipPoolWebhook.ValidateCreate(ctx, ipPoolT)
+					Expect(err).NotTo(HaveOccurred())
+				})
+
+				It("inputs empty 'spec.ips'", func() {
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
+
+					ctx := context.TODO()
+					err := ipPoolWebhook.ValidateCreate(ctx, ipPoolT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
 				It("inputs invalid 'spec.ips'", func() {
 					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 					ipPoolT.Spec.Subnet = "172.18.40.0/24"
@@ -705,24 +681,21 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					Expect(apierrors.IsInvalid(err)).To(BeTrue())
 				})
 
-				It("exists invalid IPPool in the cluster", func() {
-					ipVersion := constant.IPv4
-					subnet := "172.18.40.0/24"
-					cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-					Expect(err).NotTo(HaveOccurred())
-					Expect(cidr).NotTo(BeEmpty())
+				PIt("failed to list IPPools due to some unknown errors", func() {})
 
-					existIPPoolT.Labels[constant.LabelIPPoolCIDR] = cidr
-					existIPPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					existIPPoolT.Spec.Subnet = subnet
+				PIt("failed to assemble the total IP addresses of the IPPool due to some unknown errors", func() {})
+
+				It("exists invalid IPPool in the cluster", func() {
+					existIPPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existIPPoolT.Spec.Subnet = "172.18.40.0/24"
 					existIPPoolT.Spec.IPs = append(existIPPoolT.Spec.IPs, constant.InvalidIPRange)
 
 					ctx := context.TODO()
-					err = fakeClient.Create(ctx, existIPPoolT)
+					err := fakeClient.Create(ctx, existIPPoolT)
 					Expect(err).NotTo(HaveOccurred())
 
-					ipPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					ipPoolT.Spec.Subnet = subnet
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
 					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
 						[]string{
 							"172.18.40.1-172.18.40.2",
@@ -735,23 +708,16 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				})
 
 				It("overlaps with existing IPPool", func() {
-					ipVersion := constant.IPv4
-					subnet := "172.18.40.0/24"
-					cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-					Expect(err).NotTo(HaveOccurred())
-					Expect(cidr).NotTo(BeEmpty())
-
-					existIPPoolT.Labels[constant.LabelIPPoolCIDR] = cidr
-					existIPPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					existIPPoolT.Spec.Subnet = subnet
+					existIPPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existIPPoolT.Spec.Subnet = "172.18.40.0/24"
 					existIPPoolT.Spec.IPs = append(existIPPoolT.Spec.IPs, "172.18.40.10")
 
 					ctx := context.TODO()
-					err = fakeClient.Create(ctx, existIPPoolT)
+					err := fakeClient.Create(ctx, existIPPoolT)
 					Expect(err).NotTo(HaveOccurred())
 
-					ipPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					ipPoolT.Spec.Subnet = subnet
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
 					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
 						[]string{
 							"172.18.40.1-172.18.40.2",
@@ -945,6 +911,37 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					Expect(apierrors.IsInvalid(err)).To(BeTrue())
 				})
 
+				It("sets owner reference to a Subnet with different 'spec.subnet'", func() {
+					subnetT.SetUID(uuid.NewUUID())
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+					subnetT.Spec.IPs = append(subnetT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, subnetT)
+					Expect(err).NotTo(HaveOccurred())
+
+					err = controllerutil.SetControllerReference(subnetT, ipPoolT, scheme)
+					Expect(err).NotTo(HaveOccurred())
+
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/25"
+					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					err = ipPoolWebhook.ValidateCreate(ctx, ipPoolT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
 				It("sets owner reference to a terminating Subnet", func() {
 					controllerutil.AddFinalizer(subnetT, constant.SpiderFinalizer)
 					subnetT.SetUID(uuid.NewUUID())
@@ -986,6 +983,10 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					ipPoolWebhook.EnableSpiderSubnet = true
 				})
 
+				PIt("failed to assemble the total IP addresses of the IPPool due to some unknown errors", func() {})
+
+				PIt("failed to assemble the total IP addresses of the Subnet due to some unknown errors", func() {})
+
 				It("is out of the IP range of the Subnet", func() {
 					subnetT.SetUID(uuid.NewUUID())
 					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
@@ -1189,6 +1190,73 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			When("Validating 'spec.ips'", func() {
+				It("removes all 'spec.ips' while feature SpiderSubnet is enabled", func() {
+					ipPoolWebhook.EnableSpiderSubnet = true
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+					subnetT.Spec.IPs = append(subnetT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, subnetT)
+					Expect(err).NotTo(HaveOccurred())
+
+					err = controllerutil.SetControllerReference(subnetT, ipPoolT, scheme)
+					Expect(err).NotTo(HaveOccurred())
+
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
+					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					newIPPoolT := ipPoolT.DeepCopy()
+					newIPPoolT.Spec.IPs = nil
+
+					err = ipPoolWebhook.ValidateUpdate(ctx, ipPoolT, newIPPoolT)
+					Expect(err).NotTo(HaveOccurred())
+				})
+
+				It("removes all 'spec.ips'", func() {
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+					subnetT.Spec.IPs = append(subnetT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, subnetT)
+					Expect(err).NotTo(HaveOccurred())
+
+					err = controllerutil.SetControllerReference(subnetT, ipPoolT, scheme)
+					Expect(err).NotTo(HaveOccurred())
+
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
+					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					newIPPoolT := ipPoolT.DeepCopy()
+					newIPPoolT.Spec.IPs = nil
+
+					err = ipPoolWebhook.ValidateUpdate(ctx, ipPoolT, newIPPoolT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
 				It("appends invalid IP range to 'spec.ips'", func() {
 					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 					ipPoolT.Spec.Subnet = "172.18.40.0/24"
@@ -1220,24 +1288,21 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					Expect(apierrors.IsInvalid(err)).To(BeTrue())
 				})
 
-				It("exists invalid IPPool in the cluster", func() {
-					ipVersion := constant.IPv4
-					subnet := "172.18.40.0/24"
-					cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-					Expect(err).NotTo(HaveOccurred())
-					Expect(cidr).NotTo(BeEmpty())
+				PIt("failed to list IPPools due to some unknown errors", func() {})
 
-					existIPPoolT.Labels[constant.LabelIPPoolCIDR] = cidr
-					existIPPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					existIPPoolT.Spec.Subnet = subnet
+				PIt("failed to assemble the total IP addresses of the IPPool due to some unknown errors", func() {})
+
+				It("exists invalid IPPool in the cluster", func() {
+					existIPPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existIPPoolT.Spec.Subnet = "172.18.40.0/24"
 					existIPPoolT.Spec.IPs = append(existIPPoolT.Spec.IPs, constant.InvalidIPRange)
 
 					ctx := context.TODO()
-					err = fakeClient.Create(ctx, existIPPoolT)
+					err := fakeClient.Create(ctx, existIPPoolT)
 					Expect(err).NotTo(HaveOccurred())
 
-					ipPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					ipPoolT.Spec.Subnet = subnet
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
 					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs, "172.18.40.1-172.18.40.2")
 
 					newIPPoolT := ipPoolT.DeepCopy()
@@ -1248,23 +1313,16 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 				})
 
 				It("overlaps with existing IPPool", func() {
-					ipVersion := constant.IPv4
-					subnet := "172.18.40.0/24"
-					cidr, err := spiderpoolip.CIDRToLabelValue(ipVersion, subnet)
-					Expect(err).NotTo(HaveOccurred())
-					Expect(cidr).NotTo(BeEmpty())
-
-					existIPPoolT.Labels[constant.LabelIPPoolCIDR] = cidr
-					existIPPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					existIPPoolT.Spec.Subnet = subnet
+					existIPPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existIPPoolT.Spec.Subnet = "172.18.40.0/24"
 					existIPPoolT.Spec.IPs = append(existIPPoolT.Spec.IPs, "172.18.40.10")
 
 					ctx := context.TODO()
-					err = fakeClient.Create(ctx, existIPPoolT)
+					err := fakeClient.Create(ctx, existIPPoolT)
 					Expect(err).NotTo(HaveOccurred())
 
-					ipPoolT.Spec.IPVersion = pointer.Int64(ipVersion)
-					ipPoolT.Spec.Subnet = subnet
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/24"
 					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs, "172.18.40.1-172.18.40.2")
 
 					newIPPoolT := ipPoolT.DeepCopy()
@@ -1425,6 +1483,8 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 			})
 
 			When("Validating the IP addresses being used", func() {
+				PIt("failed to assemble the total IP addresses of the IPPool due to some unknown errors", func() {})
+
 				It("removes IP range that is being used by IPPool", func() {
 					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 					ipPoolT.Spec.Subnet = "172.18.40.0/24"
@@ -1492,6 +1552,35 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					Expect(apierrors.IsInvalid(err)).To(BeTrue())
 				})
 
+				It("updates the IPPool that sets the owner reference to a Subnet with different 'spec.subnet'", func() {
+					subnetT.SetUID(uuid.NewUUID())
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+					subnetT.Spec.IPs = append(subnetT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, subnetT)
+					Expect(err).NotTo(HaveOccurred())
+
+					err = controllerutil.SetControllerReference(subnetT, ipPoolT, scheme)
+					Expect(err).NotTo(HaveOccurred())
+
+					ipPoolT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					ipPoolT.Spec.Subnet = "172.18.40.0/25"
+					ipPoolT.Spec.IPs = append(ipPoolT.Spec.IPs, "172.18.40.1-172.18.40.2")
+
+					newIPPoolT := ipPoolT.DeepCopy()
+					newIPPoolT.Spec.IPs = append(newIPPoolT.Spec.IPs, "172.18.40.10")
+
+					err = ipPoolWebhook.ValidateUpdate(ctx, ipPoolT, newIPPoolT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
 				It("updates the IPPool that sets the owner reference to a terminating Subnet", func() {
 					controllerutil.AddFinalizer(subnetT, constant.SpiderFinalizer)
 					subnetT.SetUID(uuid.NewUUID())
@@ -1531,6 +1620,10 @@ var _ = Describe("IPPoolWebhook", Label("ippool_webhook_test"), func() {
 					ipPoolWebhook.EnableSpiderSubnet = true
 				})
 
+				PIt("failed to assemble the total IP addresses of the IPPool due to some unknown errors", func() {})
+
+				PIt("failed to assemble the total IP addresses of the Subnet due to some unknown errors", func() {})
+
 				It("is out of the IP range of the Subnet", func() {
 					subnetT.SetUID(uuid.NewUUID())
 					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
diff --git a/pkg/reservedipmanager/reservedip_webhook_test.go b/pkg/reservedipmanager/reservedip_webhook_test.go
index c09f43912..22cf9b01b 100644
--- a/pkg/reservedipmanager/reservedip_webhook_test.go
+++ b/pkg/reservedipmanager/reservedip_webhook_test.go
@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"sync/atomic"
 
+	"github.com/agiledragon/gomonkey/v2"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -41,8 +42,8 @@ var _ = Describe("ReservedIPWebhook", Label("reservedip_webhook_test"), func() {
 
 	Describe("Test ReservedIPWebhook's method", func() {
 		var count uint64
-		var rIPName string
-		var rIPT *spiderpoolv1.SpiderReservedIP
+		var rIPName, existRIPName string
+		var rIPT, existRIPT *spiderpoolv1.SpiderReservedIP
 
 		BeforeEach(func() {
 			reservedipmanager.WebhookLogger = logutils.Logger.Named("ReservedIP-Webhook")
@@ -61,6 +62,18 @@ var _ = Describe("ReservedIPWebhook", Label("reservedip_webhook_test"), func() {
 				},
 				Spec: spiderpoolv1.ReservedIPSpec{},
 			}
+
+			existRIPName = fmt.Sprintf("z-exist-reservedip-%v", count)
+			existRIPT = &spiderpoolv1.SpiderReservedIP{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       constant.SpiderReservedIPKind,
+					APIVersion: fmt.Sprintf("%s/%s", constant.SpiderpoolAPIGroup, constant.SpiderpoolAPIVersionV1),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name: existRIPName,
+				},
+				Spec: spiderpoolv1.ReservedIPSpec{},
+			}
 		})
 
 		var deleteOption *client.DeleteOptions
@@ -75,6 +88,9 @@ var _ = Describe("ReservedIPWebhook", Label("reservedip_webhook_test"), func() {
 			ctx := context.TODO()
 			err := fakeClient.Delete(ctx, rIPT, deleteOption)
 			Expect(client.IgnoreNotFound(err)).NotTo(HaveOccurred())
+
+			err = fakeClient.Delete(ctx, existRIPT, deleteOption)
+			Expect(client.IgnoreNotFound(err)).NotTo(HaveOccurred())
 		})
 
 		Describe("Default", func() {
@@ -245,6 +261,14 @@ var _ = Describe("ReservedIPWebhook", Label("reservedip_webhook_test"), func() {
 			})
 
 			When("Validating 'spec.ips'", func() {
+				It("inputs empty 'spec.ips'", func() {
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+
+					ctx := context.TODO()
+					err := rIPWebhook.ValidateCreate(ctx, rIPT)
+					Expect(err).NotTo(HaveOccurred())
+				})
+
 				It("inputs invalid 'spec.ips'", func() {
 					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 					rIPT.Spec.IPs = append(rIPT.Spec.IPs, constant.InvalidIPRange)
@@ -253,6 +277,63 @@ var _ = Describe("ReservedIPWebhook", Label("reservedip_webhook_test"), func() {
 					err := rIPWebhook.ValidateCreate(ctx, rIPT)
 					Expect(apierrors.IsInvalid(err)).To(BeTrue())
 				})
+
+				It("failed to list ReservedIPs due to some unknown errors", func() {
+					patches := gomonkey.ApplyMethodReturn(fakeClient, "List", constant.ErrUnknown)
+					defer patches.Reset()
+
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					rIPT.Spec.IPs = append(rIPT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					ctx := context.TODO()
+					err := rIPWebhook.ValidateCreate(ctx, rIPT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
+				It("exists invalid ReservedIPs in the cluster", func() {
+					existRIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existRIPT.Spec.IPs = append(existRIPT.Spec.IPs, constant.InvalidIPRange)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, existRIPT)
+					Expect(err).NotTo(HaveOccurred())
+
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					rIPT.Spec.IPs = append(rIPT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					err = rIPWebhook.ValidateCreate(ctx, rIPT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
+				It("overlaps with existing ReservedIP", func() {
+					existRIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existRIPT.Spec.IPs = append(existRIPT.Spec.IPs, "172.18.40.10")
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, existRIPT)
+					Expect(err).NotTo(HaveOccurred())
+
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					rIPT.Spec.IPs = append(rIPT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					err = rIPWebhook.ValidateCreate(ctx, rIPT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
 			})
 
 			It("creates IPv4 ReservedIP with all fields valid", func() {
@@ -344,6 +425,61 @@ var _ = Describe("ReservedIPWebhook", Label("reservedip_webhook_test"), func() {
 					err := rIPWebhook.ValidateUpdate(ctx, rIPT, newRIPT)
 					Expect(apierrors.IsInvalid(err)).To(BeTrue())
 				})
+
+				It("failed to list ReservedIPs due to some unknown errors", func() {
+					patches := gomonkey.ApplyMethodReturn(fakeClient, "List", constant.ErrUnknown)
+					defer patches.Reset()
+
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					rIPT.Spec.IPs = append(rIPT.Spec.IPs, "172.18.40.1-172.18.40.2")
+
+					newRIPT := rIPT.DeepCopy()
+					newRIPT.Spec.IPs = append(newRIPT.Spec.IPs, "172.18.40.10")
+
+					ctx := context.TODO()
+					err := rIPWebhook.ValidateUpdate(ctx, rIPT, newRIPT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
+				It("exists invalid ReservedIPs in the cluster", func() {
+					existRIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existRIPT.Spec.IPs = append(existRIPT.Spec.IPs, constant.InvalidIPRange)
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, existRIPT)
+					Expect(err).NotTo(HaveOccurred())
+
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					rIPT.Spec.IPs = append(rIPT.Spec.IPs, "172.18.40.1-172.18.40.2")
+					err = fakeClient.Create(ctx, rIPT)
+					Expect(err).NotTo(HaveOccurred())
+
+					newRIPT := rIPT.DeepCopy()
+					newRIPT.Spec.IPs = append(newRIPT.Spec.IPs, "172.18.40.10")
+
+					err = rIPWebhook.ValidateUpdate(ctx, rIPT, newRIPT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
+				It("overlaps with existing ReservedIP", func() {
+					existRIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					existRIPT.Spec.IPs = append(existRIPT.Spec.IPs, "172.18.40.10")
+
+					ctx := context.TODO()
+					err := fakeClient.Create(ctx, existRIPT)
+					Expect(err).NotTo(HaveOccurred())
+
+					rIPT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					rIPT.Spec.IPs = append(rIPT.Spec.IPs, "172.18.40.1-172.18.40.2")
+					err = fakeClient.Create(ctx, rIPT)
+					Expect(err).NotTo(HaveOccurred())
+
+					newRIPT := rIPT.DeepCopy()
+					newRIPT.Spec.IPs = append(newRIPT.Spec.IPs, "172.18.40.10")
+
+					err = rIPWebhook.ValidateUpdate(ctx, rIPT, newRIPT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
 			})
 
 			It("deletes ReservedIP", func() {
diff --git a/pkg/subnetmanager/subnet_webhook_test.go b/pkg/subnetmanager/subnet_webhook_test.go
index 6fe65fb45..9d8c4a90b 100644
--- a/pkg/subnetmanager/subnet_webhook_test.go
+++ b/pkg/subnetmanager/subnet_webhook_test.go
@@ -106,7 +106,7 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			It("adds finalizer", func() {
-				subnetT.Spec.Subnet = "172.18.40.0/24"
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 
 				ctx := context.TODO()
 				err := subnetWebhook.Default(ctx, subnetT)
@@ -116,36 +116,6 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 				Expect(contains).To(BeTrue())
 			})
 
-			It("failed to parse 'spec.subnet' as a valid label value", func() {
-				subnetT.Spec.IPVersion = pointer.Int64(constant.InvalidIPVersion)
-				subnetT.Spec.Subnet = "172.18.40.0/24"
-
-				ctx := context.TODO()
-				err := subnetWebhook.Default(ctx, subnetT)
-				Expect(err).NotTo(HaveOccurred())
-
-				v, ok := subnetT.Labels[constant.LabelSubnetCIDR]
-				Expect(ok).To(BeFalse())
-				Expect(v).To(BeEmpty())
-			})
-
-			It("sets CIDR label", func() {
-				subnet := "172.18.40.0/24"
-				subnetT.Spec.Subnet = subnet
-
-				ctx := context.TODO()
-				err := subnetWebhook.Default(ctx, subnetT)
-				Expect(err).NotTo(HaveOccurred())
-
-				cidr, err := spiderpoolip.CIDRToLabelValue(*subnetT.Spec.IPVersion, subnet)
-				Expect(err).NotTo(HaveOccurred())
-				Expect(cidr).NotTo(BeEmpty())
-
-				v, ok := subnetT.Labels[constant.LabelSubnetCIDR]
-				Expect(ok).To(BeTrue())
-				Expect(v).To(Equal(cidr))
-			})
-
 			It("failed to set 'spec.ipVersion' due to the invalid 'spec.subnet'", func() {
 				subnetT.Spec.Subnet = constant.InvalidCIDR
 
@@ -175,7 +145,6 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 
 			It("failed to merge 'spec.ips' due to the invalid 'spec.ipVersion'", func() {
 				subnetT.Spec.IPVersion = pointer.Int64(constant.InvalidIPVersion)
-				subnetT.Spec.Subnet = "172.18.40.0/24"
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						"172.18.40.10",
@@ -198,7 +167,6 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 
 			It("failed to merge 'spec.ips' due to the invalid 'spec.ips'", func() {
 				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
-				subnetT.Spec.Subnet = "172.18.40.0/24"
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						constant.InvalidIPRange,
@@ -222,7 +190,7 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			It("merges IPv4 'spec.ips'", func() {
-				subnetT.Spec.Subnet = "172.18.40.0/24"
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						"172.18.40.10",
@@ -243,7 +211,7 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			It("merges IPv6 'spec.ips'", func() {
-				subnetT.Spec.Subnet = "abcd:1234::/120"
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv6)
 				subnetT.Spec.IPs = append(subnetT.Spec.IPs,
 					[]string{
 						"abcd:1234::a",
@@ -265,7 +233,6 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 
 			It("failed to merge 'spec.excludeIPs' due to the invalid 'spec.ipVersion'", func() {
 				subnetT.Spec.IPVersion = pointer.Int64(constant.InvalidIPVersion)
-				subnetT.Spec.Subnet = "172.18.40.0/24"
 				subnetT.Spec.ExcludeIPs = append(subnetT.Spec.ExcludeIPs,
 					[]string{
 						"172.18.40.10",
@@ -288,7 +255,6 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 
 			It("failed to merge 'spec.excludeIPs' due to the invalid 'spec.ips'", func() {
 				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
-				subnetT.Spec.Subnet = "172.18.40.0/24"
 				subnetT.Spec.ExcludeIPs = append(subnetT.Spec.ExcludeIPs,
 					[]string{
 						constant.InvalidIPRange,
@@ -312,7 +278,7 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			It("merges IPv4 'spec.excludeIPs'", func() {
-				subnetT.Spec.Subnet = "172.18.40.0/24"
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 				subnetT.Spec.ExcludeIPs = append(subnetT.Spec.ExcludeIPs,
 					[]string{
 						"172.18.40.10",
@@ -333,7 +299,7 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			It("merges IPv6 'spec.excludeIPs'", func() {
-				subnetT.Spec.Subnet = "abcd:1234::/120"
+				subnetT.Spec.IPVersion = pointer.Int64(constant.IPv6)
 				subnetT.Spec.ExcludeIPs = append(subnetT.Spec.ExcludeIPs,
 					[]string{
 						"abcd:1234::a",
@@ -516,6 +482,15 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			When("Validating 'spec.ips'", func() {
+				It("inputs empty 'spec.ips'", func() {
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+
+					ctx := context.TODO()
+					err := subnetWebhook.ValidateCreate(ctx, subnetT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
 				It("inputs invalid 'spec.ips'", func() {
 					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 					subnetT.Spec.Subnet = "172.18.40.0/24"
@@ -812,6 +787,24 @@ var _ = Describe("SubnetWebhook", Label("subnet_webhook_test"), func() {
 			})
 
 			When("Validating 'spec.ips'", func() {
+				It("removes all 'spec.ips'", func() {
+					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
+					subnetT.Spec.Subnet = "172.18.40.0/24"
+					subnetT.Spec.IPs = append(subnetT.Spec.IPs,
+						[]string{
+							"172.18.40.1-172.18.40.2",
+							"172.18.40.10",
+						}...,
+					)
+
+					newSubnetT := subnetT.DeepCopy()
+					newSubnetT.Spec.IPs = nil
+
+					ctx := context.TODO()
+					err := subnetWebhook.ValidateUpdate(ctx, subnetT, newSubnetT)
+					Expect(apierrors.IsInvalid(err)).To(BeTrue())
+				})
+
 				It("appends invalid IP range to 'spec.ips'", func() {
 					subnetT.Spec.IPVersion = pointer.Int64(constant.IPv4)
 					subnetT.Spec.Subnet = "172.18.40.0/24"
diff --git a/test/e2e/affinity/affinity_test.go b/test/e2e/affinity/affinity_test.go
index 7b1c0b37e..3e9d8281e 100644
--- a/test/e2e/affinity/affinity_test.go
+++ b/test/e2e/affinity/affinity_test.go
@@ -354,11 +354,9 @@ var _ = Describe("test Affinity", Label("affinity"), func() {
 		var newPodList *corev1.PodList
 		var defaultV4PoolNameList, defaultV6PoolNameList []string
 		const stsOriginialNum = int(1)
+		statefulSetName = "sts" + tools.RandomName()
 
 		BeforeEach(func() {
-			// test statefulSet name
-			statefulSetName = "sts" + tools.RandomName()
-
 			// Create IPv4 pools and IPv6 pools
 			if frame.Info.IpV4Enabled {
 				v4PoolName, v4PoolObj = common.GenerateExampleIpv4poolObject(5)
diff --git a/test/e2e/annotation/annotation_test.go b/test/e2e/annotation/annotation_test.go
index 833cc3e38..cabf10b0f 100644
--- a/test/e2e/annotation/annotation_test.go
+++ b/test/e2e/annotation/annotation_test.go
@@ -453,14 +453,13 @@ var _ = Describe("test annotation", Label("annotation"), func() {
 	Context("Spiderpool will successively try to allocate IP in the order of the elements in the IPPool array until the first allocation succeeds or all fail", func() {
 		var v4PoolNameList1, v6PoolNameList1, v4PoolNameList2, v6PoolNameList2 []string
 		var err error
-		var deployName string
+		var deployName = "deploy" + tools.RandomName()
 		var (
 			podOriginialNum int = 1
 			podScaleupNum   int = 2
 			ippoolIpNum     int = 1
 		)
 		BeforeEach(func() {
-			deployName = "deploy" + tools.RandomName()
 			// Create one ippool to be used as backup ippool
 			if frame.Info.IpV4Enabled {
 				if frame.Info.SpiderSubnetEnabled {
diff --git a/test/e2e/common/spidersubnet.go b/test/e2e/common/spidersubnet.go
index 24a9b6708..d97e716cd 100644
--- a/test/e2e/common/spidersubnet.go
+++ b/test/e2e/common/spidersubnet.go
@@ -310,7 +310,7 @@ func GetAvailableIpsInSubnet(f *frame.Framework, subnetName string) ([]net.IP, e
 		return nil, err
 	}
 
-	ips := ip.IPsDiffSet(ips1, ips2, false)
+	ips := ip.IPsDiffSet(ips1, ips2)
 	return ips, nil
 }
 
@@ -358,7 +358,7 @@ LOOP:
 							return err
 						}
 
-						diffIps := ip.IPsDiffSet(ips1, ips2, false)
+						diffIps := ip.IPsDiffSet(ips1, ips2)
 						if diffIps != nil {
 							GinkgoWriter.Printf("inconsistent ip records in subnet %v/%v and pool %v/%v \n", subnetName, ips2, pool.Name, ips1)
 							continue LOOP
diff --git a/test/e2e/subnet/subnet_test.go b/test/e2e/subnet/subnet_test.go
index f06551c06..01bcc9825 100644
--- a/test/e2e/subnet/subnet_test.go
+++ b/test/e2e/subnet/subnet_test.go
@@ -476,16 +476,16 @@ var _ = Describe("test subnet", Label("subnet"), func() {
 	})
 
 	Context("Validity of fields in subnet.spec", func() {
+		var deployName string = "deploy" + tools.RandomName()
 		var fixedIPNumber string = "+0"
 		var deployOriginiaNum int32 = 1
-		var deployName string
 
 		BeforeEach(func() {
-			deployName = "deploy" + tools.RandomName()
 			v4SubnetName, v4SubnetObject = common.GenerateExampleV4SubnetObject(10)
 			Expect(v4SubnetObject).NotTo(BeNil())
 			v6SubnetName, v6SubnetObject = common.GenerateExampleV6SubnetObject(10)
 			Expect(v6SubnetObject).NotTo(BeNil())
+
 			// Delete namespaces and delete subnets
 			DeferCleanup(func() {
 				GinkgoWriter.Printf("delete v4 subnet %v, v6 subnet %v \n", v4SubnetName, v6SubnetName)
@@ -835,21 +835,28 @@ var _ = Describe("test subnet", Label("subnet"), func() {
 			Eventually(func() bool {
 				podList, err = frame.GetPodListByLabel(deployYaml.Spec.Template.Labels)
 				if nil != err {
-					GinkgoWriter.Printf("failed to get pod list %v \n", err)
+					GinkgoWriter.Printf("failed to get pod list %v", err)
 					return false
 				}
-				// Compare Pod List numbers
-				if len(podList.Items) != int(deployOriginiaNum) {
+				if len(podList.Items) == 0 {
 					return false
 				}
+				for _, pod := range podList.Items {
+					ctx, cancel = context.WithTimeout(context.Background(), common.EventOccurTimeout)
+					defer cancel()
+					err = frame.WaitExceptEventOccurred(ctx, common.OwnerPod, pod.Name, namespace, common.CNIFailedToSetUpNetwork)
+					if err != nil {
+						GinkgoWriter.Printf("failed to get event %v", err)
+						// https://github.com/spidernet-io/spiderpool/issues/1329
+						// Probable failure to fetch event or event is swiped and never fetched,
+						// restart the pod and let it fetch again
+						Expect(frame.DeletePod(pod.Name, namespace)).NotTo(HaveOccurred())
+						return false
+					}
+				}
 				return true
 			}, common.PodStartTimeout, common.ForcedWaitingTime).Should(BeTrue())
 
-			ctx, cancel = context.WithTimeout(context.Background(), common.EventOccurTimeout)
-			defer cancel()
-			for _, pod := range podList.Items {
-				err = frame.WaitExceptEventOccurred(ctx, common.OwnerPod, pod.Name, namespace, common.CNIFailedToSetUpNetwork)
-			}
 			Expect(frame.DeleteDeployment(deployName, namespace)).NotTo(HaveOccurred())
 		})
 	})