Skip to content

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 to true to mark it as user-injected.
  • m2p_injection_timestamp: Timestamp of injection.
  • m2p_metapackage_version: The version of mpy-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 definition before injection.
  • Use helm template for local testing before deployment.
  • Prefer specific namespace declarations to avoid fallback issues.