14 - Anatomy of a K8s-Related OSS Project¶
What this session is¶
About 30 minutes. Walk through the typical layout of a K8s-related OSS project - Helm charts, operators, kubectl plugins.
Typical Helm chart repo¶
my-app-chart/
├── README.md
├── LICENSE
├── CONTRIBUTING.md
├── Chart.yaml (chart metadata)
├── values.yaml (default values)
├── values.schema.json (JSON schema for values, optional)
├── templates/
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── serviceaccount.yaml
│ ├── hpa.yaml
│ ├── tests/
│ │ └── test-connection.yaml
│ └── NOTES.txt
├── ci/ (test values files)
│ ├── ci-values.yaml
│ └── lint-values.yaml
├── .helmignore (like .gitignore but for chart packaging)
└── .github/workflows/
├── lint.yml (helm lint, chart-testing)
└── release.yml (publish to a chart repo)
Roles:
- Chart.yaml - metadata. Version. Dependencies.
- values.yaml - what users can configure. The README usually has a table of all values.
- values.schema.json - JSON schema; helm install validates against it.
- templates/ - Go-templated manifests. _helpers.tpl is shared snippets.
- templates/tests/ - Helm tests. Run with helm test <release>. Each test is a pod that runs an assertion (e.g., curl the service to ensure it works).
- ci/ - different value combos for CI testing.
- .helmignore - files NOT included when packaging the chart.
Typical operator repo (Go-based)¶
my-operator/
├── README.md
├── LICENSE
├── CONTRIBUTING.md
├── Makefile (build, test, deploy targets)
├── go.mod / go.sum
├── PROJECT (Kubebuilder/operator-sdk project file)
├── api/
│ └── v1alpha1/
│ ├── mything_types.go (Go struct for the CRD)
│ └── zz_generated_deepcopy.go (generated code)
├── controllers/
│ └── mything_controller.go (the reconcile loop)
├── config/
│ ├── crd/bases/ (generated CRD YAMLs)
│ ├── default/ (default deployment manifests)
│ ├── manager/ (operator pod deployment)
│ ├── rbac/ (ServiceAccount + Role + Binding)
│ └── samples/ (sample CR instances)
├── hack/ (helper scripts)
└── .github/workflows/
Operators are usually built with Kubebuilder or Operator SDK. The above is the Kubebuilder layout.
You wouldn't dive into operator Go code as a first contribution. Likely contributions: improve config/samples/ examples, fix typos in README.md, update RBAC in config/rbac/, improve test fixtures.
Typical kubectl plugin¶
kubectl-myplugin/
├── README.md
├── LICENSE
├── main.go (entry point, single binary)
├── pkg/
│ └── cmd/
│ └── ... (subcommands)
├── go.mod
├── Makefile
├── .github/workflows/
│ └── release.yml (build binaries for multiple platforms)
└── docs/
kubectl plugins are standalone binaries named kubectl-<plugin>. Put one in your PATH and kubectl <plugin> works. Many plugins are small (a few hundred lines of Go).
Contributions: subcommand improvements, docs, bug fixes.
CI: what your PR will be measured against¶
For Helm charts, common CI:
- name: Run chart-testing (lint)
run: ct lint --config ct.yaml
- name: Run chart-testing (install)
run: ct install --config ct.yaml
chart-testing is the standard Helm-CI tool. Replicate locally:
For operators, CI usually runs:
- make test (unit tests)
- make manifests (regenerate CRDs from Go types - should be no-op if you didn't change types)
- make docker-build (build the operator image)
For kubectl plugins, CI runs go test ./... and cross-compiles.
Conventions in CONTRIBUTING.md¶
- Setup. "How to run the chart locally," "how to build the operator binary."
- Tests. What
make testorct installchecks. - Commit format. Some projects use Conventional Commits. Many don't.
- PR template. Address every checkbox.
- DCO. CNCF projects often require
git commit -sfor the DCO. - CLA. Some projects require a CLA signature via a bot.
Reading a chart's README¶
Real-world chart READMEs typically have:
- Overview.
- Prerequisites (K8s version, Helm version).
- Installation:
- Configuration values table - every settable value, default, description.
- Upgrade notes (breaking changes per version).
- Troubleshooting.
Read this before opening a PR. Many issues are answered there.
A worked walkthrough¶
Pick a Bitnami chart, say bitnami/postgresql. Apply orientation:
-
Open
Chart.yaml-name: postgresql, dependencies (none direct), version (likely double-digits - Bitnami iterates fast). -
Open
values.yaml- heavily commented. The structure shows:image:,auth:,primary:,readReplicas:,metrics:, etc. -
Look in
templates/: primary/statefulset.yaml(Postgres primary)primary/svc.yamlread/statefulset.yaml(read replicas if configured)secrets.yamlserviceaccount.yaml-
metrics/ -
Read the primary StatefulSet template. Note how it pulls everything from
.Values.primary.*. -
Open
templates/NOTES.txt. That's what users see after install - "your password is X, connect with Y."
Five minutes; you have a mental map of one of the most-deployed Postgres charts.
Exercise¶
Use the project you picked in page 13:
- Clone locally.
- Walk the layout. Map files to categories.
- Read CONTRIBUTING.md.
- Find the CI workflow. List the commands.
- Run them locally:
- For Helm:
helm lint .and maybect lint. - For operator:
make test. - Identify the file your issue would touch.
What you might wonder¶
"What's app.kubernetes.io/managed-by: Helm?"
A label every Helm-installed resource gets, indicating who manages it. Useful for "show me all Helm-managed things."
"What's release.toolkit.fluxcd.io/...?"
Annotations the Flux GitOps operator uses to track resources. You'll see them in Flux-managed clusters.
Done¶
- Recognize Helm chart layout.
- Recognize operator (Kubebuilder) layout.
- Recognize kubectl plugin layout.
- Read CI workflows, run them locally.
- Read a chart README for configuration.
Next: Your first contribution →