Loading...
Loading...
Compare original and translation side by side
Production-grade Helm charts. Sensible defaults. Secure by design. No cargo-culting.
生产级Helm Chart。合理默认配置。设计即安全。拒绝盲目照搬。
| Command | What it does |
|---|---|
| Scaffold a production-ready Helm chart with best-practice structure |
| Analyze an existing chart for issues — missing labels, hardcoded values, template anti-patterns |
| Audit chart for security issues — RBAC, network policies, pod security, secrets handling |
| 命令 | 功能 |
|---|---|
| 基于最佳实践结构搭建生产就绪的Helm Chart |
| 分析现有Chart的问题——缺失标签、硬编码值、模板反模式 |
| 审计Chart的安全问题——RBAC、网络策略、Pod安全、密钥处理 |
/helm:create/helm:createmychart/
├── Chart.yaml # Chart metadata and dependencies
├── values.yaml # Default configuration
├── values.schema.json # Optional: JSON Schema for values validation
├── .helmignore # Files to exclude from packaging
├── templates/
│ ├── _helpers.tpl # Named templates and helper functions
│ ├── deployment.yaml # Workload resource
│ ├── service.yaml # Service exposure
│ ├── ingress.yaml # Ingress (if applicable)
│ ├── serviceaccount.yaml # ServiceAccount
│ ├── hpa.yaml # HorizontalPodAutoscaler
│ ├── pdb.yaml # PodDisruptionBudget
│ ├── networkpolicy.yaml # NetworkPolicy
│ ├── configmap.yaml # ConfigMap (if needed)
│ ├── secret.yaml # Secret (if needed)
│ ├── NOTES.txt # Post-install usage instructions
│ └── tests/
│ └── test-connection.yaml
└── charts/ # Subcharts (dependencies)METADATA
├── apiVersion: v2 (Helm 3 only — never v1)
├── name: matches directory name exactly
├── version: semver (chart version, not app version)
├── appVersion: application version string
├── description: one-line summary of what the chart deploys
└── type: application (or library for shared helpers)
DEPENDENCIES
├── Pin dependency versions with ~X.Y.Z (patch-level float)
├── Use condition field to make subcharts optional
├── Use alias for multiple instances of same subchart
└── Run helm dependency update after changespython3 scripts/chart_analyzer.py mychart/
helm lint mychart/
helm template mychart/ --debugmychart/
├── Chart.yaml # Chart元数据与依赖
├── values.yaml # 默认配置
├── values.schema.json # 可选:values验证用JSON Schema
├── .helmignore # 打包时排除的文件
├── templates/
│ ├── _helpers.tpl # 命名模板与助手函数
│ ├── deployment.yaml # 工作负载资源
│ ├── service.yaml # 服务暴露
│ ├── ingress.yaml # Ingress(如适用)
│ ├── serviceaccount.yaml # ServiceAccount
│ ├── hpa.yaml # HorizontalPodAutoscaler
│ ├── pdb.yaml # PodDisruptionBudget
│ ├── networkpolicy.yaml # NetworkPolicy
│ ├── configmap.yaml # ConfigMap(如需要)
│ ├── secret.yaml # Secret(如需要)
│ ├── NOTES.txt # 安装后使用说明
│ └── tests/
│ └── test-connection.yaml
└── charts/ # 子Chart(依赖)元数据
├── apiVersion: v2(仅Helm 3版本——绝不使用v1)
├── name: 与目录名称完全匹配
├── version: 语义化版本(Chart版本,而非应用版本)
├── appVersion: 应用版本字符串
├── description: 一行文字概述Chart部署的内容
└── type: application(或library用于共享助手)
依赖
├── 使用~X.Y.Z锁定依赖版本(补丁级浮动)
├── 使用condition字段将子Chart设为可选
├── 使用alias处理同一子Chart的多个实例
└修改后运行helm dependency updatepython3 scripts/chart_analyzer.py mychart/
helm lint mychart/
helm template mychart/ --debug/helm:review/helm:review| Check | Severity | Fix |
|---|---|---|
| Missing _helpers.tpl | High | Create helpers for common labels and selectors |
| No NOTES.txt | Medium | Add post-install instructions |
| No .helmignore | Low | Create one to exclude .git, CI files, tests |
| Missing Chart.yaml fields | Medium | Add description, appVersion, maintainers |
| Hardcoded values in templates | High | Extract to values.yaml with defaults |
| Check | Severity | Fix |
|---|---|---|
| Missing standard labels | High | Use |
| No resource requests/limits | Critical | Add resources section with defaults in values.yaml |
| Hardcoded image tag | High | Use |
| No imagePullPolicy | Medium | Default to |
| Missing liveness/readiness probes | High | Add probes with configurable paths and ports |
| No pod anti-affinity | Medium | Add preferred anti-affinity for HA |
| Duplicate template code | Medium | Extract into named templates in _helpers.tpl |
python3 scripts/values_validator.py mychart/values.yamlHELM CHART REVIEW — [chart name]
Date: [timestamp]
CRITICAL: [count]
HIGH: [count]
MEDIUM: [count]
LOW: [count]
[Detailed findings with fix recommendations]| 检查项 | 严重程度 | 修复方案 |
|---|---|---|
| 缺失_helpers.tpl | 高 | 创建通用标签和选择器的助手 |
| 无NOTES.txt | 中 | 添加安装后说明 |
| 无.helmignore | 低 | 创建文件以排除.git、CI文件、测试文件 |
| 缺失Chart.yaml字段 | 中 | 添加description、appVersion、maintainers |
| 模板中存在硬编码值 | 高 | 提取到values.yaml并设置默认值 |
| 检查项 | 严重程度 | 修复方案 |
|---|---|---|
| 缺失标准标签 | 高 | 通过_helpers.tpl使用 |
| 无资源请求/限制 | 关键 | 在values.yaml中添加带默认值的resources部分 |
| 硬编码镜像标签 | 高 | 使用 |
| 无imagePullPolicy | 中 | 默认设为 |
| 缺失存活/就绪探针 | 高 | 添加可配置路径和端口的探针 |
| 无Pod反亲和性 | 中 | 添加用于高可用的首选反亲和性 |
| 重复模板代码 | 中 | 提取到_helpers.tpl中的命名模板 |
python3 scripts/values_validator.py mychart/values.yamlHELM CHART 审核 — [Chart名称]
日期: [时间戳]
关键: [数量]
高: [数量]
中: [数量]
低: [数量]
[带修复建议的详细发现]/helm:security/helm:security| Check | Severity | Fix |
|---|---|---|
| No securityContext | Critical | Add runAsNonRoot, readOnlyRootFilesystem |
| Running as root | Critical | Set |
| Writable root filesystem | High | Set |
| All capabilities retained | High | Drop ALL, add only specific needed caps |
| Privileged container | Critical | Set |
| No seccomp profile | Medium | Set |
| allowPrivilegeEscalation true | High | Set |
| Check | Severity | Fix |
|---|---|---|
| No ServiceAccount | Medium | Create dedicated SA, don't use default |
| automountServiceAccountToken true | Medium | Set to false unless pod needs K8s API access |
| ClusterRole instead of Role | Medium | Use namespace-scoped Role unless cluster-wide needed |
| Wildcard permissions | Critical | Use specific resource names and verbs |
| No RBAC at all | Low | Acceptable if pod doesn't need K8s API access |
| Check | Severity | Fix |
|---|---|---|
| No NetworkPolicy | Medium | Add default-deny ingress + explicit allow rules |
| Secrets in values.yaml | Critical | Use external secrets operator or sealed-secrets |
| No PodDisruptionBudget | Medium | Add PDB with minAvailable for HA workloads |
| hostNetwork: true | High | Remove unless absolutely required (e.g., CNI plugin) |
| hostPID or hostIPC | Critical | Never use in application charts |
SECURITY AUDIT — [chart name]
Date: [timestamp]
CRITICAL: [count]
HIGH: [count]
MEDIUM: [count]
LOW: [count]
[Detailed findings with remediation steps]| 检查项 | 严重程度 | 修复方案 |
|---|---|---|
| 无securityContext | 关键 | 添加runAsNonRoot、readOnlyRootFilesystem |
| 以root身份运行 | 关键 | 设置 |
| 可写根文件系统 | 高 | 设置 |
| 保留所有权限 | 高 | 移除ALL权限,仅添加所需的特定权限 |
| 特权容器 | 关键 | 设置 |
| 无seccomp配置文件 | 中 | 设置 |
| allowPrivilegeEscalation为true | 高 | 设置 |
| 检查项 | 严重程度 | 修复方案 |
|---|---|---|
| 无ServiceAccount | 中 | 创建专用SA,不使用默认SA |
| automountServiceAccountToken为true | 中 | 除非Pod需要K8s API访问,否则设为false |
| 使用ClusterRole而非Role | 中 | 除非需要集群范围权限,否则使用命名空间级Role |
| 通配符权限 | 关键 | 使用特定资源名称和动词 |
| 无RBAC配置 | 低 | 如果Pod不需要K8s API访问则可接受 |
| 检查项 | 严重程度 | 修复方案 |
|---|---|---|
| 无NetworkPolicy | 中 | 添加默认拒绝Ingress + 明确允许规则 |
| values.yaml中包含密钥 | 关键 | 使用外部密钥操作器或密封密钥 |
| 无PodDisruptionBudget | 中 | 为高可用工作负载添加带minAvailable的PDB |
| hostNetwork: true | 高 | 除非绝对必要(如CNI插件)否则移除 |
| hostPID或hostIPC | 关键 | 应用Chart中绝不使用 |
安全审计 — [Chart名称]
日期: [时间戳]
关键: [数量]
高: [数量]
中: [数量]
低: [数量]
[带修复步骤的详细发现]scripts/chart_analyzer.pyscripts/chart_analyzer.pyundefinedundefinedundefinedundefinedscripts/values_validator.pyscripts/values_validator.pyundefinedundefined
---
---{{/*
Common labels for all resources.
*/}}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ include "mychart.chart" . }}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels (subset of common labels — must be immutable).
*/}}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}{{/*
所有资源的通用标签。
*/}}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ include "mychart.chart" . }}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
选择器标签(通用标签的子集——必须不可变)。
*/}}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "mychart.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "mychart.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}spec:
serviceAccountName: {{ include "mychart.serviceAccountName" . }}
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: {{ .Chart.Name }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
resources:
{{- toYaml .Values.resources | nindent 8 }}
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}spec:
serviceAccountName: {{ include "mychart.serviceAccountName" . }}
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: {{ .Chart.Name }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
resources:
{{- toYaml .Values.resources | nindent 8 }}
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}STRUCTURE
├── Flat over nested (image.tag > container.spec.image.tag)
├── Group by resource (service.*, ingress.*, resources.*)
├── Use enabled: true/false for optional resources
├── Document every key with inline YAML comments
└── Provide sensible development defaults
NAMING
├── camelCase for keys (replicaCount, not replica_count)
├── Boolean keys: use adjectives (enabled, required) not verbs
├── Nested keys: max 3 levels deep
└── Match upstream conventions (image.repository, image.tag, image.pullPolicy)
ANTI-PATTERNS
├── Hardcoded cluster URLs or domains
├── Secrets as default values
├── Empty strings where null is correct
├── Deeply nested structures (>3 levels)
├── Undocumented values
└── values.yaml that doesn't work without overrides结构
├── 优先扁平化而非嵌套(image.tag > container.spec.image.tag)
├── 按资源分组(service.*、ingress.*、resources.*)
├── 使用enabled: true/false控制可选资源
├── 为每个键添加行内YAML注释文档
└── 提供适用于开发环境的合理默认值
命名
├── 键使用驼峰式(replicaCount,而非replica_count)
├── 布尔键:使用形容词(enabled、required)而非动词
├── 嵌套键:最多3层深度
└── 匹配上游约定(image.repository、image.tag、image.pullPolicy)
反模式
├── 硬编码集群URL或域名
├── 将密钥设为默认值
├── 用空字符串代替null
├── 深度嵌套结构(>3层)
├── 未文档化的值
└── 不覆盖就无法工作的values.yamlSUBCHARTS
├── Use Chart.yaml dependencies (not requirements.yaml — Helm 3)
├── Pin versions: version: ~15.x.x (patch float)
├── Use condition: to make optional: condition: postgresql.enabled
├── Use alias: for multiple instances of same chart
├── Override subchart values under subchart name key in values.yaml
└── Run helm dependency update before packaging
LIBRARY CHARTS
├── type: library in Chart.yaml — no templates directory
├── Export named templates only — no rendered resources
├── Use for shared labels, annotations, security contexts
└── Version independently from application charts子Chart
├── 使用Chart.yaml管理依赖(Helm 3不使用requirements.yaml)
├── 锁定版本:version: ~15.x.x(补丁级浮动)
├── 使用condition: 将子Chart设为可选:condition: postgresql.enabled
├── 使用alias: 处理同一Chart的多个实例
├── 在values.yaml中子Chart名称键下覆盖子Chart值
└── 打包前运行helm dependency update
库Chart
├── 在Chart.yaml中设置type: library——无templates目录
├── 仅导出命名模板——无渲染资源
├── 用于共享标签、注解、安全上下文
└── 独立于应用Chart进行版本管理git clone https://github.com/alirezarezvani/claude-skills.git
cp -r claude-skills/engineering/helm-chart-builder ~/.claude/skills/git clone https://github.com/alirezarezvani/claude-skills.git
cp -r claude-skills/engineering/helm-chart-builder ~/.claude/skills/./scripts/convert.sh --skill helm-chart-builder --tool codex|gemini|cursor|windsurf|openclaw./scripts/convert.sh --skill helm-chart-builder --tool codex|gemini|cursor|windsurf|openclawclawhub install cs-helm-chart-builderclawhub install cs-helm-chart-builder