Repository: kubernetes
Issue: Rethink how we manage/name/publish annotations
Labels: area/kubectl,sig/api-machinery,lifecycle/frozen

NB: This is about the annotations that kubernetes itself uses, not about end-user annotations.  Those are explicitly reserved for use by end-users.

We use annotations for 2 main things.

1) To prototype new would-be fields in existing objects.
2) To decorate objects with bits of state from the core system components.

In both cases, we have to write down and publish the name of the annotation and the expected/allowed values for it.  Currently that is ad hoc.  Sometimes it is written as a const somewhere global-ish (e.g. pkg/api).  Sometimes it is a const in a local pkg.  Sometimes it is just a string literal.

We have defined naming conventions for annotations but we don't always stick to them, nor are the conventions precise enough to be consistent.

I propose (without too much though yet) that we refine the conventions and standardize our own annotations more.  Obviously this would be a "going forward" spec.

1) Any annotation that is a "would-be field", but is still alpha or beta designated should be named as `{kind}.alpha.kubernetes.io/{field-name}` (same for beta).  `{kind}` is the top-level Kubernetes API type, all lowercase, e.g. "pod", "replicationcontroller", "podsecuritypolicy".  `{field-name}` is the proposed name of the would-field after converting capital letters to dashes, e.g. "policy", "class", "file-mode".  The "spec" nesting is implied for objects that have spec/status blocks.  NB that the suffix is "kubernetes.io" not "k8s.io".

For fields that would exist on a sub-struct of an API type, the field name would reflect the nesting, e.g. `pod.alpha.kubernetes.io/security-context.breadth`.

For fields that  would exist on a sub-struct where that struct is used as a list, the field name would reflect the name of the slice and the value would have enough information to logically patch the values.  E.g. `pod.alpha.kubernetes.io/containers.volumes.encrypted: "[ [false, true], []]"` would map to a pod with 2 containers[] records with 2 volumes in the first and none in the second.

For fields that  would exist on a sub-struct where that struct is used as a map, the field name would reflect the name of the slice and the value would have enough information to logically patch the values. E.g. `foo.alpha.kubernetes.io/field-names: "{ \"key\": \"val\" }"` would map to a foo with a map called fieldNames with a key "key".  I could not find any concrete examples in our API where this would apply.

Alternative sub-points:
- we could make "spec" explicit
- we could make the name include "field" to distinguish from annotations that are not pre-GA fields
- we could NOT convert fooBar to foo-bar for field names -- it's easier

2) All annotations that represent would-be fields must be defined in the per-API packages in `annotations.go` (or in a sub-pkg thereof?) with consistent const names and comments explaining what the feature is, who owns it, and what values are allowed.

3) All annotations that represent would-be fields must be validated as if they were real fields.

4) Any annotation that is used by the kubernetes system but is not an alpha or beta field should be named as `{subsystem}.kubernetes.io/{meaningful-name}`.  As above, `{subsystem}` is a little loose, and could use refinement.  `{meaningful-name}` is a name that reflects the meaning of the annotation.  All such annotations must be collected and published in a central file with consistent const names and comments explaining what the feature is, who owns it, and what values are allowed.  These annotations are internal to the system and do not come from users, therefore do not necessarily need alpha/beta designation.

The main goal of all this is consistency and obviousness in naming, centralized places to publish the existence, meaning, and requirements for annotations, and the ability to curate and manage names.  Ad hoc self-governance clearly is not working.

This could segue into the discussion gates for features.

@jlowdermilk @timstclair @lavalamp @erictune @smarterclayton @bgrant0607