Initial commit
This commit is contained in:
544
skills/helm-chart-scaffolding/SKILL.md
Normal file
544
skills/helm-chart-scaffolding/SKILL.md
Normal file
@@ -0,0 +1,544 @@
|
||||
---
|
||||
name: helm-chart-scaffolding
|
||||
description: Design, organize, and manage Helm charts for templating and packaging Kubernetes applications with reusable configurations. Use when creating Helm charts, packaging Kubernetes applications, or implementing templated deployments.
|
||||
---
|
||||
|
||||
# Helm Chart Scaffolding
|
||||
|
||||
Comprehensive guidance for creating, organizing, and managing Helm charts for packaging and deploying Kubernetes applications.
|
||||
|
||||
## Purpose
|
||||
|
||||
This skill provides step-by-step instructions for building production-ready Helm charts, including chart structure, templating patterns, values management, and validation strategies.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when you need to:
|
||||
- Create new Helm charts from scratch
|
||||
- Package Kubernetes applications for distribution
|
||||
- Manage multi-environment deployments with Helm
|
||||
- Implement templating for reusable Kubernetes manifests
|
||||
- Set up Helm chart repositories
|
||||
- Follow Helm best practices and conventions
|
||||
|
||||
## Helm Overview
|
||||
|
||||
**Helm** is the package manager for Kubernetes that:
|
||||
- Templates Kubernetes manifests for reusability
|
||||
- Manages application releases and rollbacks
|
||||
- Handles dependencies between charts
|
||||
- Provides version control for deployments
|
||||
- Simplifies configuration management across environments
|
||||
|
||||
## Step-by-Step Workflow
|
||||
|
||||
### 1. Initialize Chart Structure
|
||||
|
||||
**Create new chart:**
|
||||
```bash
|
||||
helm create my-app
|
||||
```
|
||||
|
||||
**Standard chart structure:**
|
||||
```
|
||||
my-app/
|
||||
├── Chart.yaml # Chart metadata
|
||||
├── values.yaml # Default configuration values
|
||||
├── charts/ # Chart dependencies
|
||||
├── templates/ # Kubernetes manifest templates
|
||||
│ ├── NOTES.txt # Post-install notes
|
||||
│ ├── _helpers.tpl # Template helpers
|
||||
│ ├── deployment.yaml
|
||||
│ ├── service.yaml
|
||||
│ ├── ingress.yaml
|
||||
│ ├── serviceaccount.yaml
|
||||
│ ├── hpa.yaml
|
||||
│ └── tests/
|
||||
│ └── test-connection.yaml
|
||||
└── .helmignore # Files to ignore
|
||||
```
|
||||
|
||||
### 2. Configure Chart.yaml
|
||||
|
||||
**Chart metadata defines the package:**
|
||||
|
||||
```yaml
|
||||
apiVersion: v2
|
||||
name: my-app
|
||||
description: A Helm chart for My Application
|
||||
type: application
|
||||
version: 1.0.0 # Chart version
|
||||
appVersion: "2.1.0" # Application version
|
||||
|
||||
# Keywords for chart discovery
|
||||
keywords:
|
||||
- web
|
||||
- api
|
||||
- backend
|
||||
|
||||
# Maintainer information
|
||||
maintainers:
|
||||
- name: DevOps Team
|
||||
email: devops@example.com
|
||||
url: https://github.com/example/my-app
|
||||
|
||||
# Source code repository
|
||||
sources:
|
||||
- https://github.com/example/my-app
|
||||
|
||||
# Homepage
|
||||
home: https://example.com
|
||||
|
||||
# Chart icon
|
||||
icon: https://example.com/icon.png
|
||||
|
||||
# Dependencies
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled
|
||||
- name: redis
|
||||
version: "17.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: redis.enabled
|
||||
```
|
||||
|
||||
**Reference:** See `assets/Chart.yaml.template` for complete example
|
||||
|
||||
### 3. Design values.yaml Structure
|
||||
|
||||
**Organize values hierarchically:**
|
||||
|
||||
```yaml
|
||||
# Image configuration
|
||||
image:
|
||||
repository: myapp
|
||||
tag: "1.0.0"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Number of replicas
|
||||
replicaCount: 3
|
||||
|
||||
# Service configuration
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
|
||||
# Ingress configuration
|
||||
ingress:
|
||||
enabled: false
|
||||
className: nginx
|
||||
hosts:
|
||||
- host: app.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
# Resources
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# Autoscaling
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
# Environment variables
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "info"
|
||||
|
||||
# ConfigMap data
|
||||
configMap:
|
||||
data:
|
||||
APP_MODE: production
|
||||
|
||||
# Dependencies
|
||||
postgresql:
|
||||
enabled: true
|
||||
auth:
|
||||
database: myapp
|
||||
username: myapp
|
||||
|
||||
redis:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
**Reference:** See `assets/values.yaml.template` for complete structure
|
||||
|
||||
### 4. Create Template Files
|
||||
|
||||
**Use Go templating with Helm functions:**
|
||||
|
||||
**templates/deployment.yaml:**
|
||||
```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:
|
||||
labels:
|
||||
{{- include "my-app.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.targetPort }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
env:
|
||||
{{- toYaml .Values.env | nindent 12 }}
|
||||
```
|
||||
|
||||
### 5. Create Template Helpers
|
||||
|
||||
**templates/_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 }}
|
||||
```
|
||||
|
||||
### 6. Manage Dependencies
|
||||
|
||||
**Add dependencies in Chart.yaml:**
|
||||
```yaml
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled
|
||||
```
|
||||
|
||||
**Update dependencies:**
|
||||
```bash
|
||||
helm dependency update
|
||||
helm dependency build
|
||||
```
|
||||
|
||||
**Override dependency values:**
|
||||
```yaml
|
||||
# values.yaml
|
||||
postgresql:
|
||||
enabled: true
|
||||
auth:
|
||||
database: myapp
|
||||
username: myapp
|
||||
password: changeme
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
```
|
||||
|
||||
### 7. Test and Validate
|
||||
|
||||
**Validation commands:**
|
||||
```bash
|
||||
# Lint the chart
|
||||
helm lint my-app/
|
||||
|
||||
# Dry-run installation
|
||||
helm install my-app ./my-app --dry-run --debug
|
||||
|
||||
# Template rendering
|
||||
helm template my-app ./my-app
|
||||
|
||||
# Template with values
|
||||
helm template my-app ./my-app -f values-prod.yaml
|
||||
|
||||
# Show computed values
|
||||
helm show values ./my-app
|
||||
```
|
||||
|
||||
**Validation script:**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Linting chart..."
|
||||
helm lint .
|
||||
|
||||
echo "Testing template rendering..."
|
||||
helm template test-release . --dry-run
|
||||
|
||||
echo "Checking for required values..."
|
||||
helm template test-release . --validate
|
||||
|
||||
echo "All validations passed!"
|
||||
```
|
||||
|
||||
**Reference:** See `scripts/validate-chart.sh`
|
||||
|
||||
### 8. Package and Distribute
|
||||
|
||||
**Package the chart:**
|
||||
```bash
|
||||
helm package my-app/
|
||||
# Creates: my-app-1.0.0.tgz
|
||||
```
|
||||
|
||||
**Create chart repository:**
|
||||
```bash
|
||||
# Create index
|
||||
helm repo index .
|
||||
|
||||
# Upload to repository
|
||||
# AWS S3 example
|
||||
aws s3 sync . s3://my-helm-charts/ --exclude "*" --include "*.tgz" --include "index.yaml"
|
||||
```
|
||||
|
||||
**Use the chart:**
|
||||
```bash
|
||||
helm repo add my-repo https://charts.example.com
|
||||
helm repo update
|
||||
helm install my-app my-repo/my-app
|
||||
```
|
||||
|
||||
### 9. Multi-Environment Configuration
|
||||
|
||||
**Environment-specific values files:**
|
||||
|
||||
```
|
||||
my-app/
|
||||
├── values.yaml # Defaults
|
||||
├── values-dev.yaml # Development
|
||||
├── values-staging.yaml # Staging
|
||||
└── values-prod.yaml # Production
|
||||
```
|
||||
|
||||
**values-prod.yaml:**
|
||||
```yaml
|
||||
replicaCount: 5
|
||||
|
||||
image:
|
||||
tag: "2.1.0"
|
||||
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 3
|
||||
maxReplicas: 20
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
hosts:
|
||||
- host: app.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
postgresql:
|
||||
enabled: true
|
||||
primary:
|
||||
persistence:
|
||||
size: 100Gi
|
||||
```
|
||||
|
||||
**Install with environment:**
|
||||
```bash
|
||||
helm install my-app ./my-app -f values-prod.yaml --namespace production
|
||||
```
|
||||
|
||||
### 10. Implement Hooks and Tests
|
||||
|
||||
**Pre-install hook:**
|
||||
```yaml
|
||||
# templates/pre-install-job.yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ include "my-app.fullname" . }}-db-setup
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: db-setup
|
||||
image: postgres:15
|
||||
command: ["psql", "-c", "CREATE DATABASE myapp"]
|
||||
restartPolicy: Never
|
||||
```
|
||||
|
||||
**Test connection:**
|
||||
```yaml
|
||||
# templates/tests/test-connection.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "my-app.fullname" . }}-test-connection"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
||||
```
|
||||
|
||||
**Run tests:**
|
||||
```bash
|
||||
helm test my-app
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern 1: Conditional Resources
|
||||
|
||||
```yaml
|
||||
{{- if .Values.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "my-app.fullname" . }}
|
||||
spec:
|
||||
# ...
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
### Pattern 2: Iterating Over Lists
|
||||
|
||||
```yaml
|
||||
env:
|
||||
{{- range .Values.env }}
|
||||
- name: {{ .name }}
|
||||
value: {{ .value | quote }}
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
### Pattern 3: Including Files
|
||||
|
||||
```yaml
|
||||
data:
|
||||
config.yaml: |
|
||||
{{- .Files.Get "config/application.yaml" | nindent 4 }}
|
||||
```
|
||||
|
||||
### Pattern 4: Global Values
|
||||
|
||||
```yaml
|
||||
global:
|
||||
imageRegistry: docker.io
|
||||
imagePullSecrets:
|
||||
- name: regcred
|
||||
|
||||
# Use in templates:
|
||||
image: {{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use semantic versioning** for chart and app versions
|
||||
2. **Document all values** in values.yaml with comments
|
||||
3. **Use template helpers** for repeated logic
|
||||
4. **Validate charts** before packaging
|
||||
5. **Pin dependency versions** explicitly
|
||||
6. **Use conditions** for optional resources
|
||||
7. **Follow naming conventions** (lowercase, hyphens)
|
||||
8. **Include NOTES.txt** with usage instructions
|
||||
9. **Add labels** consistently using helpers
|
||||
10. **Test installations** in all environments
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Template rendering errors:**
|
||||
```bash
|
||||
helm template my-app ./my-app --debug
|
||||
```
|
||||
|
||||
**Dependency issues:**
|
||||
```bash
|
||||
helm dependency update
|
||||
helm dependency list
|
||||
```
|
||||
|
||||
**Installation failures:**
|
||||
```bash
|
||||
helm install my-app ./my-app --dry-run --debug
|
||||
kubectl get events --sort-by='.lastTimestamp'
|
||||
```
|
||||
|
||||
## Reference Files
|
||||
|
||||
- `assets/Chart.yaml.template` - Chart metadata template
|
||||
- `assets/values.yaml.template` - Values structure template
|
||||
- `scripts/validate-chart.sh` - Validation script
|
||||
- `references/chart-structure.md` - Detailed chart organization
|
||||
|
||||
## Related Skills
|
||||
|
||||
- `k8s-manifest-generator` - For creating base Kubernetes manifests
|
||||
- `gitops-workflow` - For automated Helm chart deployments
|
||||
42
skills/helm-chart-scaffolding/assets/Chart.yaml.template
Normal file
42
skills/helm-chart-scaffolding/assets/Chart.yaml.template
Normal file
@@ -0,0 +1,42 @@
|
||||
apiVersion: v2
|
||||
name: <chart-name>
|
||||
description: <Chart description>
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "1.0.0"
|
||||
|
||||
keywords:
|
||||
- <keyword1>
|
||||
- <keyword2>
|
||||
|
||||
home: https://github.com/<org>/<repo>
|
||||
|
||||
sources:
|
||||
- https://github.com/<org>/<repo>
|
||||
|
||||
maintainers:
|
||||
- name: <Maintainer Name>
|
||||
email: <maintainer@example.com>
|
||||
url: https://github.com/<username>
|
||||
|
||||
icon: https://example.com/icon.png
|
||||
|
||||
kubeVersion: ">=1.24.0"
|
||||
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled
|
||||
tags:
|
||||
- database
|
||||
- name: redis
|
||||
version: "17.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: redis.enabled
|
||||
tags:
|
||||
- cache
|
||||
|
||||
annotations:
|
||||
category: Application
|
||||
licenses: Apache-2.0
|
||||
185
skills/helm-chart-scaffolding/assets/values.yaml.template
Normal file
185
skills/helm-chart-scaffolding/assets/values.yaml.template
Normal file
@@ -0,0 +1,185 @@
|
||||
# Global values shared with subcharts
|
||||
global:
|
||||
imageRegistry: docker.io
|
||||
imagePullSecrets: []
|
||||
storageClass: ""
|
||||
|
||||
# Image configuration
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: myapp/web
|
||||
tag: "" # Defaults to .Chart.AppVersion
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Override chart name
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
# Number of replicas
|
||||
replicaCount: 3
|
||||
revisionHistoryLimit: 10
|
||||
|
||||
# ServiceAccount
|
||||
serviceAccount:
|
||||
create: true
|
||||
annotations: {}
|
||||
name: ""
|
||||
|
||||
# Pod annotations
|
||||
podAnnotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
|
||||
# Pod security context
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
# Container security context
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
|
||||
# Service configuration
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: http
|
||||
annotations: {}
|
||||
sessionAffinity: None
|
||||
|
||||
# Ingress configuration
|
||||
ingress:
|
||||
enabled: false
|
||||
className: nginx
|
||||
annotations: {}
|
||||
hosts:
|
||||
- host: app.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
tls: []
|
||||
|
||||
# Resources
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 256Mi
|
||||
|
||||
# Liveness probe
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health/live
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
|
||||
# Readiness probe
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
|
||||
# Autoscaling
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
targetMemoryUtilizationPercentage: 80
|
||||
|
||||
# Pod Disruption Budget
|
||||
podDisruptionBudget:
|
||||
enabled: true
|
||||
minAvailable: 1
|
||||
|
||||
# Node selection
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- '{{ include "my-app.name" . }}'
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
# Environment variables
|
||||
env: []
|
||||
# - name: LOG_LEVEL
|
||||
# value: "info"
|
||||
|
||||
# ConfigMap data
|
||||
configMap:
|
||||
enabled: true
|
||||
data: {}
|
||||
# APP_MODE: production
|
||||
# DATABASE_HOST: postgres.example.com
|
||||
|
||||
# Secrets (use external secret management in production)
|
||||
secrets:
|
||||
enabled: false
|
||||
data: {}
|
||||
|
||||
# Persistent Volume
|
||||
persistence:
|
||||
enabled: false
|
||||
storageClass: ""
|
||||
accessMode: ReadWriteOnce
|
||||
size: 10Gi
|
||||
annotations: {}
|
||||
|
||||
# PostgreSQL dependency
|
||||
postgresql:
|
||||
enabled: false
|
||||
auth:
|
||||
database: myapp
|
||||
username: myapp
|
||||
password: changeme
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
|
||||
# Redis dependency
|
||||
redis:
|
||||
enabled: false
|
||||
auth:
|
||||
enabled: false
|
||||
master:
|
||||
persistence:
|
||||
enabled: false
|
||||
|
||||
# ServiceMonitor for Prometheus Operator
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
interval: 30s
|
||||
scrapeTimeout: 10s
|
||||
labels: {}
|
||||
|
||||
# Network Policy
|
||||
networkPolicy:
|
||||
enabled: false
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress: []
|
||||
egress: []
|
||||
500
skills/helm-chart-scaffolding/references/chart-structure.md
Normal file
500
skills/helm-chart-scaffolding/references/chart-structure.md
Normal file
@@ -0,0 +1,500 @@
|
||||
# Helm Chart Structure Reference
|
||||
|
||||
Complete guide to Helm chart organization, file conventions, and best practices.
|
||||
|
||||
## Standard Chart Directory Structure
|
||||
|
||||
```
|
||||
my-app/
|
||||
├── Chart.yaml # Chart metadata (required)
|
||||
├── Chart.lock # Dependency lock file (generated)
|
||||
├── values.yaml # Default configuration values (required)
|
||||
├── values.schema.json # JSON schema for values validation
|
||||
├── .helmignore # Patterns to ignore when packaging
|
||||
├── README.md # Chart documentation
|
||||
├── LICENSE # Chart license
|
||||
├── charts/ # Chart dependencies (bundled)
|
||||
│ └── postgresql-12.0.0.tgz
|
||||
├── crds/ # Custom Resource Definitions
|
||||
│ └── my-crd.yaml
|
||||
├── templates/ # Kubernetes manifest templates (required)
|
||||
│ ├── NOTES.txt # Post-install instructions
|
||||
│ ├── _helpers.tpl # Template helper functions
|
||||
│ ├── deployment.yaml
|
||||
│ ├── service.yaml
|
||||
│ ├── ingress.yaml
|
||||
│ ├── configmap.yaml
|
||||
│ ├── secret.yaml
|
||||
│ ├── serviceaccount.yaml
|
||||
│ ├── hpa.yaml
|
||||
│ ├── pdb.yaml
|
||||
│ ├── networkpolicy.yaml
|
||||
│ └── tests/
|
||||
│ └── test-connection.yaml
|
||||
└── files/ # Additional files to include
|
||||
└── config/
|
||||
└── app.conf
|
||||
```
|
||||
|
||||
## Chart.yaml Specification
|
||||
|
||||
### API Version v2 (Helm 3+)
|
||||
|
||||
```yaml
|
||||
apiVersion: v2 # Required: API version
|
||||
name: my-application # Required: Chart name
|
||||
version: 1.2.3 # Required: Chart version (SemVer)
|
||||
appVersion: "2.5.0" # Application version
|
||||
description: A Helm chart for my application # Required
|
||||
type: application # Chart type: application or library
|
||||
keywords: # Search keywords
|
||||
- web
|
||||
- api
|
||||
- backend
|
||||
home: https://example.com # Project home page
|
||||
sources: # Source code URLs
|
||||
- https://github.com/example/my-app
|
||||
maintainers: # Maintainer list
|
||||
- name: John Doe
|
||||
email: john@example.com
|
||||
url: https://github.com/johndoe
|
||||
icon: https://example.com/icon.png # Chart icon URL
|
||||
kubeVersion: ">=1.24.0" # Compatible Kubernetes versions
|
||||
deprecated: false # Mark chart as deprecated
|
||||
annotations: # Arbitrary annotations
|
||||
example.com/release-notes: https://example.com/releases/v1.2.3
|
||||
dependencies: # Chart dependencies
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled
|
||||
tags:
|
||||
- database
|
||||
import-values:
|
||||
- child: database
|
||||
parent: database
|
||||
alias: db
|
||||
```
|
||||
|
||||
## Chart Types
|
||||
|
||||
### Application Chart
|
||||
```yaml
|
||||
type: application
|
||||
```
|
||||
- Standard Kubernetes applications
|
||||
- Can be installed and managed
|
||||
- Contains templates for K8s resources
|
||||
|
||||
### Library Chart
|
||||
```yaml
|
||||
type: library
|
||||
```
|
||||
- Shared template helpers
|
||||
- Cannot be installed directly
|
||||
- Used as dependency by other charts
|
||||
- No templates/ directory
|
||||
|
||||
## Values Files Organization
|
||||
|
||||
### values.yaml (defaults)
|
||||
```yaml
|
||||
# Global values (shared with subcharts)
|
||||
global:
|
||||
imageRegistry: docker.io
|
||||
imagePullSecrets: []
|
||||
|
||||
# Image configuration
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: myapp/web
|
||||
tag: "" # Defaults to .Chart.AppVersion
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Deployment settings
|
||||
replicaCount: 1
|
||||
revisionHistoryLimit: 10
|
||||
|
||||
# Pod configuration
|
||||
podAnnotations: {}
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
|
||||
# Container security
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
|
||||
# Service
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: http
|
||||
annotations: {}
|
||||
|
||||
# Resources
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
|
||||
# Autoscaling
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
# Node selection
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
|
||||
# Monitoring
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
interval: 30s
|
||||
```
|
||||
|
||||
### values.schema.json (validation)
|
||||
```json
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"replicaCount": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"required": ["repository"],
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"pullPolicy": {
|
||||
"type": "string",
|
||||
"enum": ["Always", "IfNotPresent", "Never"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["image"]
|
||||
}
|
||||
```
|
||||
|
||||
## Template Files
|
||||
|
||||
### Template Naming Conventions
|
||||
|
||||
- **Lowercase with hyphens**: `deployment.yaml`, `service-account.yaml`
|
||||
- **Partial templates**: Prefix with underscore `_helpers.tpl`
|
||||
- **Tests**: Place in `templates/tests/`
|
||||
- **CRDs**: Place in `crds/` (not templated)
|
||||
|
||||
### Common Templates
|
||||
|
||||
#### _helpers.tpl
|
||||
```yaml
|
||||
{{/*
|
||||
Standard naming helpers
|
||||
*/}}
|
||||
{{- define "my-app.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- 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 -}}
|
||||
|
||||
{{- define "my-app.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- 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 -}}
|
||||
|
||||
{{- define "my-app.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "my-app.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Image name helper
|
||||
*/}}
|
||||
{{- define "my-app.image" -}}
|
||||
{{- $registry := .Values.global.imageRegistry | default .Values.image.registry -}}
|
||||
{{- $repository := .Values.image.repository -}}
|
||||
{{- $tag := .Values.image.tag | default .Chart.AppVersion -}}
|
||||
{{- printf "%s/%s:%s" $registry $repository $tag -}}
|
||||
{{- end -}}
|
||||
```
|
||||
|
||||
#### NOTES.txt
|
||||
```
|
||||
Thank you for installing {{ .Chart.Name }}.
|
||||
|
||||
Your release is named {{ .Release.Name }}.
|
||||
|
||||
To learn more about the release, try:
|
||||
|
||||
$ helm status {{ .Release.Name }}
|
||||
$ helm get all {{ .Release.Name }}
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
|
||||
Application URL:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
|
||||
Get the application URL by running:
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "my-app.name" . }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
kubectl port-forward $POD_NAME 8080:80
|
||||
echo "Visit http://127.0.0.1:8080"
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
## Dependencies Management
|
||||
|
||||
### Declaring Dependencies
|
||||
|
||||
```yaml
|
||||
# Chart.yaml
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled # Enable/disable via values
|
||||
tags: # Group dependencies
|
||||
- database
|
||||
import-values: # Import values from subchart
|
||||
- child: database
|
||||
parent: database
|
||||
alias: db # Reference as .Values.db
|
||||
```
|
||||
|
||||
### Managing Dependencies
|
||||
|
||||
```bash
|
||||
# Update dependencies
|
||||
helm dependency update
|
||||
|
||||
# List dependencies
|
||||
helm dependency list
|
||||
|
||||
# Build dependencies
|
||||
helm dependency build
|
||||
```
|
||||
|
||||
### Chart.lock
|
||||
|
||||
Generated automatically by `helm dependency update`:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 12.0.0
|
||||
digest: sha256:abcd1234...
|
||||
generated: "2024-01-01T00:00:00Z"
|
||||
```
|
||||
|
||||
## .helmignore
|
||||
|
||||
Exclude files from chart package:
|
||||
|
||||
```
|
||||
# Development files
|
||||
.git/
|
||||
.gitignore
|
||||
*.md
|
||||
docs/
|
||||
|
||||
# Build artifacts
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
|
||||
# CI/CD
|
||||
.travis.yml
|
||||
.gitlab-ci.yml
|
||||
Jenkinsfile
|
||||
|
||||
# Testing
|
||||
test/
|
||||
*.test
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.iml
|
||||
```
|
||||
|
||||
## Custom Resource Definitions (CRDs)
|
||||
|
||||
Place CRDs in `crds/` directory:
|
||||
|
||||
```
|
||||
crds/
|
||||
├── my-app-crd.yaml
|
||||
└── another-crd.yaml
|
||||
```
|
||||
|
||||
**Important CRD notes:**
|
||||
- CRDs are installed before any templates
|
||||
- CRDs are NOT templated (no `{{ }}` syntax)
|
||||
- CRDs are NOT upgraded or deleted with chart
|
||||
- Use `helm install --skip-crds` to skip installation
|
||||
|
||||
## Chart Versioning
|
||||
|
||||
### Semantic Versioning
|
||||
|
||||
- **Chart Version**: Increment when chart changes
|
||||
- MAJOR: Breaking changes
|
||||
- MINOR: New features, backward compatible
|
||||
- PATCH: Bug fixes
|
||||
|
||||
- **App Version**: Application version being deployed
|
||||
- Can be any string
|
||||
- Not required to follow SemVer
|
||||
|
||||
```yaml
|
||||
version: 2.3.1 # Chart version
|
||||
appVersion: "1.5.0" # Application version
|
||||
```
|
||||
|
||||
## Chart Testing
|
||||
|
||||
### Test Files
|
||||
|
||||
```yaml
|
||||
# templates/tests/test-connection.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "my-app.fullname" . }}-test-connection"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
helm test my-release
|
||||
helm test my-release --logs
|
||||
```
|
||||
|
||||
## Hooks
|
||||
|
||||
Helm hooks allow intervention at specific points:
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ include "my-app.fullname" . }}-migration
|
||||
annotations:
|
||||
"helm.sh/hook": pre-upgrade,pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
```
|
||||
|
||||
### Hook Types
|
||||
|
||||
- `pre-install`: Before templates rendered
|
||||
- `post-install`: After all resources loaded
|
||||
- `pre-delete`: Before any resources deleted
|
||||
- `post-delete`: After all resources deleted
|
||||
- `pre-upgrade`: Before upgrade
|
||||
- `post-upgrade`: After upgrade
|
||||
- `pre-rollback`: Before rollback
|
||||
- `post-rollback`: After rollback
|
||||
- `test`: Run with `helm test`
|
||||
|
||||
### Hook Weight
|
||||
|
||||
Controls hook execution order (-5 to 5, lower runs first)
|
||||
|
||||
### Hook Deletion Policies
|
||||
|
||||
- `before-hook-creation`: Delete previous hook before new one
|
||||
- `hook-succeeded`: Delete after successful execution
|
||||
- `hook-failed`: Delete if hook fails
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use helpers** for repeated template logic
|
||||
2. **Quote strings** in templates: `{{ .Values.name | quote }}`
|
||||
3. **Validate values** with values.schema.json
|
||||
4. **Document all values** in values.yaml
|
||||
5. **Use semantic versioning** for chart versions
|
||||
6. **Pin dependency versions** exactly
|
||||
7. **Include NOTES.txt** with usage instructions
|
||||
8. **Add tests** for critical functionality
|
||||
9. **Use hooks** for database migrations
|
||||
10. **Keep charts focused** - one application per chart
|
||||
|
||||
## Chart Repository Structure
|
||||
|
||||
```
|
||||
helm-charts/
|
||||
├── index.yaml
|
||||
├── my-app-1.0.0.tgz
|
||||
├── my-app-1.1.0.tgz
|
||||
├── my-app-1.2.0.tgz
|
||||
└── another-chart-2.0.0.tgz
|
||||
```
|
||||
|
||||
### Creating Repository Index
|
||||
|
||||
```bash
|
||||
helm repo index . --url https://charts.example.com
|
||||
```
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [Helm Documentation](https://helm.sh/docs/)
|
||||
- [Chart Template Guide](https://helm.sh/docs/chart_template_guide/)
|
||||
- [Best Practices](https://helm.sh/docs/chart_best_practices/)
|
||||
244
skills/helm-chart-scaffolding/scripts/validate-chart.sh
Normal file
244
skills/helm-chart-scaffolding/scripts/validate-chart.sh
Normal file
@@ -0,0 +1,244 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CHART_DIR="${1:-.}"
|
||||
RELEASE_NAME="test-release"
|
||||
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Helm Chart Validation"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
success() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
}
|
||||
|
||||
warning() {
|
||||
echo -e "${YELLOW}⚠${NC} $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
}
|
||||
|
||||
# Check if Helm is installed
|
||||
if ! command -v helm &> /dev/null; then
|
||||
error "Helm is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Chart directory: $CHART_DIR"
|
||||
echo ""
|
||||
|
||||
# 1. Check chart structure
|
||||
echo "1️⃣ Checking chart structure..."
|
||||
if [ ! -f "$CHART_DIR/Chart.yaml" ]; then
|
||||
error "Chart.yaml not found"
|
||||
exit 1
|
||||
fi
|
||||
success "Chart.yaml exists"
|
||||
|
||||
if [ ! -f "$CHART_DIR/values.yaml" ]; then
|
||||
error "values.yaml not found"
|
||||
exit 1
|
||||
fi
|
||||
success "values.yaml exists"
|
||||
|
||||
if [ ! -d "$CHART_DIR/templates" ]; then
|
||||
error "templates/ directory not found"
|
||||
exit 1
|
||||
fi
|
||||
success "templates/ directory exists"
|
||||
echo ""
|
||||
|
||||
# 2. Lint the chart
|
||||
echo "2️⃣ Linting chart..."
|
||||
if helm lint "$CHART_DIR"; then
|
||||
success "Chart passed lint"
|
||||
else
|
||||
error "Chart failed lint"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 3. Check Chart.yaml
|
||||
echo "3️⃣ Validating Chart.yaml..."
|
||||
CHART_NAME=$(grep "^name:" "$CHART_DIR/Chart.yaml" | awk '{print $2}')
|
||||
CHART_VERSION=$(grep "^version:" "$CHART_DIR/Chart.yaml" | awk '{print $2}')
|
||||
APP_VERSION=$(grep "^appVersion:" "$CHART_DIR/Chart.yaml" | awk '{print $2}' | tr -d '"')
|
||||
|
||||
if [ -z "$CHART_NAME" ]; then
|
||||
error "Chart name not found"
|
||||
exit 1
|
||||
fi
|
||||
success "Chart name: $CHART_NAME"
|
||||
|
||||
if [ -z "$CHART_VERSION" ]; then
|
||||
error "Chart version not found"
|
||||
exit 1
|
||||
fi
|
||||
success "Chart version: $CHART_VERSION"
|
||||
|
||||
if [ -z "$APP_VERSION" ]; then
|
||||
warning "App version not specified"
|
||||
else
|
||||
success "App version: $APP_VERSION"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 4. Test template rendering
|
||||
echo "4️⃣ Testing template rendering..."
|
||||
if helm template "$RELEASE_NAME" "$CHART_DIR" > /dev/null 2>&1; then
|
||||
success "Templates rendered successfully"
|
||||
else
|
||||
error "Template rendering failed"
|
||||
helm template "$RELEASE_NAME" "$CHART_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 5. Dry-run installation
|
||||
echo "5️⃣ Testing dry-run installation..."
|
||||
if helm install "$RELEASE_NAME" "$CHART_DIR" --dry-run --debug > /dev/null 2>&1; then
|
||||
success "Dry-run installation successful"
|
||||
else
|
||||
error "Dry-run installation failed"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 6. Check for required Kubernetes resources
|
||||
echo "6️⃣ Checking generated resources..."
|
||||
MANIFESTS=$(helm template "$RELEASE_NAME" "$CHART_DIR")
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "kind: Deployment"; then
|
||||
success "Deployment found"
|
||||
else
|
||||
warning "No Deployment found"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "kind: Service"; then
|
||||
success "Service found"
|
||||
else
|
||||
warning "No Service found"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "kind: ServiceAccount"; then
|
||||
success "ServiceAccount found"
|
||||
else
|
||||
warning "No ServiceAccount found"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 7. Check for security best practices
|
||||
echo "7️⃣ Checking security best practices..."
|
||||
if echo "$MANIFESTS" | grep -q "runAsNonRoot: true"; then
|
||||
success "Running as non-root user"
|
||||
else
|
||||
warning "Not explicitly running as non-root"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "readOnlyRootFilesystem: true"; then
|
||||
success "Using read-only root filesystem"
|
||||
else
|
||||
warning "Not using read-only root filesystem"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "allowPrivilegeEscalation: false"; then
|
||||
success "Privilege escalation disabled"
|
||||
else
|
||||
warning "Privilege escalation not explicitly disabled"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 8. Check for resource limits
|
||||
echo "8️⃣ Checking resource configuration..."
|
||||
if echo "$MANIFESTS" | grep -q "resources:"; then
|
||||
if echo "$MANIFESTS" | grep -q "limits:"; then
|
||||
success "Resource limits defined"
|
||||
else
|
||||
warning "No resource limits defined"
|
||||
fi
|
||||
if echo "$MANIFESTS" | grep -q "requests:"; then
|
||||
success "Resource requests defined"
|
||||
else
|
||||
warning "No resource requests defined"
|
||||
fi
|
||||
else
|
||||
warning "No resources defined"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 9. Check for health probes
|
||||
echo "9️⃣ Checking health probes..."
|
||||
if echo "$MANIFESTS" | grep -q "livenessProbe:"; then
|
||||
success "Liveness probe configured"
|
||||
else
|
||||
warning "No liveness probe found"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "readinessProbe:"; then
|
||||
success "Readiness probe configured"
|
||||
else
|
||||
warning "No readiness probe found"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 10. Check dependencies
|
||||
if [ -f "$CHART_DIR/Chart.yaml" ] && grep -q "^dependencies:" "$CHART_DIR/Chart.yaml"; then
|
||||
echo "🔟 Checking dependencies..."
|
||||
if helm dependency list "$CHART_DIR" > /dev/null 2>&1; then
|
||||
success "Dependencies valid"
|
||||
|
||||
if [ -f "$CHART_DIR/Chart.lock" ]; then
|
||||
success "Chart.lock file present"
|
||||
else
|
||||
warning "Chart.lock file missing (run 'helm dependency update')"
|
||||
fi
|
||||
else
|
||||
error "Dependencies check failed"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 11. Check for values schema
|
||||
if [ -f "$CHART_DIR/values.schema.json" ]; then
|
||||
echo "1️⃣1️⃣ Validating values schema..."
|
||||
success "values.schema.json present"
|
||||
|
||||
# Validate schema if jq is available
|
||||
if command -v jq &> /dev/null; then
|
||||
if jq empty "$CHART_DIR/values.schema.json" 2>/dev/null; then
|
||||
success "values.schema.json is valid JSON"
|
||||
else
|
||||
error "values.schema.json contains invalid JSON"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Validation Complete!"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Chart: $CHART_NAME"
|
||||
echo "Version: $CHART_VERSION"
|
||||
if [ -n "$APP_VERSION" ]; then
|
||||
echo "App Version: $APP_VERSION"
|
||||
fi
|
||||
echo ""
|
||||
success "All validations passed!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " • helm package $CHART_DIR"
|
||||
echo " • helm install my-release $CHART_DIR"
|
||||
echo " • helm test my-release"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user