How to Mock Kubernetes Services with a ClusterIP Registry in Python
Simulate Kubernetes service discovery by assigning ClusterIP addresses to dataclass-defined services, with JSON export for inspection or testing.
Python code
72 linesimport json
from dataclasses import dataclass, asdict
from typing import Dict, Optional
@dataclass
class Service:
name: str
namespace: str
cluster_ip: str
selector: Dict[str, str]
port: int
target_port: Optional[int] = None
class ClusterIPServiceRegistry:
_ip_counter = 0
def __init__(self) -> None:
self._services: Dict[str, Service] = {}
def _next_cluster_ip(self) -> str:
self._ip_counter += 1
return f"10.96.{self._ip_counter // 256}.{self._ip_counter % 256}"
def create_service(self, name: str, namespace: str, selector: Dict[str, str], port: int, target_port: Optional[int] = None) -> Service:
key = f"{namespace}/{name}"
if key in self._services:
raise ValueError(f"Service {key} already exists")
service = Service(
name=name,
namespace=namespace,
cluster_ip=self._next_cluster_ip(),
selector=selector,
port=port,
target_port=target_port or port,
)
self._services[key] = service
return service
def get_service(self, name: str, namespace: str = "default") -> Optional[Service]:
return self._services.get(f"{namespace}/{name}")
def list_services(self) -> list[Service]:
return list(self._services.values())
def to_json(self) -> str:
return json.dumps([asdict(s) for s in self.list_services()], indent=2)
if __name__ == "__main__":
registry = ClusterIPServiceRegistry()
web_service = registry.create_service(
name="web",
namespace="default",
selector={"app": "web"},
port=80,
target_port=8080,
)
api_service = registry.create_service(
name="api",
namespace="prod",
selector={"app": "api"},
port=443,
)
print(registry.to_json())
found = registry.get_service("web")
print(f"\nFound: {found.cluster_ip} -> {found.target_port}")
Output
[
{
"name": "web",
"namespace": "default",
"cluster_ip": "10.96.0.1",
"selector": {
"app": "web"
},
"port": 80,
"target_port": 8080
},
{
"name": "api",
"namespace": "prod",
"cluster_ip": "10.96.0.2",
"selector": {
"app": "api"
},
"port": 443,
"target_port": 443
}
]
Found: 10.96.0.1 -> 8080
How it works
The ClusterIPServiceRegistry auto-generates ClusterIP addresses using a monotonically increasing counter, mapping it into a 10.96.x.x /16 range like real Kubernetes. The Service dataclass stores the essential metadata — name, namespace, selector, ports — and asdict converts it to a dict for clean JSON output. Namespace/name keying mirrors Kubernetes' unique resource identifier, preventing duplicate services. The to_json method lets you export the registry state, which is handy for mocking service discovery in tests or local dev setups. Using an optional target_port defaults it to the service port, matching K8s behavior when not explicitly set.
Common mistakes
- Forgetting that ClusterIP allocation starts at .1, not .0, which skews IP expectations in tests
- Not keying services by namespace — this allows duplicate names across namespaces and breaks lookups
- Using mutable class-level `_ip_counter` across registries, causing shared state and unexpected IPs
Variations
- Use a fixed range like 10.43.0.0/16 to match k3s or a provider-specific CIDR
- Back the registry with a `dict` plus a `threading.Lock` to make it concurrency-safe
Real-world use cases
- Local development shim that mimics Kubernetes service discovery without a real cluster.
- Integration tests for microservices that depend on stable ClusterIP endpoints and DNS-like lookups.
- Sandboxed demo environments where users create services and inspect JSON output for validation.
Sponsored
More from Production deployment patterns
- Auto Rollback on Error Rate Exceeded in Python medium
- Automate Semantic Versioning with Conventional Commits in Python medium
- Design a Data Helper for Beginners in Python easy
- Docker healthcheck CMD mock in Python easy
- Generate a Mock Artifact Version Tag in Python easy
- Generate a docker-compose.yml with mock services in Python easy
Keep learning
Related tutorials and quizzes for this topic.