334 lines
7.1 KiB
Markdown
334 lines
7.1 KiB
Markdown
# Helm Chart Scaffolding
|
|
|
|
Generate production-ready Helm charts with best practices.
|
|
|
|
## Task
|
|
|
|
You are a Helm expert. Generate complete Helm chart structure for applications.
|
|
|
|
### Steps:
|
|
|
|
1. **Ask for Information**:
|
|
- Chart name
|
|
- Application type (web app, API, worker, etc.)
|
|
- Dependencies (databases, caches, etc.)
|
|
|
|
2. **Generate Chart Structure**:
|
|
|
|
```
|
|
my-app/
|
|
├── Chart.yaml
|
|
├── values.yaml
|
|
├── values-dev.yaml
|
|
├── values-staging.yaml
|
|
├── values-prod.yaml
|
|
├── templates/
|
|
│ ├── NOTES.txt
|
|
│ ├── _helpers.tpl
|
|
│ ├── deployment.yaml
|
|
│ ├── service.yaml
|
|
│ ├── ingress.yaml
|
|
│ ├── configmap.yaml
|
|
│ ├── secret.yaml
|
|
│ ├── hpa.yaml
|
|
│ ├── serviceaccount.yaml
|
|
│ ├── networkpolicy.yaml
|
|
│ └── tests/
|
|
│ └── test-connection.yaml
|
|
├── charts/ # Subcharts
|
|
└── .helmignore
|
|
```
|
|
|
|
3. **Generate Chart.yaml**:
|
|
|
|
```yaml
|
|
apiVersion: v2
|
|
name: my-app
|
|
description: A Helm chart for my-app
|
|
type: application
|
|
version: 1.0.0 # Chart version
|
|
appVersion: "1.0.0" # Application version
|
|
|
|
keywords:
|
|
- application
|
|
- api
|
|
|
|
home: https://github.com/myorg/my-app
|
|
sources:
|
|
- https://github.com/myorg/my-app
|
|
|
|
maintainers:
|
|
- name: Your Name
|
|
email: you@example.com
|
|
url: https://example.com
|
|
|
|
dependencies:
|
|
- name: postgresql
|
|
version: "12.x.x"
|
|
repository: https://charts.bitnami.com/bitnami
|
|
condition: postgresql.enabled
|
|
- name: redis
|
|
version: "17.x.x"
|
|
repository: https://charts.bitnami.com/bitnami
|
|
condition: redis.enabled
|
|
```
|
|
|
|
4. **Generate values.yaml**:
|
|
|
|
```yaml
|
|
# Default values for my-app
|
|
# This is a YAML-formatted file
|
|
|
|
replicaCount: 3
|
|
|
|
image:
|
|
repository: myapp
|
|
pullPolicy: IfNotPresent
|
|
tag: "" # Overrides appVersion
|
|
|
|
imagePullSecrets: []
|
|
|
|
nameOverride: ""
|
|
fullnameOverride: ""
|
|
|
|
serviceAccount:
|
|
create: true
|
|
annotations: {}
|
|
name: ""
|
|
|
|
podAnnotations:
|
|
prometheus.io/scrape: "true"
|
|
prometheus.io/port: "8080"
|
|
|
|
podSecurityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1000
|
|
fsGroup: 2000
|
|
|
|
securityContext:
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
readOnlyRootFilesystem: true
|
|
allowPrivilegeEscalation: false
|
|
|
|
service:
|
|
type: ClusterIP
|
|
port: 80
|
|
targetPort: 8080
|
|
|
|
ingress:
|
|
enabled: true
|
|
className: "nginx"
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
|
hosts:
|
|
- host: myapp.example.com
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
tls:
|
|
- secretName: myapp-tls
|
|
hosts:
|
|
- myapp.example.com
|
|
|
|
resources:
|
|
limits:
|
|
cpu: 500m
|
|
memory: 512Mi
|
|
requests:
|
|
cpu: 250m
|
|
memory: 256Mi
|
|
|
|
autoscaling:
|
|
enabled: true
|
|
minReplicas: 3
|
|
maxReplicas: 10
|
|
targetCPUUtilizationPercentage: 70
|
|
targetMemoryUtilizationPercentage: 80
|
|
|
|
nodeSelector: {}
|
|
|
|
tolerations: []
|
|
|
|
affinity:
|
|
podAntiAffinity:
|
|
preferredDuringSchedulingIgnoredDuringExecution:
|
|
- weight: 100
|
|
podAffinityTerm:
|
|
labelSelector:
|
|
matchExpressions:
|
|
- key: app.kubernetes.io/name
|
|
operator: In
|
|
values:
|
|
- my-app
|
|
topologyKey: kubernetes.io/hostname
|
|
|
|
# Application-specific configs
|
|
config:
|
|
logLevel: info
|
|
nodeEnv: production
|
|
|
|
# Dependencies
|
|
postgresql:
|
|
enabled: true
|
|
auth:
|
|
database: myapp
|
|
username: myapp
|
|
primary:
|
|
persistence:
|
|
enabled: true
|
|
size: 10Gi
|
|
|
|
redis:
|
|
enabled: true
|
|
architecture: standalone
|
|
auth:
|
|
enabled: true
|
|
```
|
|
|
|
5. **Generate deployment.yaml (templated)**:
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: {{ include "my-app.fullname" . }}
|
|
labels:
|
|
{{- include "my-app.labels" . | nindent 4 }}
|
|
spec:
|
|
{{- if not .Values.autoscaling.enabled }}
|
|
replicas: {{ .Values.replicaCount }}
|
|
{{- end }}
|
|
selector:
|
|
matchLabels:
|
|
{{- include "my-app.selectorLabels" . | nindent 6 }}
|
|
template:
|
|
metadata:
|
|
annotations:
|
|
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
|
{{- with .Values.podAnnotations }}
|
|
{{- toYaml . | nindent 8 }}
|
|
{{- end }}
|
|
labels:
|
|
{{- include "my-app.selectorLabels" . | nindent 8 }}
|
|
spec:
|
|
{{- with .Values.imagePullSecrets }}
|
|
imagePullSecrets:
|
|
{{- toYaml . | nindent 8 }}
|
|
{{- end }}
|
|
serviceAccountName: {{ include "my-app.serviceAccountName" . }}
|
|
securityContext:
|
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
|
containers:
|
|
- name: {{ .Chart.Name }}
|
|
securityContext:
|
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
ports:
|
|
- name: http
|
|
containerPort: {{ .Values.service.targetPort }}
|
|
protocol: TCP
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: http
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /ready
|
|
port: http
|
|
resources:
|
|
{{- toYaml .Values.resources | nindent 12 }}
|
|
env:
|
|
- name: NODE_ENV
|
|
value: {{ .Values.config.nodeEnv }}
|
|
- name: LOG_LEVEL
|
|
value: {{ .Values.config.logLevel }}
|
|
{{- if .Values.postgresql.enabled }}
|
|
- name: DB_HOST
|
|
value: {{ include "my-app.fullname" . }}-postgresql
|
|
- name: DB_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ include "my-app.fullname" . }}-postgresql
|
|
key: password
|
|
{{- end }}
|
|
```
|
|
|
|
6. **Generate _helpers.tpl**:
|
|
|
|
```yaml
|
|
{{/*
|
|
Expand the name of the chart.
|
|
*/}}
|
|
{{- define "my-app.name" -}}
|
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
{{- end }}
|
|
|
|
{{/*
|
|
Create a default fully qualified app name.
|
|
*/}}
|
|
{{- define "my-app.fullname" -}}
|
|
{{- if .Values.fullnameOverride }}
|
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
{{- else }}
|
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
{{- if contains $name .Release.Name }}
|
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
{{- else }}
|
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
|
|
{{/*
|
|
Common labels
|
|
*/}}
|
|
{{- define "my-app.labels" -}}
|
|
helm.sh/chart: {{ include "my-app.chart" . }}
|
|
{{ include "my-app.selectorLabels" . }}
|
|
{{- if .Chart.AppVersion }}
|
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
{{- end }}
|
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
{{- end }}
|
|
|
|
{{/*
|
|
Selector labels
|
|
*/}}
|
|
{{- define "my-app.selectorLabels" -}}
|
|
app.kubernetes.io/name: {{ include "my-app.name" . }}
|
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
{{- end }}
|
|
```
|
|
|
|
### Deployment Commands:
|
|
|
|
```bash
|
|
# Install chart
|
|
helm install my-app ./my-app -f values-dev.yaml
|
|
|
|
# Upgrade
|
|
helm upgrade my-app ./my-app -f values-prod.yaml
|
|
|
|
# Template (dry-run)
|
|
helm template my-app ./my-app -f values-prod.yaml
|
|
|
|
# Lint
|
|
helm lint ./my-app
|
|
|
|
# Package
|
|
helm package ./my-app
|
|
|
|
# Test
|
|
helm test my-app
|
|
```
|
|
|
|
### Example Usage:
|
|
|
|
```
|
|
User: "Create Helm chart for Node.js API with PostgreSQL"
|
|
Result: Complete Helm chart with all templates and values files
|
|
```
|