Kubernetes — Structure#
Layout pattern#
Custom Monorepo — Staging + cmd/pkg hybrid
Kubernetes does not follow the standard Go module layout. It uses a home-grown staging monorepo pattern: 34 independently publishable k8s.io/* sub-libraries live under staging/src/k8s.io/ and are replace-directed in go.mod to local paths. The main module’s implementation lives in pkg/ (no internal/), entry points are in cmd/, and admission/auth plugins live in plugin/pkg/. Import boundaries are enforced not by Go’s internal/ mechanism but by the custom cmd/import-boss tool and .import-restrictions files scattered through staging/.
Directory map#
kubernetes/
├── api/ — OpenAPI spec JSON files, API discovery docs, API validation rules
├── build/ — Docker build infrastructure (server-image, pause container, build-image scripts)
├── CHANGELOG/ — Per-release changelogs
├── cluster/ — Cloud provider scripts (GCE), add-on configs, kubemark cluster support
├── cmd/ — All binary entry points (core components + codegen tools + dev tooling)
│ ├── kube-apiserver/
│ ├── kube-controller-manager/
│ ├── kube-scheduler/
│ ├── kubelet/
│ ├── kube-proxy/
│ ├── kubectl/
│ ├── kubectl-convert/
│ ├── kubeadm/
│ ├── cloud-controller-manager/
│ ├── kubemark/
│ ├── gendocs/ genkubedocs/ genman/ genyaml/ genswaggertypedocs/ genfeaturegates/
│ └── import-boss/ importverifier/ dependencycheck/ dependencyverifier/ clicheck/ ...
├── docs/ — User-facing documentation stubs
├── hack/ — Shell scripts: build, verify, codegen, test runners; make-rules library
├── LICENSES/ — Third-party and vendor license files
├── pkg/ — Core implementation (~842 Go package directories, no internal/)
│ ├── admission/ — Admission controller framework interfaces
│ ├── api/ — Internal API type helpers and validation
│ ├── apis/ — Internal type definitions for all API groups (versioned subdirs)
│ ├── auth/ — Authentication and authorization helpers
│ ├── controller/ — All ~40 built-in controllers (deployments, replicasets, jobs, etc.)
│ ├── controlplane/ — API server control-plane setup and wiring
│ ├── features/ — Feature gate constant definitions
│ ├── generated/ — Generated deepcopy functions and OpenAPI schema
│ ├── kubeapiserver/— API server configuration helpers
│ ├── kubectl/ — kubectl implementation helpers
│ ├── kubelet/ — Kubelet (largest sub-tree; CRI, volume, pod lifecycle)
│ ├── proxy/ — kube-proxy iptables/ipvs implementations
│ ├── quota/ — Resource quota evaluation framework
│ ├── registry/ — API resource storage strategies (etcd REST storage)
│ ├── scheduler/ — Scheduler framework, plugins, and algorithm profiles
│ ├── volume/ — Volume plugin system (in-tree and CSI bridge)
│ └── ... — probe, printers, routes, security, serviceaccount, util, windows
├── plugin/
│ └── pkg/
│ ├── admission/— Built-in admission plugins (ResourceQuota, LimitRanger, etc.)
│ └── auth/ — Built-in authorization modules
├── staging/
│ └── src/k8s.io/ — 34 sub-modules published independently (see below)
├── test/ — e2e, integration, conformance, fuzz, and node test suites
├── third_party/ — Vendored code included directly (not via go mod)
└── vendor/ — Vendored all external dependenciesEntry points#
All cmd/ entry points follow a consistent <name>.go → app/server.go → app/options/ pattern. The top-level file is a thin main() wrapper that delegates to the app sub-package.
Core control-plane components#
| Binary | Entry file | Role |
|---|---|---|
kube-apiserver | cmd/kube-apiserver/apiserver.go | The central REST API server; all cluster state passes through here |
kube-controller-manager | cmd/kube-controller-manager/controller-manager.go | Runs all built-in reconciliation controllers in one process |
kube-scheduler | cmd/kube-scheduler/scheduler.go | Assigns pods to nodes using a plugin-based scheduling framework |
cloud-controller-manager | cmd/cloud-controller-manager/main.go | Cloud-provider-specific control loops (separate from core CCM) |
Node components#
| Binary | Entry file | Role |
|---|---|---|
kubelet | cmd/kubelet/kubelet.go | Node agent: manages pod lifecycle, CRI, volumes, health checks |
kube-proxy | cmd/kube-proxy/proxy.go | Network proxy: maintains iptables/ipvs rules for Service VIPs |
User-facing tools#
| Binary | Entry file | Role |
|---|---|---|
kubectl | cmd/kubectl/kubectl.go | Primary CLI for interacting with the cluster |
kubectl-convert | cmd/kubectl-convert/ | kubectl plugin for converting API objects between versions |
kubeadm | cmd/kubeadm/kubeadm.go | Cluster bootstrap and upgrade tooling |
Scale testing#
| Binary | Role |
|---|---|
kubemark | Hollow node simulator for scale-testing the control plane |
Code generation tools (developer tooling only, not shipped)#
gendocs, genkubedocs, genman, genyaml, genswaggertypedocs, genfeaturegates — generate documentation artifacts. import-boss, importverifier, dependencycheck, dependencyverifier, clicheck, fieldnamedocscheck, preferredimports — CI verification tools.
Package organization#
Staging sub-modules (staging/src/k8s.io/)#
These are the foundation libraries. They are developed in-tree but published as independent modules via a periodic sync script. Key modules:
| Module | Role |
|---|---|
k8s.io/api | Versioned API type definitions (core, apps, batch, rbac, …) |
k8s.io/apimachinery | Runtime machinery: runtime.Object, ObjectMeta, scheme, codec |
k8s.io/apiserver | Generic API server framework (REST storage, admission, auth, RBAC) |
k8s.io/apiextensions-apiserver | CRD API server extension |
k8s.io/client-go | Official Go client: typed, dynamic, informers, work queues |
k8s.io/kubectl | kubectl command library (reusable outside the main binary) |
k8s.io/controller-manager | Shared controller manager infrastructure |
k8s.io/kube-scheduler | Scheduler framework interfaces and extension points |
k8s.io/component-base | Shared component infrastructure: logs, metrics, feature gates, version |
k8s.io/cloud-provider | Cloud provider interface definitions |
k8s.io/cri-api | Container Runtime Interface (CRI) protobuf definitions |
k8s.io/code-generator | Codegen tools: deepcopy-gen, register-gen, informer-gen, etc. |
k8s.io/kms | KMS encryption provider API |
k8s.io/dynamic-resource-allocation | DRA (structured parameters) framework |
k8s.io/sample-controller | Reference implementation of a custom controller |
Internal packages (pkg/)#
No internal/ directory exists at the repo root; access control is enforced by import-boss. The pkg/ tree holds ~842 package directories — the bulk of the Kubernetes implementation. Notable clusters:
pkg/controller/— ~40 controllers, each in its own subdirectory (deployment, replicaset, job, daemonset, statefulset, endpoint, namespace, node, serviceaccount, …)pkg/kubelet/— Largest single sub-tree; contains CRI client wiring, pod lifecycle, volume management, eviction, QoS, PLEG (Pod Lifecycle Event Generator)pkg/scheduler/framework/— Plugin framework with defined extension points (Filter, Score, Reserve, Bind, …)pkg/registry/— Etcd-backed REST storage for each API resource grouppkg/volume/— In-tree volume plugins and CSI bridge
Public packages (plugin/pkg/)#
Admission plugins and authorization modules that depend on pkg/ but are logically separate from it. Houses built-in admission plugins like ResourceQuota, LimitRanger, PodSecurity, ServiceAccount, and authorization plugins like RBAC and Node.
Layering#
The dependency graph flows strictly bottom-up:
staging/src/k8s.io/{api,apimachinery} ← no k8s deps; pure types + primitives
↓
staging/src/k8s.io/{apiserver,client-go,component-base} ← use api+apimachinery
↓
pkg/{apis,registry,controller,scheduler,kubelet,…} ← use staging libs
↓
plugin/pkg/{admission,auth} ← use pkg/
↓
cmd/*/app/ ← wire everything together; only layer allowed to import broadlyThis layering is enforced by .import-restrictions files processed by import-boss at CI time. Violations fail the build.
Build system#
- Build tool: GNU Make, delegating to
hack/make-rules/shell library - Key targets:
make all— Build all binaries (cross-compiles for linux/amd64 by default)make test— Run unit testsmake test-integration— Run integration tests (requires etcd)make test-e2e-node— Run e2e node testsmake clean— Remove build artifactsmake verify— Run all verification scripts (lint, import checks, codegen drift)make update— Regenerate all generated code
- Docker: Yes, multi-stage.
build/contains:build/server-image/Dockerfile— Multi-stage build producing the server container imagebuild/pause/Dockerfile— The pause container (infra container for pod network namespaces)build/build-image/— The hermetic build container used in CI
- Codegen: Extensive.
hack/scripts drivek8s.io/code-generatorto regenerate deepcopy functions, typed clients, informers, listers, conversion functions, and OpenAPI schemas. Generated files are checked in and drift is detected in CI.
Notable structural decisions#
No
internal/at the root. Unlike most Go projects, Kubernetes does not use Go’sinternal/directory to restrict imports. Instead it inventedimport-boss: a custom tool that reads.import-restrictionsJSON files and enforces allowed/forbidden import rules at CI time. This predates Go’sinternal/feature being well-established but is now a maintained design choice.Staging as in-tree monorepo. The
staging/directory is arguably the most distinctive structural decision. 34 libraries that are consumed by the entire Go ecosystem (client-go,apimachinery,apiserver, etc.) are developed in the same commit graph as the main binary. A periodic automated job (“publishing-bot”) syncs each staging module to its own GitHub repository. This allows atomic cross-module refactors while maintaining independent versioning for consumers.plugin/as a controlled extension layer. Admission and authorization plugins that must ship with the binary but are logically distinct from core pkg/ code live inplugin/pkg/. This separation makes it easy to audit what is “core framework” vs. “policy implementation.”cmd/*/app/pattern universally applied. Every binary, fromkube-apiservertokubeadmto codegen tools, uses the same two-level structure: a thincmd/<name>/<name>.gowithmain()delegating tocmd/<name>/app/server.go. Options are always incmd/<name>/app/options/. This consistency across 25+ binaries is non-trivial.test/as a first-class top-level directory. Rather than collocating all tests with source, Kubernetes has a dedicatedtest/directory with 353+ package directories covering e2e (cluster-level), e2e_node (per-node), integration (in-process with real etcd), conformance, fuzz, and kubemark scale tests. This reflects the project’s commitment to treating testing infrastructure as a product in itself.vendor/is committed. All external dependencies are vendored in a committedvendor/directory. This is a deliberate choice for reproducibility in a project where thousands of contributors work across multiple organizations. It also enables offline builds and simplifies the build container setup.