Related Fundamentals: Understand the orchestration context by reviewing Kubernetes Manifests and Deployments and Container Orchestration - Kubernetes.
CleanStart provides auto-generated Helm charts pre-configured with security best practices: non-root user (UID 65532), dropped Linux capabilities, read-only root filesystem, and network policies. These charts are Bitnami-compatible drop-in replacements—deploy CleanStart images in place of Bitnami with a 30-second values change.
Installing CleanStart Helm Charts
1. Add Helm Repository
# Add CleanStart Helm repositoryhelm repo add cleanstart https://helm.cleanstart.dev/chartshelm repo update # List available chartshelm repo search cleanstart# Output:# NAME CHART VERSION APP VERSION DESCRIPTION# cleanstart/apache 13.0.0 2.4.57 Apache HTTP server# cleanstart/nginx 14.1.0 1.25.0 NGINX web server# cleanstart/postgresql 14.0.0 15.2 PostgreSQL database# cleanstart/redis 17.1.0 7.0.8 Redis in-memory data store# cleanstart/mysql 9.3.0 8.0.32 MySQL database# cleanstart/mongodb 13.0.0 6.0.0 MongoDB NoSQL database# cleanstart/kafka 20.0.0 3.3.1 Apache Kafka message broker2. Install Chart with Default Values
# Install with defaults (single replica, no persistence)helm install my-app cleanstart/nginx \ --namespace default \ --create-namespace # Install with custom release namehelm install my-release-name cleanstart/postgresql \ --namespace database # Verify installationhelm list -n databasekubectl get pods -n databaseSecurity Defaults in CleanStart Charts
Every CleanStart Helm chart includes:
# Non-root usersecurityContext: runAsNonRoot: true runAsUser: 65532 # appuser runAsGroup: 65532 fsGroup: 65532 capabilities: drop: - ALL # Drop all Linux capabilities readOnlyRootFilesystem: true allowPrivilegeEscalation: false # Resource limitsresources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m" # Network policiesnetworkPolicy: enabled: true ingress: - from: - podSelector: matchLabels: app: frontendBitnami Drop-In Replacement
Side-by-Side Comparison
Aspect | Bitnami | CleanStart |
|---|---|---|
Base OS | Debian | Alpine |
Image Size | 200-400MB | 40-80MB |
Security Context | UID 1001 | UID 65532 (non-root) |
Capabilities | Many allowed | All dropped |
Read-only filesystem | Optional | Default |
FIPS compliance | No | Yes |
Scanning | Annual | Real-time |
Switching from Bitnami to CleanStart
Before (Bitnami):
helm install my-postgres bitnami/postgresql \ --set auth.password=mypassword \ --set persistence.size=10GiAfter (CleanStart):
helm install my-postgres cleanstart/postgresql \ --set auth.password=mypassword \ --set persistence.size=10GiThat's it! The interface is identical. The only difference is the security posture and image size.
Custom Deployment: PostgreSQL Example
Create values-prod.yaml:
# Image configurationimage: repository: us-docker.pkg.dev/my-project/prod/postgresql tag: 15.2-prod-signed pullPolicy: IfNotPresent # Pod count and strategyreplicaCount: 2strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 # Storage (persistent volume)persistence: enabled: true size: 50Gi storageClassName: gce-ssd annotations: snapshot.storage.kubernetes.io/allow-volume-clone: "true" # Database initializationauth: username: postgres password: "$(POSTGRES_PASSWORD)" # From secret database: myapp_db postgresPassword: "$(POSTGRES_ROOT_PASSWORD)" # Primary node configurationprimary: resources: requests: memory: "2Gi" cpu: "1000m" limits: memory: "4Gi" cpu: "2000m" # Liveliness and readiness probes livenessProbe: enabled: true initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: enabled: true initialDelaySeconds: 10 periodSeconds: 5 # Replication (hot standby)readReplicas: enabled: true replicaCount: 1 resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "2Gi" cpu: "1000m" # Backup and WAL archivingbackup: enabled: true schedule: "0 2 * * *" # 2 AM daily destinationBucket: gs://my-backup-bucket retentionDays: 30 # Monitoring and alertsmonitoring: enabled: true prometheus: enabled: true serviceMonitor: enabled: true interval: 30s # Network policiesnetworkPolicy: enabled: true ingress: - from: - namespaceSelector: matchLabels: app: myapp ports: - protocol: TCP port: 5432 # Pod disruption budgetpodDisruptionBudget: enabled: true minAvailable: 1 # Security context (already defaults to secure settings)securityContext: runAsNonRoot: true runAsUser: 65532 capabilities: drop: - ALL readOnlyRootFilesystem: trueDeploy with custom values:
# Install with production valueshelm install my-postgres cleanstart/postgresql \ --namespace database \ --create-namespace \ -f values-prod.yaml # Verify installationhelm status my-postgres -n databasekubectl get pods -n databasekubectl describe pod -n database -l app=postgresqlStatefulSet Configuration for Stateful Apps
CleanStart automatically uses StatefulSets for stateful applications:
# PostgreSQL (StatefulSet by default)helm install postgres cleanstart/postgresql -n database # Redis (StatefulSet with replicas for Sentinel)helm install redis cleanstart/redis \ -n cache \ --set replica.replicaCount=2 # Kafka (StatefulSet for broker scaling)helm install kafka cleanstart/kafka \ -n messaging \ --set broker.replicaCount=3Verify StatefulSet deployment:
kubectl get statefulset -n database# Output:# NAME READY AGE# my-postgres-postgresql 2/2 2m kubectl get pods -n database -o wide# Output:# NAME READY STATUS RESTARTS AGE IP# my-postgres-postgresql-0 1/1 Running 0 2m 10.0.0.5# my-postgres-postgresql-1 1/1 Running 0 2m 10.0.0.6Deployment Examples
Example 1: NGINX with CleanStart
# Create namespacekubectl create namespace web # Install NGINXhelm install web-server cleanstart/nginx \ --namespace web \ --set service.type=LoadBalancer \ --set service.loadBalancerSourceRanges='{10.0.0.0/8,172.16.0.0/12}' # Verifykubectl get svc -n web# Output: LoadBalancer IP address # Access applicationcurl http://LOAD_BALANCER_IPExample 2: PostgreSQL with High Availability
# values-ha.yamlprimary: replicaCount: 1 persistence: size: 100Gi storageClassName: fast-ssd readReplicas: enabled: true replicaCount: 3 # 3 read replicas backup: enabled: true schedule: "0 */4 * * *" # Every 4 hours destinationBucket: gs://pg-backups monitoring: enabled: true prometheus: enabled: truehelm install postgres cleanstart/postgresql \ -n database \ -f values-ha.yamlExample 3: Redis Cluster with Sentinel
# values-redis-sentinel.yamlmode: sentinel # or standalone, master-replica sentinel: enabled: true replicas: 3 quorum: 2 replica: replicaCount: 2 persistence: size: 50Gi monitoring: enabled: truehelm install redis-sentinel cleanstart/redis \ -n cache \ -f values-redis-sentinel.yamlLiveness and Readiness Probes
CleanStart charts include pre-configured probes:
# Automatic probe configuration by service typelivenessProbe: httpGet: path: /health port: http initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 1Test probes:
# Check probe statuskubectl describe pod POD_NAME -n NAMESPACE | grep -A 5 "Liveness\|Readiness" # Manually test endpointkubectl port-forward POD_NAME 8080:8080 -n NAMESPACEcurl http://localhost:8080/healthcurl http://localhost:8080/readySignal Forwarding and Graceful Shutdown
CleanStart Helm charts handle SIGTERM properly for graceful shutdown:
# In chart templatelifecycle: preStop: exec: command: ["/bin/sh", "-c", "sleep 15"] terminationGracePeriodSeconds: 30This ensures:
- Pod receives SIGTERM
- Application drains connections (15 second pause)
- Pod terminates cleanly after 30 seconds max
Verify graceful shutdown:
# Delete pod and observe logskubectl delete pod POD_NAME -n NAMESPACEkubectl logs POD_NAME -n NAMESPACE --timestamps=true | tail -20# You should see "Shutting down gracefully..."ConfigMap and Secret Integration
Using ConfigMaps for Configuration
apiVersion: v1kind: ConfigMapmetadata: name: app-config namespace: defaultdata: app.conf: | server.port: 8080 database.pool_size: 20 logging.level: info# Deploy ConfigMapkubectl apply -f configmap.yaml # Reference in Helm valueshelm install my-app cleanstart/myapp \ --set-file config.file=./app.conf # Or create from ConfigMapkubectl create configmap app-config --from-file=app.conf helm install my-app cleanstart/myapp \ --set config.existingConfigMap=app-configUsing Secrets for Sensitive Data
# Create secret from CLIkubectl create secret generic db-credentials \ --from-literal=username=postgres \ --from-literal=password=ACTUAL_PASSWORD \ -n database # Reference in Helm valueshelm install postgres cleanstart/postgresql \ --set auth.existingSecret=db-credentials \ --set auth.secretKeys.adminPasswordKey=passwordUpgrades and Rollbacks
# Check current versionhelm list -n database # Upgrade to new versionhelm upgrade my-postgres cleanstart/postgresql \ -n database \ --values values-prod.yaml \ --wait # Monitor upgrade progresskubectl rollout status statefulset/my-postgres-postgresql -n database # Rollback to previous versionhelm rollback my-postgres -n database # Get release historyhelm history my-postgres -n databaseTroubleshooting
Pod Not Starting
# Check pod eventskubectl describe pod POD_NAME -n NAMESPACE # Check logskubectl logs POD_NAME -n NAMESPACEkubectl logs POD_NAME -n NAMESPACE --previous # If crashed # Check resource availabilitykubectl describe nodeReadiness Probe Failing
# Manual endpoint testkubectl exec POD_NAME -n NAMESPACE -- \ curl -v http://localhost:8080/ready # Check probe configurationkubectl get pod POD_NAME -n NAMESPACE -o yaml | \ grep -A 10 readinessProbeStorage Issues
# Check PVC statuskubectl get pvc -n NAMESPACE # Describe PVCkubectl describe pvc CLAIM_NAME -n NAMESPACE # Check storage classkubectl get storageclasskubectl describe storageclass STORAGE_CLASS_NAMENetwork Policy Blocking Traffic
# Test connectivitykubectl exec SOURCE_POD -n NAMESPACE -- \ curl -v http://DEST_POD:PORT # Review network policieskubectl get networkpolicy -n NAMESPACEkubectl describe networkpolicy POLICY_NAME -n NAMESPACEPerformance Tuning
# values-performance.yamlresources: requests: memory: "4Gi" cpu: "2000m" limits: memory: "8Gi" cpu: "4000m" # Use fast storagepersistence: storageClassName: fast-ssd # or nvme # Enable caching layerscache: enabled: true size: 2GiMonitoring Integration
All CleanStart Helm charts integrate with Prometheus:
# Enable monitoringhelm install my-app cleanstart/nginx \ --set monitoring.enabled=true \ --set monitoring.prometheus.enabled=true # Access metricskubectl port-forward svc/my-app-metrics 9090:9090curl http://localhost:9090/metricsAI/ML Workload Deployment with Helm
For deploying AI and machine learning workloads to Kubernetes with GPU support, resource allocation, and specialized model serving patterns, see AI Container Helm Deployments. For detailed Bitnami Helm chart value references and configuration options, see Helm Chart Reference.
Uninstalling Charts
# Uninstall releasehelm uninstall my-app -n NAMESPACE # Uninstall and keep release history for rollbackhelm uninstall my-app -n NAMESPACE --keep-history # Clean up PVCs (important for stateful apps)kubectl delete pvc -l release=my-app -n NAMESPACE