Skip to content
Go back

[Tools] Drunk Charts: A Reusable Helm Library for Kubernetes Deployments


Introduction

If you’ve managed multiple microservices on Kubernetes, you’ve likely felt the pain of maintaining dozens of near-identical Helm charts — each with the same Deployment, Service, Ingress, and HPA templates copied and slightly tweaked. It’s tedious, error-prone, and hard to keep consistent.

To solve this, I built drunk.charts — a set of Helm charts anchored by a library chart (drunk-lib) that provides standardized, reusable templates, and a thin application chart (drunk-app) that consumes it. Deploy any application by simply providing a values.yaml — no template duplication required.

All charts are published as OCI artifacts on GitHub Container Registry at oci://ghcr.io/baoduy and are available on Artifact Hub.


Table of Contents

Open Table of Contents

Architecture

The design follows Helm’s library chart pattern:

drunk-lib (library chart — type: library)
  └── 19 named templates: drunk-lib.<resource-type>
  └── Published as OCI: oci://ghcr.io/baoduy/drunk-lib

drunk-app (application chart — type: application)
  └── Thin wrapper: each template is a single include of drunk-lib.<name>
  └── Declares drunk-lib as a dependency
  └── Published as OCI: oci://ghcr.io/baoduy/drunk-app

This separation means you fix a bug or add a feature in drunk-lib once, bump the version, and every drunk-app deployment inherits it on the next helm dependency update.



drunk-lib: The Library Chart

drunk-lib (v1.3.0) is a Helm library chart — it produces no resources on its own. Instead, it provides named templates that other charts invoke via {{ include "drunk-lib.<name>" . }}.

Available Templates

CategoryTemplateResource Generated
Core Workloadsdrunk-lib.deploymentapps/v1 Deployment
drunk-lib.statefulsetapps/v1 StatefulSet
Networkingdrunk-lib.servicev1 Service
drunk-lib.ingressnetworking.k8s.io/v1 Ingress
drunk-lib.gatewaygateway.networking.k8s.io/v1 Gateway
drunk-lib.httproutegateway.networking.k8s.io/v1 HTTPRoute
drunk-lib.backendTlsPolicygateway.networking.k8s.io BackendTLSPolicy
Configurationdrunk-lib.configMapv1 ConfigMap
drunk-lib.secretsv1 Secret
drunk-lib.secretProviderClassSecretProviderClass (CSI Driver)
drunk-lib.tls-secretsv1 Secret (TLS type)
Storagedrunk-lib.volumesv1 PersistentVolumeClaim
Batchdrunk-lib.cronjobbatch/v1 CronJob
drunk-lib.jobbatch/v1 Job
Scalingdrunk-lib.hpaautoscaling/v2 HorizontalPodAutoscaler
Securitydrunk-lib.networkPolicynetworking.k8s.io/v1 NetworkPolicy
drunk-lib.serviceAccountv1 ServiceAccount
drunk-lib.imagePull-secretv1 Secret (dockerconfigjson)

Helper Functions

The chart also provides shared helper templates:

How Templates Work

Each template is self-contained and gate-controlled. For example, the Deployment template:

  1. Checks .Values.deployment.enabled — no-op if false
  2. Composes pod metadata using app.labels / app.selectorLabels
  3. Attaches checksum annotations via app.checksums so ConfigMap/Secret changes trigger rollouts
  4. Wires init containers from .Values.global.initContainer
  5. Pulls environment from configMap, secrets, configFrom[], secretFrom[], and CSI secretProvider
  6. Reads scheduling (nodeSelector, affinity, tolerations), security contexts, resources, and volumes from root-level values — shared with sibling resources (Jobs, CronJobs)
  7. Hard-codes automountServiceAccountToken: false for security

Deployment Template — Full Schema

KeyTypeDefaultNotes
deployment.enabledboolfalseGate for the entire resource
deployment.replicaCountint1Pod replicas
deployment.strategy.typestringRollingUpdateRollingUpdate or Recreate
deployment.strategy.maxSurgeint/string1Rolling update config
deployment.strategy.maxUnavailableint/string0Rolling update config
deployment.portsmapname: containerPort pairs
deployment.commandlistContainer command override
deployment.argslistContainer args override
deployment.livenessstringHTTP path for liveness probe
deployment.readinessstringHTTP path for readiness probe
deployment.podAnnotationsmapExtra pod annotations

