Project Structure
Reference documentation for the memcached-operator project scaffold, following the Operator SDK / Kubebuilder go.kubebuilder.io/v4 layout conventions.
Directory Layout
memcached-operator/
├── api/
│ ├── v1alpha1/
│ │ ├── groupversion_info.go # API group registration (memcached.c5c3.io/v1alpha1)
│ │ ├── memcached_types.go # CRD type definitions (Memcached, MemcachedList)
│ │ └── zz_generated.deepcopy.go # Generated DeepCopy methods (do not edit)
│ └── v1beta1/ # Storage version (primary API)
│ ├── groupversion_info.go # API group registration (memcached.c5c3.io/v1beta1)
│ ├── memcached_types.go # CRD type definitions (Memcached, MemcachedList)
│ ├── memcached_conversion.go # Hub conversion marker (v1beta1 is the hub)
│ ├── memcached_webhook.go # Defaulting webhook
│ ├── memcached_validation_webhook.go # Validation webhook
│ └── zz_generated.deepcopy.go # Generated DeepCopy methods (do not edit)
├── cmd/
│ └── main.go # Operator entry point, manager bootstrap
├── config/
│ ├── crd/
│ │ ├── bases/ # Generated CRD YAML manifests
│ │ └── kustomization.yaml
│ ├── default/
│ │ ├── kustomization.yaml # Aggregates crd + rbac + manager
│ │ └── manager_metrics_patch.yaml # Metrics endpoint configuration
│ ├── manager/
│ │ ├── manager.yaml # Controller manager Deployment
│ │ └── kustomization.yaml
│ ├── prometheus/
│ │ ├── monitor.yaml # ServiceMonitor template
│ │ └── kustomization.yaml
│ ├── rbac/
│ │ ├── kustomization.yaml
│ │ ├── leader_election_role.yaml
│ │ ├── leader_election_role_binding.yaml
│ │ ├── role.yaml # Generated ClusterRole from RBAC markers
│ │ ├── role_binding.yaml
│ │ └── service_account.yaml
│ └── samples/
│ ├── memcached_v1alpha1_memcached.yaml # Example Memcached CR
│ └── kustomization.yaml
├── hack/
│ └── boilerplate.go.txt # License header for generated files
├── internal/
│ └── controller/
│ ├── memcached_controller.go # Reconciler implementation
│ ├── memcached_controller_test.go # Controller integration tests
│ └── suite_test.go # envtest bootstrap (Ginkgo/Gomega)
├── bin/ # Tool binaries and compiled output (gitignored)
├── .golangci.yml # Linter configuration
├── Dockerfile # Multi-stage container build
├── Makefile # Development workflow targets
├── PROJECT # Operator SDK project metadata
├── go.mod # Go module definition
└── go.sum # Dependency checksumsKey Files
PROJECT
Operator SDK project metadata file declaring:
| Field | Value |
|---|---|
| Domain | c5c3.io |
| Layout | go.kubebuilder.io/v4 |
| Project Name | memcached-operator |
| Repo | github.com/c5c3/memcached-operator |
| API Group | memcached.c5c3.io |
| API Versions | v1alpha1, v1beta1 (storage) |
| Kind | Memcached |
| CRD Version | v1 |
| Scope | Namespaced |
api/v1beta1/ (primary)
CRD type definitions for the memcached.c5c3.io/v1beta1 API group — the storage version and hub for multi-version conversion:
groupversion_info.go- DeclaresGroupVersion,SchemeBuilder, andAddToSchemefor scheme registration.memcached_types.go- DefinesMemcachedSpec,MemcachedStatus,Memcached, andMemcachedListwith kubebuilder markers (+kubebuilder:object:root=true,+kubebuilder:subresource:status,+kubebuilder:storageversion).memcached_conversion.go- Implements theconversion.Hubinterface, marking v1beta1 as the hub type for spoke (v1alpha1) conversion.memcached_webhook.go- Defaulting webhook that sets field defaults on create/update.memcached_validation_webhook.go- Validation webhook that enforces CRD constraints.zz_generated.deepcopy.go- Auto-generated bymake generate. Implementsruntime.Objectinterface viaDeepCopyObject().
api/v1alpha1/ (spoke)
Legacy CRD type definitions for the memcached.c5c3.io/v1alpha1 API group. Retained for backward compatibility — resources submitted as v1alpha1 are automatically converted to v1beta1 via the conversion webhook:
groupversion_info.go- DeclaresGroupVersion,SchemeBuilder, andAddToSchemefor scheme registration.memcached_types.go- DefinesMemcachedSpec,MemcachedStatus,Memcached, andMemcachedList. Schema is identical to v1beta1.zz_generated.deepcopy.go- Auto-generated bymake generate. Implementsruntime.Objectinterface viaDeepCopyObject().
cmd/main.go
Operator entry point that:
- Registers
clientgoscheme,memcached/v1alpha1(for conversion support), andmemcached/v1beta1on the runtime scheme - Parses CLI flags for metrics address (
:8443), health probe address (:8081), leader election, and secure metrics - Creates a controller-runtime
Managerwith leader election IDd4f3c8a2.c5c3.io - Wires the
MemcachedReconcilerviaSetupWithManager - Registers
/healthzand/readyzprobe endpoints - Starts the manager with OS signal handling
internal/controller/
memcached_controller.go-MemcachedReconcilerstruct embeddingclient.Clientwith aSchemefield. Includes RBAC markers for memcacheds (full CRUD), status, and finalizers.SetupWithManagerregisters watches forv1beta1.MemcachedCRs. TheReconcilemethod fetches and reconcilesv1beta1.Memcachedresources.suite_test.go- Ginkgo/Gomega test suite bootstrapping envtest with CRD paths pointing toconfig/crd/bases/. Creates a test client with the v1beta1 scheme registered.memcached_controller_test.go- Integration tests validating CR creation, reconciler setup, and reconcile behavior.
config/
Kustomize-based deployment configuration following Kubebuilder v4 conventions:
| Directory | Purpose |
|---|---|
config/crd/ | CRD manifests generated by controller-gen |
config/rbac/ | ServiceAccount, ClusterRole, ClusterRoleBinding, leader election RBAC |
config/manager/ | Controller manager Deployment manifest |
config/default/ | Aggregation overlay referencing crd + rbac + manager |
config/samples/ | Example Memcached CR for testing |
config/prometheus/ | ServiceMonitor template for Prometheus integration |
Dockerfile
Multi-stage build:
- Builder stage:
golang:1.25withCGO_ENABLED=0,TARGETOS/TARGETARCHbuild args for cross-platform support - Runtime stage:
gcr.io/distroless/static:nonrootrunning as UID 65532
Makefile Targets
Development
| Target | Description |
|---|---|
manifests | Generate CRD YAML (config/crd/bases/) and RBAC (config/rbac/) via controller-gen |
generate | Generate DeepCopy methods in zz_generated.deepcopy.go |
fmt | Run go fmt ./... |
vet | Run go vet ./... |
test | Run envtest-based integration tests with coverage (depends on manifests, generate, fmt, vet) |
test-e2e | Run end-to-end tests against a real cluster |
lint | Run golangci-lint |
lint-fix | Run golangci-lint with --fix |
Build
| Target | Description |
|---|---|
build | Compile manager binary to bin/manager (depends on manifests, generate, fmt, vet) |
run | Run controller locally from host |
docker-build | Build container image tagged as ${IMG} |
docker-push | Push container image to registry |
docker-buildx | Build and push multi-platform image (linux/amd64, linux/arm64) |
Deployment
| Target | Description |
|---|---|
install | Install CRDs into cluster via kustomize build config/crd |
uninstall | Remove CRDs from cluster |
deploy | Deploy controller manager with RBAC to cluster via kustomize build config/default |
undeploy | Remove controller manager from cluster |
Tool Dependencies
Tools are auto-downloaded to bin/ on first use via Makefile targets:
| Tool | Version | Purpose |
|---|---|---|
controller-gen | v0.17.2 | CRD/RBAC manifest and DeepCopy generation |
kustomize | v5.6.0 | Kubernetes manifest composition |
setup-envtest | release-0.20 | Download envtest API server binaries |
golangci-lint | v2.10.1 | Go linter aggregator |
Go Module
| Field | Value |
|---|---|
| Module path | github.com/c5c3/memcached-operator |
| Go version | 1.25 |
| controller-runtime | v0.23.1 |
| k8s.io/apimachinery | v0.35.1 |
| k8s.io/client-go | v0.35.0 |
| Ginkgo | v2.27.2 |
| Gomega | v1.38.2 |
Conventions
This project follows the Kubebuilder v4 / Operator SDK conventions:
- Entry point in
cmd/main.go(not project root) - API types in
api/<version>/with kubebuilder markers for code generation - Controller logic in
internal/controller/(unexported, internal to the module) - RBAC generated from
//+kubebuilder:rbacmarkers on the reconciler - CRDs generated from struct tags and
//+kubebuilder:validationmarkers on types - Secure metrics via controller-runtime's built-in authentication (no kube-rbac-proxy sidecar)
- envtest for integration testing against an in-memory API server and etcd
- Ginkgo/Gomega as the BDD test framework