Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 147 additions & 1 deletion components/skills/k8s-helm-charts-dev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,95 @@ Use this skill when you need to:
- Set up Helm chart repositories
- Follow Helm best practices and conventions

## Chart Complexity Classification

Before starting, classify your chart to determine the appropriate approach:

| Level | Characteristics | CI Handling | Example |
|-------|-----------------|-------------|---------|
| **Simple** | Single container, no external deps, standard probes | Full lint + install | Static site, simple API |
| **Standard** | Multiple resources, ConfigMaps/Secrets, optional deps | Full lint + install | Web app with ingress |
| **Complex** | External services required, multi-port, JVM config | Lint only, skip install | OpenMetadata, data platforms |
| **Operator** | CRDs, webhooks, cluster-wide resources | Lint only, manual test | Prometheus Operator |

**Quick Decision:**
- Needs database/search/messaging at runtime? → **Complex** (exclude from install tests)
- Has admin port separate from main port? → Check `assets/patterns/multi-port-service.yaml`
- JVM application? → Check `assets/patterns/jvm-application.yaml`

> **Details**: See `references/chart-complexity.md` for full classification guide and CI configuration.

## Research Strategy

Before creating a chart, research the application:

1. **Check for official chart** - Many projects maintain their own Helm charts
2. **Review Docker documentation** - Container entrypoint, environment variables, ports
3. **Identify external dependencies** - What services does the app need?

**If documentation scraping fails**, use alternative methods:
- Search GitHub for existing implementations
- Check Docker Hub for environment variable documentation
- Review Kubernetes deployment examples in project repos

> **Details**: See `references/research-strategy.md` for complete fallback strategies and information gathering checklist.

## Structured Development Workflow

For complex charts or when contributing to existing projects, use a structured approach:

### Workflow Selection

| Chart Complexity | Official Chart Exists | Workflow |
|------------------|----------------------|----------|
| Simple/Standard | No | **Fast Path** - Quick research, create, validate |
| Simple/Standard | Yes (use as-is) | **Skip** - Use existing chart |
| Complex/Operator | No | **Full Workflow** - Research → Plan → Implement |
| Any | Yes (extend) | **Full Workflow** with contribution strategy |

### Research Phase

Systematically investigate the application before creating templates:
1. Check for existing charts (official, community)
2. Gather configuration details (image, ports, env vars)
3. Document findings in structured format
4. Get approval for complex applications

> **Details**: See `references/research-phase-workflow.md`

### Planning Phase

Translate research into actionable implementation plan:
1. Create high-level plan with target features
2. Break down into atomic components (phases)
3. Draft phase plans for each component
4. Get sequential approvals
5. Map plans to GitHub issues (optional)

> **Details**: See `references/planning-phase-workflow.md`

### Implementation Phase

Execute with quality gates and review checkpoints:
1. Create worktree and draft PR immediately
2. Implement following phase plan
3. Run sanity checks (lint, template, security)
4. Pause for external review when needed
5. Submit PR when complete, clean up worktree

> **Details**: See `references/implementation-workflow.md`

### Extending Existing Charts

When an official chart exists but needs improvements:
1. Decide: fork repo vs copy locally
2. Review upstream patterns and values schema
3. Maintain compatibility for contribution
4. Document differences and improvements
5. Prepare upstream contribution (PR or patch)

> **Details**: See `references/extend-contribute-strategy.md`

## Helm Overview