StatefulSet Template

For workloads requiring stable network identity and persistent storage. Same pod spec composition as Deployment, with added volumeClaimTemplates support and headless Service generation.

Security Defaults

All templates enforce security best practices out of the box:

podSecurityContext:
  fsGroup: 10000
  runAsUser: 10000
  runAsGroup: 10000

securityContext:
  capabilities:
    drop: ["ALL"]
  readOnlyRootFilesystem: true
  runAsNonRoot: true

Using drunk-lib in Your Own Charts

To build a custom chart on top of drunk-lib:

# Chart.yaml
apiVersion: v2
name: my-custom-chart
type: application
dependencies:
  - name: drunk-lib
    version: "1.3.0"
    repository: "oci://ghcr.io/baoduy"

Then in your templates:

# templates/deployment.yaml
{{- include "drunk-lib.deployment" . -}}

# templates/service.yaml
{{- include "drunk-lib.service" . -}}


drunk-app: The Application Chart

drunk-app (v1.3.5) is the ready-to-use chart for deploying applications. It’s intentionally a thin wrapper — every template file is a single line:

{{- include "drunk-lib.deployment" . -}}

This means you never write templates. You configure everything through values.yaml.

Installation

# From OCI registry (recommended)
helm install my-app oci://ghcr.io/baoduy/drunk-app --version 1.3.5 -f values.yaml

# Or via Helm repo
helm repo add drunk-charts https://baoduy.github.io/drunk.charts/drunk-app
helm repo update
helm install my-app drunk-charts/drunk-app -f values.yaml

Minimal Deployment

global:
  image: my-registry.azurecr.io/my-app
  tag: "1.0.0"

deployment:
  enabled: true
  ports:
    http: 8080

service:
  type: ClusterIP

volumes:
  - name: tmp
    emptyDir: {}
    mountPath: /tmp

Note: The tmp volume is essential because readOnlyRootFilesystem: true is the default — your app needs a writable /tmp.

Environment Variables and Secrets

# Inline environment variables
env:
  APP_ENV: production
  LOG_LEVEL: info

# Inline secrets (stored as K8s Secret)
secrets:
  DB_CONNECTION: "Server=db;Database=mydb;User=admin;Password=secret"

# Reference existing secrets
secretFrom:
  - name: existing-secret
    key: connection-string
    envName: DB_CONNECTION

# Reference existing configmaps
configFrom:
  - name: shared-config
    key: api-url
    envName: API_URL

Health Checks and Autoscaling

deployment:
  enabled: true
  ports:
    http: 8080
  liveness: /healthz
  readiness: /ready

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 128Mi

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70
  targetMemoryUtilizationPercentage: 80

Azure Key Vault Integration (CSI Driver)

secretProvider:
  enabled: true
  tenantId: "your-tenant-id"
  vaultName: "my-keyvault"
  useWorkloadIdentity: true
  objects:
    - name: db-connection-string
      type: secret
      envName: DB_CONNECTION
    - name: api-key
      type: secret
      envName: API_KEY

TLS Secrets Management

Three modes supported:

tlsSecrets:
  # Mode 1: Inline base64-encoded certificates
  - name: my-tls
    cert: <base64-encoded-cert>
    key: <base64-encoded-key>

  # Mode 2: File-based (populate via --set-file during helm install)
  - name: my-tls-file
    certFile: true
    cert: ""
    key: ""

  # Mode 3: CA certificate only (for backend TLS validation)
  - name: my-ca
    ca: <base64-encoded-ca>

Gateway API with TLS Validation

For clusters using the Gateway API instead of traditional Ingress:

httpRoute:
  enabled: true
  hostnames:
    - my-app.drunkcoding.net
  rules:
    - backendRefs:
        - name: my-app
          port: 8080
  parentRefs:
    - name: main-gateway
      namespace: gateway-system
  validation:
    enabled: true
    hostname: my-app.drunkcoding.net
    wellKnownCACertificates: System

CronJobs and Jobs

cronJobs:
  - name: nightly-cleanup
    enabled: true
    schedule: "0 2 * * *"
    command: ["./cleanup.sh"]
    resources:
      limits:
        cpu: 200m
        memory: 256Mi

jobs:
  - name: db-migration
    enabled: true
    command: ["dotnet", "ef", "database", "update"]

Network Policies

