A set of flexible kustomization resources that provide useful defaults for generic applications deployed in enthusiast-grade Kubernetes clusters.
This set of Kustomizations is built from the following observations:
- Most selfhostable applications are cut by the same statefulset-service-ingress pattern.
- Some of them will have small deviations from the pattern.
- Deployments for the same application do not vary a lot between different clusters.
- Cluster-specific variations are often reusable across applications.
This set of Kustomizations attempts to provide highly composable Kustomize resources that can be used to create applications from a common base. It does not attempt to be exhaustive, but it does attempt to capture in a composable way the most common patterns of a simple deployment.
Application-specific quirks can be applied using patches on top of the provided components.
Cluster-specific variations can be built by users on a different repo. As an example, composable variations for my personal cluster cury
can be found in contrib/curry
.
This project uses semver, but changes to the contrib/
folder are not considered breaking.
A collection of resources
(static, plain manifests) that are modified by patches
, and other modifications that are applied on top of them.
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ingress.yaml
patches:
- patch: |
- op: replace
path: /spec/rules/0/host
value: testapp.terabox.moe
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: foo.bar
# ...
Kustomizations
can include other kustomizations
, e.g. A includes B. The included kustomization patches are applied first on top of those resources, then the includer kustomization
's patches are applied on top of all resources.
The included patches cannot reference manifests in the includer kustomization
, or in other included kustomizations
.
Replacements
can get fields from an object and paste it into others.
The Replacement
below gets the name of a Deployment
and copies it into the name of all Ingresses
and Services
in the Kustomization
.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Replacement
source:
kind: Deployment
fieldPath: metadata.name
targets:
- select:
kind: Ingress
fieldPaths: metadata.name
- select:
kind: Service
fieldPaths: metadata.name
Like patches, the fieldPath
fields support descending into arbitrarly deep nodes, and filtering arrays.
Replacements
Components
change the rules of the game, by defining sets of both manifests and modifiers (patches, replacements, etc.) that are applied to all manifests belonging to the Kustomization that imports them.
This means a Component
acts as a reusable patch set that can affect siblings and parents.
By defining a set of Replacements
and Patches
into a Component
we can make, for example, a Component
that creates a Service
manifest for a given port, and injects that very same port into the first container of a StatefulSet
that does not belong to the Component
.
This makes heavy (ab)use of Components
and Replacements
to provide a skeleton for standard webapps, which are composed of a StatefulSet
with a single container and a path to persist data, a Service
, and an Ingress
.
Base Components
get some application-specific information using a Replacement
that copies things from a ConfigMap
called kustomization-meta
. This ConfigMap
needs to be defined by the app and have a name
and a port
properties.
Other application-specific behavior is defined as Patches
or Replacements
. name
and port
are not specified this way because they need to be templated across multiple components, and they need to exist
The ss-base
component provides a simple StatefulSet
. ss-base/port
and ss-base/pvc
can be used to add a port or a PVC to this StatefulSet
, and ss-base/mount
to mount that PVC. ingress
and service
can be used to add the corresponding resources to the application as well.
All these components can modify each other by leveraging labelSelector
s. E.g., ss-base/service
knows to which StatefulSet
it needs to patch because the StatefulSet
generated by the ss-base
component has a specific label for this purpose.
# testapp.yaml
resources:
- meta.yaml
components:
- ../_resources/ingress/internal
- ../_resources/ss-base
- ../_resources/ss-base/hostpath
- ../_resources/ss-base/service
- ../_resources/_names
patches:
- target:
kind: Ingress
patch: |
- op: replace
path: /spec/rules/0/host
value: testapp.terabox.moe
images:
- name: _
newName: ghcr.io/roobre/testapp:1.2.3
# meta.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kustomize-meta
data:
name: testapp
port: "8080"