User Manifests in mpy-metapackage¶
Available from 2.3.17
Introduction¶
The user_manifests section allows you to inject custom Kubernetes manifests directly through mpy-metapackage. This mechanism is designed to:
- Bypass certain limitations of Helm templating.
- Quickly test low-level configurations without modifying the core package.
- Facilitate experimentation with custom Kubernetes resources.
Structure of user_manifests¶
The user_manifests block is defined in the Helm values.yaml under the mpy_meta_config.parts section:
mpy_meta_config:
parts:
user_manifests:
- description: "Custom IngressRoute for SSH access"
definition: |
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: "{{ $.Values.package_release.key }}-ssh-ingressroute"
namespace: "{{ $.Release.Namespace }}"
labels:
app.kubernetes.io/component: "user-ssh-ingressroute"
spec:
entryPoints:
- websecure
routes:
- match: HostSNI(`mkrds-{{ $.Values.package_release.main_fqdn }}`)
services:
- name: {{ $.Values.package_release.key }}-myapp-svc
port: 2222
tls:
passthrough: true
Fields:¶
description: (Optional) A description for documentation and traceability.definition: (Required) The complete manifest to inject.
Automatic Labels and Annotations¶
Each user_manifests entry receives the following labels and annotations:
- Labels:
- app.kubernetes.io/name: Name of the application.
- app.kubernetes.io/instance: Release name.
- app.kubernetes.io/version: Version of the package.
- app.kubernetes.io/managed-by: Helm
- helm.sh/chart: Chart version.
- muppy.io/package-release: Package release key.
- Annotations:
m2p_user_manifest: Set totrueto mark it as user-injected.m2p_injection_timestamp: Timestamp of injection.m2p_metapackage_version: The version ofmpy-metapackage.
Namespace Management¶
If the namespace field is not specified in the manifest, it will automatically default to:
missing-required-namespace
This prevents deployment issues and makes debugging easier.
Cluster-scoped objects¶
A ClusterRoleBinding, a ClusterRole or any other cluster-scoped kind is written with a
namespace all the same: the template requires the field, and the API server ignores it on
a kind that has none. The Parts Config of Muppy itself declares one this way, to let its key
holder ask the API server who is calling:
user_manifests:
- description: lets mpy-masterkeyd ask the API server who is calling (TokenReview)
definition: |
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: "{{ .Values.package_release.key }}-mkeyd-tokenreview"
namespace: "{{ .Release.Namespace }}"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: default
namespace: "{{ .Release.Namespace }}"
Name it after the Release key: a cluster-scoped name is unique for the whole cluster, and two Releases of the same package would otherwise fight over one object. Muppy syncs the RBAC kinds with the Release's other objects (Kubernetes ▸ Objects) and links a cluster-scoped one to its Release through the labels the chart stamps on it.
Usage¶
To deploy user manifests:
helm upgrade --install my-release . --values values.yaml
To check the injected objects:
kubectl get all -A --selector=m2p_user_manifest=true
To troubleshoot:
kubectl describe <object> -n <namespace>
Best Practices¶
- Always validate the
definitionbefore injection. - Use
helm templatefor local testing before deployment. - Prefer specific
namespacedeclarations to avoid fallback issues.