networkPolicies:
  - name: allow-ingress-only
    podSelector:
      matchLabels:
        app: my-app
    ingress:
      - from:
          - namespaceSelector:
              matchLabels:
                name: ingress-system
        ports:
          - port: 8080
    policyTypes:
      - Ingress

Init Containers

global:
  image: my-registry.azurecr.io/my-app
  tag: "1.0.0"
  initContainer:
    image: busybox
    tag: latest
    command: ["sh", "-c", "echo initializing"]


Claude Code AI Plugins

Both charts ship with Claude Code plugins that provide AI-assisted configuration. These are available on the Claude Code Plugin Marketplace.

Installing the Plugins

# Add from marketplace
plugin marketplace add baoduy/drunk.charts

drunk-app Plugin

The drunk-app plugin provides an AI assistant with three modes:

  1. Answer — Ask “how does X work?” and get explanations with YAML snippets
  2. Generate — Say “give me a values.yaml for [use case]” and get a complete, validated configuration
  3. Validate — Paste a values.yaml and get a full validation report with fix instructions

Example interactions:

/drunk-app generate a values.yaml for a .NET API with health checks, 
autoscaling, and Azure Key Vault secrets

/drunk-app validate my values.yaml — is the probe configuration correct?

/drunk-app how do I configure multiple network policies?

drunk-lib Plugin

The drunk-lib plugin provides per-template expert skills — 18 specialized assistants, one for each resource type:

SkillExpertise
drunk-lib-deploymentDeployment workloads, rolling updates, pod spec
drunk-lib-statefulsetStateful workloads, headless services, volume claims
drunk-lib-serviceService types, port mapping
drunk-lib-ingressNginx ingress, TLS, path routing
drunk-lib-httprouteGateway API HTTPRoute configuration
drunk-lib-gatewayGateway resource setup
drunk-lib-backend-tls-policyBackend TLS validation
drunk-lib-hpaHorizontal Pod Autoscaler tuning
drunk-lib-cronjobScheduled batch workloads
drunk-lib-jobOne-off batch workloads
drunk-lib-configmapConfigMap from values
drunk-lib-secretsSecret management
drunk-lib-secretproviderCSI Secret Store (Azure Key Vault, AWS)
drunk-lib-tls-secretsTLS certificate management
drunk-lib-networkpolicyNetwork isolation rules
drunk-lib-serviceaccountServiceAccount configuration
drunk-lib-imagepull-secretPrivate registry credentials
drunk-lib-volumesPVC and volume management

Each skill contains the exact values schema consumed by that template, the rendering logic, validation rules, and generation templates — so Claude can produce correct configurations without guessing.



Why a Library Chart?

ApproachProsCons
Copy-paste templates per serviceFull controlDrift, maintenance nightmare
Umbrella chart with subchartsOrganizedHeavy, complex dependency management
Library chart + thin wrapperDRY, consistent, flexibleSlightly opinionated defaults

The library chart pattern gives you:

  1. Single source of truth — fix a bug in drunk-lib, all apps get it on next upgrade
  2. Consistency — every service follows the same security, labeling, and resource patterns
  3. Speed — new services need only a values.yaml, no template work
  4. Flexibility — disable any resource by setting enabled: false
  5. AI-ready — Claude Code plugins understand the exact schema and can generate/validate configs

OCI Distribution

All charts are published to GitHub Container Registry as OCI artifacts:

# Pull directly
helm pull oci://ghcr.io/baoduy/drunk-app --version 1.3.5
helm pull oci://ghcr.io/baoduy/drunk-lib --version 1.3.0

# Use as dependency
# Chart.yaml
dependencies:
  - name: drunk-lib
    version: "1.3.0"
    repository: "oci://ghcr.io/baoduy"

Published packages are visible at github.com/baoduy?tab=packages&repo_name=drunk.charts.


Conclusion

drunk.charts eliminates the boilerplate of Kubernetes deployments while maintaining full flexibility. The drunk-lib library chart provides battle-tested templates with security-first defaults, and drunk-app makes them instantly usable with just a values.yaml. Combined with Claude Code AI plugins that understand the exact schema, you can generate and validate configurations with confidence.

The charts are open source and actively maintained. Contributions and feedback are welcome on GitHub.


Share this post on:

Previous Post
[.NET] Streamline Your DTOs with DKNet.EfCore.DtoGenerator
Next Post
[Az] Day 12: Enabling MDM Devices by leverage Cloudflare Tunnel and WARP.