Bootstrap stateless Web & API workloads and scheduled jobs in seconds.
helm-serve is a DRY (Don't Repeat Yourself) Helm Library Chart designed to act as a standardized foundation for microservices and scheduled tasks. It abstracts away the complexity of defining repetitive Deployment, Service, Ingress, and CronJob manifests, allowing developers to focus on configuration rather than boilerplate YAML.
- Zero Boilerplate: Define your app with just a few lines of YAML.
- Multi-Mode Support: Switch between Deployment and CronJob modes by simply defining the relevant values section.
- Inversion of Control: Supports custom naming conventions via
templatePrefixinjection. - Dynamic Values: Supports Go Template syntax (
tpl) directly withinvalues.yaml. - Production Ready: Includes secure defaults (non-root users, resource limits), probes, and metadata injection.
- Standardized Networking: Auto-wired Ingress and Service configuration.
Since this is a Library Chart, it is not meant to be installed directly (helm install). Instead, add it as a dependency to your application chart.
- Add it to your application's
Chart.yaml:
dependencies:
- name: helm-serve
repository: oci://ghcr.io/btungut
version: 0.2.0 # <-- Check for the latest version- Update dependencies:
helm dependency update2.a. Clean your charts/ directory if needed:
rm -rf charts/ && helm dependency update .In your application chart's values.yaml, simply define the essentials. The library handles the rest.
# values.yaml (Minimal Example for Deployment Mode)
deployment:
replicaCount: 2
image:
repository: myrepo/my-app
tag: v1.0.0
containerPort: 80
service:
enabled: true
port: 80
ingress:
enabled: true
className: "nginx"
rule:
host: "api.mydomain.com"
path: /Running helm template . with this config will automatically generate:
- A Deployment with 2 replicas and resource limits enabled.
- A Service pointing to the pods.
- An Ingress routing traffic to that service.
For scheduled tasks, simply define the cronJob section in your values.yaml:
# values.yaml (Minimal Example for CronJob Mode)
cronJob:
schedule: "0 2 * * *" # Daily at 2am
image:
repository: myrepo/my-batch-job
tag: v1.0.0
env:
JOB_TYPE: "data-processing"This will generate a CronJob resource with secure defaults and resource limits.
helm-serve is agnostic to naming conventions. It delegates the responsibility of naming resources to the Consumer Chart.
To use your own naming logic (e.g., my-app-fullname), define a helper template in your chart and pass the prefix:
# values.yaml
templatePrefix: "my-custom-naming-prefix"The library will then call {{ include "my-custom-naming-prefix.fullname" . }} to name resources.
You can find example values.yaml files demonstrating various configurations in the test/ directory.
Minimal configuration with just deployment, service, and ingress basics. Visit test/values-basic.yaml for details.
Intermediate configuration with shared values, ConfigMaps, Secrets, NodePort service, and environment variables. Visit test/values-middle.yaml for details.
Comprehensive configuration showcasing all features including custom labels, annotations, probes, template prefix override, and dynamic value injection via tpl.
Visit test/values-full.yaml for details.
CronJob configuration for scheduled tasks with cron schedule, concurrency policies, job history limits, and resource management. Visit test/values-cronjob.yaml for details.
The library supports two modes: Deployment and CronJob. The mode is determined automatically based on which values section you define:
deploymentkey present in values: Renders Deployment resource. Service and Ingress are also rendered if theirenabledflag is set totrue.cronJobkey present in values: Renders CronJob resource only.
This allows you to use the same library chart for both long-running services and scheduled batch jobs without any extra configuration.
The following table lists the configurable parameters of the helm-serve chart and their default values.
| Parameter | Description | Default |
|---|---|---|
templatePrefix |
Critical: The prefix used to invoke naming templates from the consumer chart. | {{ .Chart.Name }} |
shared |
A map for defining shared variables accessible via tpl elsewhere. |
{} |
| Parameter | Description | Default |
|---|---|---|
deployment.replicaCount |
Number of desired pods. | 1 |
deployment.revisionHistoryLimit |
Number of old ReplicaSets to retain. | 0 (GitOps friendly) |
deployment.terminationGracePeriodSeconds |
Duration the pod needs to terminate gracefully. | 10 |
deployment.image.repository |
Container image repository. | "" |
deployment.image.tag |
Container image tag. | "" |
deployment.image.pullPolicy |
Image pull policy. | IfNotPresent |
deployment.imagePullSecrets |
List of image pull secrets. | [] |
deployment.containerPort |
The port the container exposes. | Required |
deployment.env |
Key-value pairs for environment variables. Supports tpl string interpolation. |
{} |
deployment.configMaps |
List of ConfigMaps to mount/inject ({name: "", required: bool}). |
[] |
deployment.secrets |
List of Secrets to mount/inject ({name: "", required: bool}). |
[] |
deployment.resources |
CPU/Memory requests and limits. | requests/limits: cpu: 200m, memory: 256Mi |
deployment.startupProbe |
Kubernetes Startup Probe configuration. | {} |
deployment.livenessProbe |
Kubernetes Liveness Probe configuration. | {} |
deployment.readinessProbe |
Kubernetes Readiness Probe configuration. | {} |
deployment.labels |
Custom labels added to Deployment metadata. | {} |
deployment.podAnnotations |
Custom annotations added to Pod metadata. | {} |
| Parameter | Description | Default |
|---|---|---|
service.enabled |
Enable or disable Service creation. | false |
service.name |
Override the default service name (Use with caution). | "" |
service.type |
Service type (ClusterIP, NodePort, LoadBalancer). | ClusterIP |
service.port |
The port exposed by the service. | Required if enabled |
service.nodePort |
Fixed NodePort (only if type is NodePort). | nil |
service.labels |
Custom labels for the Service. | {} |
| Parameter | Description | Default |
|---|---|---|
ingress.enabled |
Enable or disable Ingress creation. | false |
ingress.className |
Ingress controller class name (e.g., nginx). |
Required if enabled |
ingress.annotations |
Annotations for Ingress (e.g., rewrite rules). | {} |
ingress.rule.host |
The hostname for the ingress rule. | Required if enabled |
ingress.rule.path |
The path for the ingress rule. | Required if enabled |
ingress.rule.pathType |
Path match type (Prefix, Exact). | Prefix |
| Parameter | Description | Default |
|---|---|---|
cronJob.schedule |
Cron schedule expression (e.g., "*/5 * * * *"). |
Required |
cronJob.concurrencyPolicy |
How to handle concurrent executions (Allow, Forbid, Replace). | nil |
cronJob.successfulJobsHistoryLimit |
Number of successful jobs to keep. | nil |
cronJob.failedJobsHistoryLimit |
Number of failed jobs to keep. | nil |
cronJob.suspend |
Suspend the CronJob (true/false). | nil |
cronJob.startingDeadlineSeconds |
Deadline in seconds for starting the job if it misses scheduled time. | nil |
cronJob.backoffLimit |
Number of retries before marking job as failed. | nil |
cronJob.activeDeadlineSeconds |
Job timeout in seconds. | nil |
cronJob.ttlSecondsAfterFinished |
Clean up finished jobs after this duration. | nil |
cronJob.restartPolicy |
Pod restart policy (OnFailure or Never). | OnFailure |
cronJob.image.repository |
Container image repository. | "" |
cronJob.image.tag |
Container image tag. | "" |
cronJob.image.pullPolicy |
Image pull policy. | IfNotPresent |
cronJob.imagePullSecrets |
List of image pull secrets. | [] |
cronJob.env |
Key-value pairs for environment variables. Supports tpl. |
{} |
cronJob.configMaps |
List of ConfigMaps to inject ({name: "", required: bool}). |
[] |
cronJob.secrets |
List of Secrets to inject ({name: "", required: bool}). |
[] |
cronJob.resources |
CPU/Memory requests and limits. | requests/limits: cpu: 200m, memory: 256Mi |
cronJob.labels |
Custom labels added to CronJob metadata. | {} |
cronJob.podAnnotations |
Custom annotations added to Pod metadata. | {} |
You can reference values from other parts of your values.yaml or Helm context directly in your environment variables.
shared:
commonSecret: "my-org-secret"
deployment:
env:
# Injects the release name dynamically
APP_INSTANCE: "{{ .Release.Name }}"
# References the shared value defined above
API_KEY_REF: "{{ .Values.shared.commonSecret }}"The chart automatically injects the following environment variables into the container for observability:
HELM_Version: The chart version.HELM_AppVersion: The application version.HELM_Description: The chart description.HELM_Namespace: The release namespace.K8S_Namespace: The actual Kubernetes namespace (via Downward API).
This project is licensed under the Apache License 2.0.