Documentation
¶
Overview ¶
Package staticpod renders and manages the control-plane static pod manifests (the control plane runs as kubelet-managed static pods).
stratum is the SOLE writer of the manifest directory: every manifest is re-rendered idempotently from the persisted node state on controller start, so hand-edits are overwritten by design and the rendered files stand as the on-disk truth.
The systemctl-shaped verbs the host-process model needed are replaced by three file operations kubelet reacts to:
Restart — re-render with a bumped restarted-at annotation (content change
makes kubelet recreate the pod)
Stop — remove the manifest and wait for the component to go down
Start — re-render the manifest from the current node state
Index ¶
- Constants
- Variables
- func Active(name string) bool
- func Dir() string
- func Exists(name string) bool
- func HasListener(name string) bool
- func ManifestName(name string) (string, bool)
- func NamesFor(st *nodestate.NodeState) []string
- func PIDs(name string) ([]int, error)
- func Path(name string) string
- func Put(name string, b []byte) error
- func Read(name string) ([]byte, error)
- func Restart(name string) error
- func RestartAsIs(name string) error
- func RestoreSnapshot(dir string) error
- func Running(name string) (bool, error)
- func Snapshot(dir string) error
- func Start(name string) error
- func StartTicks(pid int) (uint64, bool, error)
- func Stop(name string, timeout time.Duration) error
- func WaitActive(name string, timeout time.Duration) error
- func WaitReplaced(name string, mark Mark, timeout time.Duration) error
- func WriteAll(st *nodestate.NodeState) error
- type ContainerSpec
- type Mark
Constants ¶
const AdmissionConfigAnnotation = "stratum.ciq.com/admission-config-sha256"
AdmissionConfigAnnotation carries the sha256 of the node profile's AdmissionConfiguration file on the kube-apiserver pod. The apiserver reads the admission-webhook.yaml merged from it only when it starts, and its manifest names that file without its contents, so a changed admission body would otherwise leave the running apiserver on the old policy. It is an annotation of its own so AuditPolicyAnnotation keeps the value it had.
const AuditPolicyAnnotation = "stratum.ciq.com/audit-policy-sha256"
AuditPolicyAnnotation carries the sha256 of the node profile's plain config files, in order, on the kube-apiserver pod: for the cis profile, its audit policy. The apiserver reads such a file only when it starts, and its manifest names the file without its contents, so a changed file would otherwise leave the running apiserver on the old one.
const RestartedAtAnnotation = "stratum.ciq.com/restarted-at"
RestartedAtAnnotation is bumped by Restart; kubelet recreates a static pod whenever its manifest content changes, and the annotation is the one field whose only job is to change.
Variables ¶
var Names = []string{"etcd", "kube-apiserver", "kube-controller-manager", "kube-scheduler", "kube-vip"}
Names is every component rendered as a static pod, in start order.
Functions ¶
func Dir ¶
func Dir() string
Dir is the kubelet staticPodPath (prepare.go points kubelet.conf here).
func Exists ¶
Exists reports whether this node renders the component at all — the static-pod replacement for comps.UnitExists ("is this a control plane?").
func HasListener ¶
HasListener reports whether the component owns a localhost listener a caller can wait on (the checks Active polls): every roster component but kube-vip, whose metrics server is disabled, and no name outside the roster. It is the listenerless rule localPort already encodes, so a second static pod without a listener needs only its localPort entry left out.
func ManifestName ¶
ManifestName reports whether a file name in the manifest directory — or in a snapshot of it — is one of the rendered component manifests ("<name>.yaml"), and which component. It is false for a render-derived file, a staging leftover, and anything else: kubelet parses every visible file in the directory as a pod, but only these are ones this package renders, and only these does a manifest-set restore replace. Exported for the upgrade's readers of a manifest snapshot, which must count exactly the components a restore replaces — a webhook config file is not a pod kubelet runs.
func NamesFor ¶
NamesFor is the roster this node state renders: Names in start order, with kube-vip in it exactly when the state carries a VIP. It is the one place the kube-vip-only-with-VIP rule lives, so every roster derived from it — the upgrade's re-render order, the restore's restart set — cannot restate the rule beside it. A fresh slice per call: callers append to and reorder the roster they are handed, and one that aliased Names would corrupt it for every other reader.
func PIDs ¶
PIDs lists the processes on this node running the component: procid's walk with the static-pod scanners' deliberately loose argv[0]-basename rule, so an image's entrypoint with no staged host path is still found. An unreadable process table is unknown, not proof that the process is gone.
func Put ¶
Put writes b as name's manifest, exactly as given. It is for putting back a manifest read earlier, where re-rendering would take its images from this binary rather than from whatever was running (an upgrade rollback runs the newer binary against the older manifests).
func Restart ¶
Restart re-renders with a bumped restarted-at annotation; kubelet recreates the pod on the content change.
func RestartAsIs ¶
RestartAsIs restarts a component whose manifest must not change: it bumps the restarted-at annotation on the manifest as it is on disk, where Restart re-renders it and so takes its images from this binary. An upgrade rollback runs the newer binary against the older manifests it has just restored, and re-rendering those would put the newer images back. It reports an error for a component with no manifest.
func RestoreSnapshot ¶
RestoreSnapshot puts a snapshot's manifest set back where the render keeps it: every manifest through the package's one staging path into the manifest directory, every render-derived file at the live path the render writes it, with the mode the snapshot holds. Anything else in the snapshot — a stray file, a leftover — lands nowhere: kubelet parses every non-hidden file in the manifest directory as a pod, and the derived files belong in the directory the apiserver's argv names. Before anything moves, the visible staging files the pre-atomic writer left in the live manifest directory are swept: kubelet parses them as pods, and they sort AFTER the real manifest in the file source's glob, so they hold that pod's store key permanently.
func Running ¶
Running reports whether a static-pod component process is still present on this node. Unlike Active, it covers a process that has already closed its listener while it finishes shutting down, and kube-vip which has no listener. An error means the process state is unknown.
func Snapshot ¶
Snapshot copies the manifest set into dir, which it creates: every component manifest in the manifest directory, plus the render-derived files. Staging leftovers and anything else in the directory stay out — a file that joined a snapshot would be restored as a pod on every later restore. The set lands complete or not at all: it is staged under a hidden name beside dir and renamed into place only once every copy succeeded, so a snapshot that exists is one a restore can put back whole. A caller that keeps an existing snapshot for its own resume semantics (the upgrade's) must check before calling: a snapshot already at dir is not retaken.
func Start ¶
Start (re)renders one component's manifest from the persisted node state — the static-pod equivalent of the supervisor's ArgsFn semantics: `stratum snapshot rejoin/restore` patches the state, and Start renders the patched membership flags.
func StartTicks ¶
StartTicks is when process pid started, in clock ticks since boot.
func Stop ¶
Stop removes the manifest and waits until the component's process is gone, so callers that are about to do something destructive (move etcd's data dir aside) know the old process is no longer serving or retaining host state. kube-vip has no listener, but its process must still exit before teardown.
func WaitActive ¶
WaitActive polls until Active or timeout.
func WaitReplaced ¶
WaitReplaced waits until every process running the component started after mark: once a changed manifest is written, until kubelet has taken down whatever ran before it. A process that started in mark's own tick counts as started before it: kubelet takes far longer than a tick to start a pod from a manifest written after the mark. A check that the component answers, made before then, can be answered by a process from the manifest it replaced, however many times that one was restarted in between.
Types ¶
type ContainerSpec ¶
type ContainerSpec struct {
// Command is the explicit command in the manifest. If empty, the image's
// entrypoint is unknown to this reader.
Command []string
// Argv is Command followed by Args. Without Command it starts with Args,
// not the image entrypoint.
Argv []string
// Env is the container's declared environment. It does NOT include the
// image's own ENV layer, which is not visible from the manifest; that is
// pinned by digest in build/images.txt and audited at build time.
Env map[string]string
}
ContainerSpec is the rendered exec definition of a component, read back from the manifest kubelet actually reads.
It exists so an auditor can see a component's ARGV and its ENVIRONMENT together, from one artifact. For a kubelet-managed static pod those really are the whole story: a container's environment is the image's ENV plus the pod spec's env, and the kubelet does not leak its own environ into it. So for any component rendered here, this file is the environment — which is what makes an audit of etcd's boolean TLS flags decidable rather than an inference about etcd's defaults.
func ReadContainerSpec ¶
func ReadContainerSpec(name string) (ContainerSpec, error)
ReadContainerSpec parses the rendered manifest for a component and returns its explicit command, combined argv and declared environment.
Deliberately reads the FILE rather than re-rendering from node state: a re-render would report what stratum intends, and the point of an audit is to report what kubelet was handed. An out-of-band edit is therefore visible here, which is exactly what a CIS check over these flags is for.