**Helm** is the package manager for Kubernetes that:
Expand Down Expand Up @@ -499,6 +588,37 @@ global:
image: {{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}
```

## Pattern Templates

Ready-to-use patterns for common scenarios. Copy values and template sections to your chart.

### External Services

| Pattern | Use When | File |
|---------|----------|------|
| Database | Chart connects to MySQL or PostgreSQL | `assets/patterns/external-database.yaml` |
| Search | Chart connects to Elasticsearch or OpenSearch | `assets/patterns/external-search.yaml` |
| Messaging | Chart connects to Airflow, Kafka, RabbitMQ, or Redis | `assets/patterns/external-messaging.yaml` |

All patterns include:
- Values structure with `existingSecret` support
- Helper template functions
- Environment variable configuration
- Example configurations

### Application Architecture

| Pattern | Use When | File |
|---------|----------|------|
| Multi-Port Service | App has main + admin/metrics ports | `assets/patterns/multi-port-service.yaml` |
| JVM Application | Java/Kotlin/Scala app needing heap/GC config | `assets/patterns/jvm-application.yaml` |
| Health Probes (Multi-Port) | Different probes on different ports | `assets/patterns/health-probes-multiport.yaml` |

### Quick Reference

For port numbers, environment variables, and connection strings:
- `references/external-services.md` - Common services reference table

## Best Practices

1. **Use semantic versioning** for chart and app versions
Expand Down Expand Up @@ -533,10 +653,36 @@ kubectl get events --sort-by='.lastTimestamp'

## Reference Files

### Chart Templates
- `assets/Chart.yaml.template` - Chart metadata template
- `assets/values.yaml.template` - Values structure template
- `scripts/validate-chart.sh` - Validation script

### Pattern Files
- `assets/patterns/external-database.yaml` - MySQL/PostgreSQL configuration
- `assets/patterns/external-search.yaml` - Elasticsearch/OpenSearch configuration
- `assets/patterns/external-messaging.yaml` - Airflow/Kafka/RabbitMQ/Redis configuration
- `assets/patterns/multi-port-service.yaml` - Multiple ports pattern
- `assets/patterns/jvm-application.yaml` - JVM heap/GC/JMX configuration
- `assets/patterns/health-probes-multiport.yaml` - Probes on different ports

### Workflow Templates
- `assets/templates/research-summary.md` - Research findings documentation
- `assets/templates/high-level-plan.md` - High-level chart plan
- `assets/templates/phase-plan.md` - Per-phase implementation plan
- `assets/templates/issue-structure.md` - GitHub issue hierarchy

### References
- `references/chart-structure.md` - Detailed chart organization
- `references/chart-complexity.md` - Chart complexity classification guide
- `references/research-strategy.md` - Documentation research and fallback strategies
- `references/external-services.md` - Common ports, env vars, connection strings
- `references/extend-contribute-strategy.md` - Extending and contributing to existing charts
- `references/research-phase-workflow.md` - Research phase structured workflow
- `references/planning-phase-workflow.md` - Planning phase structured workflow
- `references/implementation-workflow.md` - Implementation phase with checkpoints

### Scripts
- `scripts/validate-chart.sh` - Validation script

## Related Skills

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# =============================================================================
# External Database Configuration Pattern
# =============================================================================
# Use this pattern when chart connects to an EXISTING external database
# rather than deploying a database as a subchart dependency.
#
# Supports: MySQL, PostgreSQL, MariaDB
#
# Usage:
# 1. Copy the values section to your values.yaml
# 2. Copy the helper templates to your _helpers.tpl
# 3. Copy the environment variable section to your deployment.yaml
# =============================================================================

# -----------------------------------------------------------------------------
# VALUES.YAML SECTION
# -----------------------------------------------------------------------------
# Copy this to your values.yaml under a 'database:' key

database:
# -- Database type: mysql, postgres, or mariadb
type: mysql

# -- External database host (required)
host: ""

# -- Database port (3306 for MySQL/MariaDB, 5432 for PostgreSQL)
port: 3306

# -- Database name
name: "app_db"

# -- Database username
username: ""

# -- Database password (use existingSecret in production)
password: ""

# -- Use existing Kubernetes secret for database credentials
# If set, password field is ignored
existingSecret: ""

# -- Key in existing secret containing the password
existingSecretKey: "password"

# -- Additional JDBC connection parameters
# MySQL example: "useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"
# PostgreSQL example: "sslmode=require"
params: ""

# -- Connection pool settings (if supported by application)
pool:
# -- Minimum pool size
minSize: 5
# -- Maximum pool size
maxSize: 20
# -- Connection timeout in milliseconds
connectionTimeout: 30000

# -----------------------------------------------------------------------------
# HELPERS.TPL SECTION
# -----------------------------------------------------------------------------
# Copy these helper templates to your templates/_helpers.tpl

# {{/*
# Database JDBC URL
# */}}
# {{- define "<chart>.databaseUrl" -}}
# {{- $params := "" }}
# {{- if .Values.database.params }}
# {{- $params = printf "?%s" .Values.database.params }}
# {{- end }}
# {{- if eq .Values.database.type "mysql" }}
# {{- printf "jdbc:mysql://%s:%d/%s%s" .Values.database.host (int .Values.database.port) .Values.database.name $params }}
# {{- else if eq .Values.database.type "mariadb" }}
# {{- printf "jdbc:mariadb://%s:%d/%s%s" .Values.database.host (int .Values.database.port) .Values.database.name $params }}
# {{- else if eq .Values.database.type "postgres" }}
# {{- printf "jdbc:postgresql://%s:%d/%s%s" .Values.database.host (int .Values.database.port) .Values.database.name $params }}
# {{- end }}
# {{- end }}

# {{/*
# Database driver class name
# */}}
# {{- define "<chart>.databaseDriver" -}}
# {{- if eq .Values.database.type "mysql" }}
# {{- "com.mysql.cj.jdbc.Driver" }}
# {{- else if eq .Values.database.type "mariadb" }}
# {{- "org.mariadb.jdbc.Driver" }}
# {{- else if eq .Values.database.type "postgres" }}
# {{- "org.postgresql.Driver" }}
# {{- end }}
# {{- end }}

# {{/*
# Database dialect (for ORMs like Hibernate)
# */}}
# {{- define "<chart>.databaseDialect" -}}
# {{- if eq .Values.database.type "mysql" }}
# {{- "org.hibernate.dialect.MySQL8Dialect" }}
# {{- else if eq .Values.database.type "mariadb" }}
# {{- "org.hibernate.dialect.MariaDB103Dialect" }}
# {{- else if eq .Values.database.type "postgres" }}
# {{- "org.hibernate.dialect.PostgreSQL10Dialect" }}
# {{- end }}
# {{- end }}

# -----------------------------------------------------------------------------
# DEPLOYMENT.YAML ENVIRONMENT SECTION
# -----------------------------------------------------------------------------
# Copy this to your deployment.yaml container env section

# env:
# # Database connection details
# - name: DB_TYPE
# value: {{ .Values.database.type | quote }}
# - name: DB_HOST
# value: {{ .Values.database.host | quote }}
# - name: DB_PORT
# value: {{ .Values.database.port | quote }}
# - name: DB_NAME
# value: {{ .Values.database.name | quote }}
# - name: DB_USER
# value: {{ .Values.database.username | quote }}
# - name: DB_PASSWORD
# {{- if .Values.database.existingSecret }}
# valueFrom:
# secretKeyRef:
# name: {{ .Values.database.existingSecret }}
# key: {{ .Values.database.existingSecretKey }}
# {{- else }}
# value: {{ .Values.database.password | quote }}
# {{- end }}
# # Optional: JDBC URL (if application uses single URL)
# - name: DB_URL
# value: {{ include "<chart>.databaseUrl" . | quote }}
# - name: DB_DRIVER
# value: {{ include "<chart>.databaseDriver" . | quote }}

# -----------------------------------------------------------------------------
# ALTERNATIVE: DATABASE_URL STYLE (Node.js, Rails, etc.)
# -----------------------------------------------------------------------------
# Some applications prefer a single connection URL

# env:
# - name: DATABASE_URL
# {{- if .Values.database.existingSecret }}
# valueFrom:
# secretKeyRef:
# name: {{ .Values.database.existingSecret }}
# key: database-url
# {{- else }}
# {{- if eq .Values.database.type "postgres" }}
# value: "postgresql://{{ .Values.database.username }}:{{ .Values.database.password }}@{{ .Values.database.host }}:{{ .Values.database.port }}/{{ .Values.database.name }}"
# {{- else }}
# value: "mysql://{{ .Values.database.username }}:{{ .Values.database.password }}@{{ .Values.database.host }}:{{ .Values.database.port }}/{{ .Values.database.name }}"
# {{- end }}
# {{- end }}

# -----------------------------------------------------------------------------
# NOTES.TXT SECTION
# -----------------------------------------------------------------------------
# Add database connection info to NOTES.txt

# {{- if .Values.database.host }}
# Database Configuration:
# Type: {{ .Values.database.type }}
# Host: {{ .Values.database.host }}:{{ .Values.database.port }}
# Database: {{ .Values.database.name }}
# User: {{ .Values.database.username }}
# {{- else }}
# WARNING: Database host is not configured!
# Set database.host in your values to connect to your database.
# {{- end }}

# -----------------------------------------------------------------------------
# COMMON PORTS REFERENCE
# -----------------------------------------------------------------------------
# | Database | Default Port |
# |------------|--------------|
# | MySQL | 3306 |
# | PostgreSQL | 5432 |
# | MariaDB | 3306 |
# | MongoDB | 27017 |
# | Cassandra | 9042 |
# | CockroachDB| 26257 |

# -----------------------------------------------------------------------------
# EXAMPLE VALUES FOR DIFFERENT SCENARIOS
# -----------------------------------------------------------------------------

# MySQL in same cluster:
# database:
# type: mysql
# host: mysql.database.svc.cluster.local
# port: 3306
# name: myapp
# username: myapp
# existingSecret: myapp-db-credentials
# existingSecretKey: password

# PostgreSQL with SSL:
# database:
# type: postgres
# host: postgres.example.com
# port: 5432
# name: myapp
# username: myapp
# existingSecret: myapp-db-credentials
# params: "sslmode=require"

# AWS RDS MySQL:
# database:
# type: mysql
# host: myapp.xxxxx.us-east-1.rds.amazonaws.com
# port: 3306
# name: myapp
# username: admin
# existingSecret: rds-credentials
# params: "useSSL=true&requireSSL=true"
Loading