cmd/config/docs/api-conventions/functions-spec.md
apiVersion: v1
This document specifies a standard for client-side functions that operate on Kubernetes declarative configurations referred to as KRM Functions. This standard enables creating small, interoperable, and language-independent executable programs packaged as containers that can be chained together as part of a configuration management pipeline. The end result of such a pipeline are fully rendered configurations that can then be applied to a control plane (e.g. Using ‘kubectl apply’ for Kubernetes control plane). As such, although this document references Kubernetes Resource Model and API conventions, it is completely decoupled from Kubernetes API machinery and does not depend on any in-cluster components.
This document references terms described in Kubernetes API Conventions.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
KRM functions enable shift-left practices (client-side) through:
small, medium,
large and inject the cpu and memory resources into containers accordingly.init and side-car containers into resources based off of
resource type, annotations, etc.Performing these on the client rather than the server enables:
Service.selector and Deployment.spec.template labels
match.init container to a client "CRD" resource after it was
generated.The inter-process communication between the orchestrator and a function works as follows:
stdin.
The input is a Kubernetes object of kind ResourceList as described below.stdin, performs computations, and provides
the output as a ResourceList to stdout. The function MAY also emit
non-structured error message on stderr.stdout, stderr, and the exit code of the function
as it sees fit following to the semantics described below.A function MUST accept input from stdin and MUST output to stdout a
Kubernetes object of kind ResourceList with the following OpenAPI schema:
swagger: "2.0"
info:
title: KRM Functions Specification (ResourceList)
version: v1
definitions:
ResourceList:
type: object
description: ResourceList is the input/output wire format for KRM functions.
x-kubernetes-group-version-kind:
- group: config.kubernetes.io
kind: ResourceList
version: v1
- group: config.kubernetes.io
kind: ResourceList
version: v1beta1
required:
- items
properties:
apiVersion:
description: apiVersion of ResourceList
type: string
kind:
description: kind of ResourceList i.e. `ResourceList`
type: string
items:
type: array
description: |
[input/output]
Items is a list of Kubernetes objects:
https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds).
A function will read this field in the input ResourceList and populate
this field in the output ResourceList.
items:
type: object
functionConfig:
type: object
description: |
[input]
FunctionConfig is an optional Kubernetes object for passing arguments to a
function invocation.
results:
type: array
description: |
[output]
Results is an optional list that can be used by function to emit results
for observability and debugging purposes.
items:
"$ref": "#/definitions/Result"
Result:
type: object
required:
- message
properties:
message:
type: string
description: Message is a human readable message.
severity:
type: string
enum:
- error
- warning
- info
default: error
description: |
Severity is the severity of a result:
"error": indicates an error result.
"warning": indicates a warning result.
"info": indicates an informational result.
resourceRef:
type: object
description: |
ResourceRef is the metadata for referencing a Kubernetes object
associated with a result.
required:
- apiVersion
- kind
- name
properties:
apiVersion:
description:
APIVersion refers to the `apiVersion` field of the object
manifest.
type: string
kind:
description: Kind refers to the `kind` field of the object.
type: string
namespace:
description:
Namespace refers to the `metadata.namespace` field of the object
manifest.
type: string
name:
description:
Name refers to the `metadata.name` field of the object manifest.
type: string
field:
type: object
description: |
Field is the reference to a field in the object.
If defined, `ResourceRef` must also be provided.
required:
- path
properties:
path:
type: string
description: |
Path is the JSON path of the field
e.g. `spec.template.spec.containers[3].resources.limits.cpu`
currentValue:
description: |
CurrrentValue is the current value of the field.
Can be any value - string, number, boolean, array or object.
proposedValue:
description: |
PropposedValue is the proposed value of the field to fix an issue.
Can be any value - string, number, boolean, array or object.
file:
type: object
description: File references a file containing the resource.
required:
- path
properties:
path:
type: string
description: |
Path is the OS agnostic, slash-delimited, relative path.
e.g. `some-dir/some-file.yaml`.
index:
type: number
default: 0
description: Index of the object in a multi-object YAML file.
tags:
type: object
additionalProperties:
type: string
description: |
Tags is an unstructured key value map stored with a result that may be set
by external tools to store and retrieve arbitrary metadata.
paths: {}
The following is an example input, where the custom resource of kind
FulfillmentCenter is provided as functionConfig. The function will operate
on one resource of kind Service.
apiVersion: config.kubernetes.io/v1
kind: ResourceList
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
spec:
address: "100 Main St."
items:
- apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
annotations:
internal.config.kubernetes.io/index: "0"
internal.config.kubernetes.io/path: "service.yaml"
spec: # Example comment
type: LoadBalancer
selector:
app: wordpress
tier: frontend
ports:
- protocol: TCP
port: 80
The following is an example output containing one result representing a validation error:
apiVersion: config.kubernetes.io/v1
kind: ResourceList
items:
- apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
annotations:
internal.config.kubernetes.io/index: "0"
internal.config.kubernetes.io/path: "service.yaml"
spec: # Example comment
type: LoadBalancer
selector:
app: wordpress
tier: frontend
ports:
- protocol: TCP
port: 80
results:
- message: "Invalid type. Expected: integer, given: string"
severity: error
resourceRef:
apiVersion: v1
kind: Service
name: wordpress
field:
path: spec.ports.0.port
file:
path: service.yaml
A function MUST support YAML as a serialization format for the input and output. A function MUST use utf8 encoding (as YAML is a superset of JSON, JSON will also be supported by any conforming function).
A function MUST be implemented as a container.
A function container MUST be capable of running as a non-root user nobody if
it does not require access to host filesystem.
Any non-structured error messages MUST be emitted to stderr. stdout is
reserved for ResourceList as described above.
An exit code of zero indicates function execution was successful. A non-zero exit code indicates a failure.
A function MAY Create, Update, or Delete any number of items in the items
field and output the resultant list in the corresponding items field of the
output.
A function SHOULD preserve comments when input serialization format is YAML. This allows for human authoring of configuration to coexist with changes made by functions.
For orchestration purposes, the orchestrator will use a set of annotations,
referred to as internal annotations, on resources in Resources.items. These
annotations are not persisted to resource manifests on the filesystem: The
orchestrator sets this annotation when reading files from the local filesystem
and removes the annotation when writing the output of functions back to the
filesystem.
Annotation prefix internal.config.kubernetes.io is reserved for use for
internal annotations. In general, a function MUST NOT modify these annotations with
the exception of the specific annotations listed below. This enables orchestrators to add additional internal annotations, without requiring changes to existing functions.
internal.config.kubernetes.io/pathRecords the slash-delimited, OS-agnostic, relative file path to a resource. The path is relative to a fix location on the filesystem. Different orchestrator implementations can choose different fixed points.
A function SHOULD NOT modify these annotations.
Example:
metadata:
annotations:
internal.config.kubernetes.io/path: "relative/file/path.yaml"
internal.config.kubernetes.io/indexRecords the index of a Resource in file. In a multi-object YAML file, resources
are separated by three dashes (---), and the index represents the position of
the Resource starting from zero. When this annotation is not specified, it
implies a value of 0.
A function SHOULD NOT modify these annotations.
Example:
metadata:
annotations:
internal.config.kubernetes.io/path: "relative/file/path.yaml"
internal.config.kubernetes.io/index: 2
This represents the third resource in the file.