k8s.io/api: the Go types behind every Kubernetes object
The canonical location of the Kubernetes API definition.
At a glance
- What is it?
- The kubernetes/api repository holds the schema of the external API types served by the Kubernetes API server, one directory per API group, published as its own Go module so that client-go, apimachinery and apiserver can be depended on together without a dependency diamond. It suits Go developers who want the typed API objects rather than unstructured maps, and its one hard rule is that the types should be serialized to JSON, not to protobuf.
- Who is it for?
- Adopt k8s.io/api when you are writing Go code that reads or writes Kubernetes objects and want typed structs rather than unstructured maps, and serialize them to JSON as the documentation recommends.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A staging mirror, not a place to send pull requests
The first thing the README says is that this is an automatically published staged repository for Kubernetes, with a warning marker at the top. Contributions, including issues and pull requests, should be made to the main Kubernetes repository, and this repository is read-only for importing and is not used for direct contributions. The topic list on the repository reflects that, with a single tag, k8s-staging.
The mechanism is described in the section titled Where does it come from. The `api` directory is synced from the staging area of the main Kubernetes repository, and code changes are made in that location, merged into k8s.io/kubernetes and later synced here. The same idea appears in the list of things you should not do, where it says the staging source is synced to k8s.io/api, that all changes must be made in the former, and that the latter is read-only.
So the practical rule for a contributor is simple: change the code in kubernetes/kubernetes under staging/src/k8s.io/api, and the mirror updates itself. For a consumer, the practical rule is different and is stated elsewhere: the most likely interaction with this repository is as a dependency of client-go.
The repository is not archived, the last push was on 2026-10-16, there are no GitHub releases because releases happen in the main Kubernetes repository, and the licence is Apache-2.0.
One directory per API group, all in one Go module
The top level listing is a map of the Kubernetes API surface, and it is worth reading as such. Every entry is an API group directory: `admission/`, `admissionregistration/`, `apidiscovery/`, `apiserverinternal/`, `apps/`, `authentication/`, `authorization/`, `autoscaling/`, `batch/`, `certificates/`, `coordination/`, `core/`, `discovery/`, `events/`, `extensions/`, `flowcontrol/`, `imagepolicy/`, `lifecycle/`, `networking/`, `node/`, `policy/`, `rbac/`, `resource/`, `scheduling/`, `storage/` and `storagemigration/`.
That structure maps onto how Kubernetes itself is organised. `core/` holds the fundamental objects such as Pods, Services and ConfigMaps, `apps/` holds the workload resources, `networking/` the ingress and network policy types, `rbac/` the role and cluster role definitions, `batch/` the job and cron job types, and `storage/` the storage class and volume types. A Go program that imports this module gets every one of them under a single import path, which is what makes a type switch over API groups practical.
The module declaration confirms the shape:
module k8s.io/api
go 1.27.0
godebug default=go1.27The go.mod file is marked as generated, and the required dependencies are short: `k8s.io/apimachinery` at a pseudo version matching the sync date, `k8s.io/klog/v2`, and `github.com/google/go-cmp` for tests. The indirect list pulls in the usual Kubernetes ecosystem pieces, `sigs.k8s.io/json`, `sigs.k8s.io/yaml`, `sigs.k8s.io/structured-merge-diff/v7`, `k8s.io/utils`, `github.com/fxamacker/cbor/v2`, `github.com/x448/float16` and `gopkg.in/inf.v0`, which is a reasonable footprint for a types-only module.
The generated file at the root, `openapi_models_test.go` and `roundtrip_test.go`, tell you what the project checks about itself: that the models match the OpenAPI definition and that they survive a round trip.
Why the module is published separately at all
The stated reason for the separate publication is dependency management, and it is a specific problem rather than a general preference.
The library is published separately to avoid diamond dependency problems for users who depend on more than one of `k8s.io/client-go`, `k8s.io/apimachinery` and `k8s.io/apiserver`. In Go's module graph, a diamond is when two dependencies both depend on a third, and if the versions required by the two sides disagree, the module resolution can pick a version that satisfies neither cleanly. Splitting the API types into their own module means client-go, apimachinery and apiserver can each depend on the same `k8s.io/api` version without forcing a user who depends on several of them into a version conflict.
This matters in practice for anyone writing a tool that pulls in a Kubernetes client alongside something else that also talks to the API, because without the split the client library and the server library would each carry their own copy of the type definitions and you would end up comparing types from two different packages that look identical but are not.
The compatibility statement is short: branches track Kubernetes branches and are compatible with that repo. There is no independent version scheme here, and the pseudo version in the dependency on apimachinery, `v0.0.0-20261016061814-74229373536e`, shows the mechanism. A pseudo version encodes a commit hash and a timestamp rather than a release number, which is what a module that is synced rather than released looks like.
So the version to pin is not a version of this repository but the Kubernetes branch you are targeting.
Serialize to JSON, not to protobuf
The recommended use section carries the most important guidance in the README, and it is a warning rather than a recommendation.
The recommendation is to use the Go types in this repository and serialize them directly to JSON. The warning is about protobuf. If you want to store or interact with proto-formatted Kubernetes API objects, the recommendation is to use the official serialization stack in `k8s.io/apimachinery`, because directly serializing these types to proto will not result in data that matches the wire format or is compatible with other Kubernetes ecosystem tools. The reason given is that the wire format includes a magic prefix and an envelope proto.
That detail explains why the type definitions alone are not enough for protobuf. A Kubernetes object on the wire is not a bare message of the object type. It is wrapped in an envelope that carries the API version and kind, and it is preceded by a magic prefix that identifies the payload as Kubernetes protobuf. A struct that mirrors the object fields but omits both will produce bytes that no other tool in the ecosystem will accept, even though the field contents are right.
The same reasoning drives the advice against embedding these proto objects inside your own proto definitions. The better recommendation is to store Kubernetes objects as byte arrays in the wire format, since that is self-describing. The payoff is that you can use either the JSON or the binary proto wire format without code changes, and the note says that operating on both Custom Resources and built-in types at the same time would otherwise be difficult.
This is the difference between a types module and a serialization library, and it is the single most common mistake made by people who treat k8s.io/api as a general purpose Kubernetes client.
Against unstructured objects and against a hand-written client
The realistic alternative is not another repository but the other way of talking to a Kubernetes API server.
The first alternative is unstructured access, where you work with `map[string]interface{}` and a resource name, and let the client do the field lookups for you. That is the approach the dynamic client takes, and it has one decisive advantage: it works for Custom Resources, including ones that do not exist yet. A CRD is defined in your cluster by someone else, and a typed Go struct for it does not exist until someone writes a client for it. Any code that only uses the types in this repository will fail to compile against a resource that only exists in the cluster, while unstructured code will handle it.
That is the boundary. The types in this repository are the built-in API surface, and they give you compile-time checking, autocomplete and refactoring for everything Kubernetes ships. They give you nothing for a resource someone else invented last week.
The second alternative is a third-party client library. Such a library wraps the API server in a friendlier interface, often with builders and helpers, and it is the right choice when you want less boilerplate than client-go gives you. What it costs is a dependency on somebody else's abstraction over an interface that changes with every Kubernetes release, and for a tool that has to work across many cluster versions, pinning the upstream types is often simpler than pinning a wrapper.
There is also the option of generating your own client from the OpenAPI definition of the cluster you target. That produces types matching one specific version, which is precise but ties the code to a cluster, and it discards the ability to handle multiple versions in one binary.
Editorial conclusion
Adopt k8s.io/api when you are writing Go code that reads or writes Kubernetes objects and want typed structs rather than unstructured maps, and serialize them to JSON as the documentation recommends. Do not adopt it if you need protobuf wire compatibility, because the type definitions do not round-trip into the envelope format without the official stack in k8s.io/apimachinery, and check first that your module tracks a Kubernetes branch, since the branches here track the upstream repository and are compatible with it rather than with an arbitrary version.
Frequently asked questions
What is the k8s.io/api repository for?
It holds the schema of the external API types served by the Kubernetes API server, one directory per API group, and is the canonical location of the Kubernetes API definition. It is published as its own Go module so that client-go, apimachinery and apiserver can be depended on together without diamond dependency problems.
Where do I send a pull request for the Kubernetes API types?
Not here. This repository is an automatically published staged mirror and is read-only for importing. Changes go to the main Kubernetes repository under staging/src/k8s.io/api, are merged into k8s.io/kubernetes, and are later synced to this repository.
Can I serialize the k8s.io/api types to protobuf?
Not directly. The documentation says to use the official serialization stack in `k8s.io/apimachinery`, because directly serializing these types to proto will not match the wire format, which includes a magic prefix and an envelope proto. It also advises against embedding these proto objects in your own proto definitions and suggests storing objects as byte arrays in the self-describing wire format.
How do I pick a version of k8s.io/api to depend on?
Branches in this repository track Kubernetes branches and are compatible with that repo, so you pick the Kubernetes branch you are targeting rather than an independent version. The dependency on apimachinery is a pseudo version built from a commit hash and timestamp, which shows the module is synced rather than released.
What should I use instead of k8s.io/api for Custom Resources?
Unstructured access, since a typed Go struct does not exist for a resource defined by a CRD in your cluster. The typed types in this repository cover the built-in API surface and give compile-time checking for everything Kubernetes ships, but nothing for resources someone else invented.
Is k8s.io/api still being maintained?
The repository is not archived and the last push was on 2026-10-16. It has no GitHub releases of its own, since the source of truth is the main Kubernetes repository, and the licence is Apache-2.0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kubernetes-api)Was this useful?