[add]: helm-chart-scaffolding
This commit is contained in:
560
skills/yanghuajun336/helm-chart-scaffolding/SKILL.md
Normal file
560
skills/yanghuajun336/helm-chart-scaffolding/SKILL.md
Normal file
@@ -0,0 +1,560 @@
|
||||
---
|
||||
名称:helm-chart-scaffolding
|
||||
描述:设计、组织和管理 Helm 图表,用于对 Kubernetes 应用程序进行模板化和打包,同时使用可重复使用的配置。在创建 Helm 图表、打包 Kubernetes 应用程序或实现模板化部署时使用。
|
||||
---
|
||||
|
||||
|
||||
# Helm 图表模板生成
|
||||
|
||||
有关为打包和部署 Kubernetes 应用程序创建、组织和管理 Helm 图表的全面指南。
|
||||
|
||||
## 目的
|
||||
|
||||
此技能提供了构建可投入生产的 Helm 图表的分步说明,包括图表结构、模板模式、值管理以及验证策略。
|
||||
|
||||
## 何时使用此技能
|
||||
|
||||
在您需要以下情况时使用此技能:
|
||||
|
||||
- 从零开始创建新的 Helm 图表
|
||||
- 将 Kubernetes 应用程序打包以进行分发
|
||||
- 使用 Helm 管理多环境部署
|
||||
- 为可重用的 Kubernetes 清单实现模板化
|
||||
- 设置 Helm 图表仓库
|
||||
- 遵循 Helm 最佳实践和约定
|
||||
|
||||
## Helm 概述
|
||||
|
||||
**Helm** 是 Kubernetes 的包管理器:
|
||||
|
||||
- 为可重用性创建 Kubernetes 清单模板
|
||||
- 管理应用程序的发布和回滚
|
||||
- 处理图表之间的依赖关系
|
||||
- 为部署提供版本控制
|
||||
- 简化跨环境的配置管理
|
||||
|
||||
## 分步工作流程
|
||||
|
||||
### 1. 初始化图表结构
|
||||
|
||||
**创建新图表:**
|
||||
|
||||
```bash
|
||||
helm create my-app
|
||||
```
|
||||
|
||||
**标准图表结构:**
|
||||
|
||||
```
|
||||
my-app/
|
||||
├── Chart.yaml # 图表元数据
|
||||
├── values.yaml # 默认配置值
|
||||
├── charts/ # 图表依赖
|
||||
├── templates/ # Kubernetes 清单模板
|
||||
│ ├── NOTES.txt # 安装后说明
|
||||
│ ├── _helpers.tpl # 模板辅助函数
|
||||
│ ├── deployment.yaml
|
||||
│ ├── service.yaml
|
||||
│ ├── ingress.yaml
|
||||
│ ├── serviceaccount.yaml
|
||||
│ ├── hpa.yaml
|
||||
│ └── tests/
|
||||
│ └── test-connection.yaml
|
||||
└── .helmignore # 忽略的文件
|
||||
```
|
||||
|
||||
### 2. 配置 Chart.yaml
|
||||
|
||||
**图表元数据定义了包:**
|
||||
|
||||
```yaml
|
||||
apiVersion: v2
|
||||
name: my-app
|
||||
description: 一个用于我的应用程序的 Helm 图表
|
||||
type: application
|
||||
version: 1.0.0 # 图表版本
|
||||
appVersion: "2.1.0" # 应用程序版本
|
||||
|
||||
# 图表发现关键字
|
||||
keywords:
|
||||
- web
|
||||
- api
|
||||
- backend
|
||||
|
||||
# 维护者信息
|
||||
maintainers:
|
||||
- name: yanghuajun336
|
||||
email: yanghuajun336@example.com
|
||||
url: https://github.com/yanghuajun336/my-app
|
||||
|
||||
# 源码仓库
|
||||
sources:
|
||||
- https://github.com/yanghuajun336/my-app
|
||||
|
||||
# 主页
|
||||
home: https://github.com/yanghuajun336
|
||||
|
||||
# 图表图标
|
||||
icon: https://example.com/icon.png
|
||||
|
||||
# 依赖
|
||||
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
|
||||
```
|
||||
|
||||
**参考:** 请参阅 `assets/Chart.yaml.template` 获取完整示例
|
||||
|
||||
### 3. 设计 values.yaml 结构
|
||||
|
||||
**按层次组织值:**
|
||||
```yaml
|
||||
# 镜像配置
|
||||
image:
|
||||
repository: myapp
|
||||
tag: "1.0.0"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# 副本数量
|
||||
replicaCount: 3
|
||||
|
||||
# Service 配置
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
|
||||
# Ingress 配置
|
||||
ingress:
|
||||
enabled: false
|
||||
className: nginx
|
||||
hosts:
|
||||
- host: app.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
# 资源限制
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# 自动扩缩容
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
# 环境变量
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "info"
|
||||
|
||||
# ConfigMap 数据
|
||||
configMap:
|
||||
data:
|
||||
APP_MODE: production
|
||||
|
||||
# 依赖
|
||||
postgresql:
|
||||
enabled: true
|
||||
auth:
|
||||
database: myapp
|
||||
username: myapp
|
||||
|
||||
redis:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
**参考:** 请参阅 `assets/values.yaml.template` 获取完整结构
|
||||
|
||||
### 4. 创建模板文件
|
||||
|
||||
**使用 Go 模板语法结合 Helm 函数:**
|
||||
|
||||
**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. 创建模板辅助函数
|
||||
|
||||
**templates/\_helpers.tpl:**
|
||||
|
||||
```yaml
|
||||
{{/*
|
||||
展开图表名称。
|
||||
*/}}
|
||||
{{- 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.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 }}
|
||||
```
|
||||
|
||||
### 6. 管理依赖
|
||||
|
||||
**在 Chart.yaml 中添加依赖:**
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled
|
||||
```
|
||||
|
||||
**更新依赖:**
|
||||
|
||||
```bash
|
||||
helm dependency update
|
||||
helm dependency build
|
||||
```
|
||||
|
||||
**覆盖依赖的配置值:**
|
||||
|
||||
```yaml
|
||||
# values.yaml
|
||||
postgresql:
|
||||
enabled: true
|
||||
auth:
|
||||
database: myapp
|
||||
username: myapp
|
||||
password: changeme
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
```
|
||||
|
||||
### 7. 测试与验证
|
||||
|
||||
**验证命令:**
|
||||
|
||||
```bash
|
||||
# 检查图表语法
|
||||
helm lint my-app/
|
||||
|
||||
# 模拟安装(不实际部署)
|
||||
helm install my-app ./my-app --dry-run --debug
|
||||
|
||||
# 渲染模板
|
||||
helm template my-app ./my-app
|
||||
|
||||
# 使用指定值文件渲染模板
|
||||
helm template my-app ./my-app -f values-prod.yaml
|
||||
|
||||
# 显示计算后的值
|
||||
helm show values ./my-app
|
||||
```
|
||||
|
||||
**验证脚本:**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "正在检查图表语法..."
|
||||
helm lint .
|
||||
|
||||
echo "正在测试模板渲染..."
|
||||
helm template test-release . --dry-run
|
||||
|
||||
echo "正在检查必填值..."
|
||||
helm template test-release . --validate
|
||||
|
||||
echo "所有验证均已通过!"
|
||||
```
|
||||
|
||||
**参考:** 请参阅 `scripts/validate-chart.sh`
|
||||
|
||||
### 8. 打包与分发
|
||||
|
||||
**打包图表:**
|
||||
|
||||
```bash
|
||||
helm package my-app/
|
||||
# 生成文件:my-app-1.0.0.tgz
|
||||
```
|
||||
|
||||
**创建图表仓库:**
|
||||
|
||||
```bash
|
||||
# 生成索引文件
|
||||
helm repo index .
|
||||
|
||||
# 上传到仓库
|
||||
# AWS S3 示例
|
||||
aws s3 sync . s3://my-helm-charts/ --exclude "*" --include "*.tgz" --include "index.yaml"
|
||||
```
|
||||
|
||||
**使用图表:**
|
||||
|
||||
```bash
|
||||
helm repo add my-repo https://charts.example.com
|
||||
helm repo update
|
||||
helm install my-app my-repo/my-app
|
||||
```
|
||||
|
||||
### 9. 多环境配置
|
||||
|
||||
**针对不同环境的值文件:**
|
||||
|
||||
```
|
||||
my-app/
|
||||
├── values.yaml # 默认配置
|
||||
├── values-dev.yaml # 开发环境
|
||||
├── values-staging.yaml # 预发布环境
|
||||
└── values-prod.yaml # 生产环境
|
||||
```
|
||||
|
||||
**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
|
||||
```
|
||||
|
||||
**使用环境值文件安装:**
|
||||
|
||||
```bash
|
||||
helm install my-app ./my-app -f values-prod.yaml --namespace production
|
||||
```
|
||||
|
||||
### 10. 实现 Hook 与测试
|
||||
|
||||
**安装前 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
|
||||
```
|
||||
|
||||
**测试连接:**
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
**运行测试:**
|
||||
|
||||
```bash
|
||||
helm test my-app
|
||||
```
|
||||
|
||||
## 常用模式
|
||||
|
||||
### 模式 1:条件化资源
|
||||
|
||||
```yaml
|
||||
{{- if .Values.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "my-app.fullname" . }}
|
||||
spec:
|
||||
# ...
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
### 模式 2:遍历列表
|
||||
|
||||
```yaml
|
||||
env:
|
||||
{{- range .Values.env }}
|
||||
- name: {{ .name }}
|
||||
value: {{ .value | quote }}
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
### 模式 3:引入外部文件
|
||||
|
||||
```yaml
|
||||
data:
|
||||
config.yaml: |
|
||||
{{- .Files.Get "config/application.yaml" | nindent 4 }}
|
||||
```
|
||||
|
||||
### 模式 4:全局值
|
||||
|
||||
```yaml
|
||||
global:
|
||||
imageRegistry: docker.io
|
||||
imagePullSecrets:
|
||||
- name: regcred
|
||||
|
||||
# 在模板中使用:
|
||||
image: {{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **使用语义化版本号** 管理图表和应用版本
|
||||
2. **为所有配置项添加注释** 在 values.yaml 中
|
||||
3. **使用模板辅助函数** 处理重复逻辑
|
||||
4. **打包前验证图表** 确保无误
|
||||
5. **明确固定依赖版本号**
|
||||
6. **为可选资源使用条件判断**
|
||||
7. **遵循命名规范**(小写字母,连字符分隔)
|
||||
8. **在 NOTES.txt 中** 提供使用说明
|
||||
9. **通过辅助函数** 统一添加标签
|
||||
10. **在所有环境中** 测试安装流程
|
||||
|
||||
## 故障排查
|
||||
|
||||
**模板渲染错误:**
|
||||
|
||||
```bash
|
||||
helm template my-app ./my-app --debug
|
||||
```
|
||||
|
||||
**依赖问题:**
|
||||
|
||||
```bash
|
||||
helm dependency update
|
||||
helm dependency list
|
||||
```
|
||||
|
||||
**安装失败:**
|
||||
|
||||
```bash
|
||||
helm install my-app ./my-app --dry-run --debug
|
||||
kubectl get events --sort-by='.lastTimestamp'
|
||||
```
|
||||
|
||||
|
||||
## 相关技能
|
||||
|
||||
- `k8s-manifest-generator` - 用于创建基础 Kubernetes 清单
|
||||
- `gitops-workflow` - 用于自动化 Helm 图表部署
|
||||
@@ -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
|
||||
@@ -0,0 +1,185 @@
|
||||
## 全局配置,供子 chart 共享
|
||||
global:
|
||||
imageRegistry: docker.io
|
||||
imagePullSecrets: []
|
||||
storageClass: ""
|
||||
|
||||
## 镜像相关配置
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: myapp/web
|
||||
tag: "" # 默认为 .Chart.AppVersion
|
||||
pullPolicy: IfNotPresent # 镜像拉取策略
|
||||
|
||||
## chart 名称覆盖
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
## 副本数量与修订历史
|
||||
replicaCount: 3 # 副本数
|
||||
revisionHistoryLimit: 10 # 保留历史版本数
|
||||
|
||||
## ServiceAccount 配置
|
||||
serviceAccount:
|
||||
create: true # 是否创建 ServiceAccount
|
||||
annotations: {} # 关联注解
|
||||
name: "" # 指定名称
|
||||
|
||||
## Pod 注解
|
||||
podAnnotations:
|
||||
prometheus.io/scrape: "true" # Prometheus 采集
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
|
||||
## Pod 安全上下文
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true # 非 root 用户运行
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
## 容器安全上下文
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false # 禁止权限提升
|
||||
readOnlyRootFilesystem: true # 只读根文件系统
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
|
||||
## Service 配置
|
||||
service:
|
||||
type: ClusterIP # 服务类型
|
||||
port: 80 # 服务端口
|
||||
targetPort: http # 目标端口
|
||||
annotations: {} # 服务注解
|
||||
sessionAffinity: None # 会话亲和性
|
||||
|
||||
## Ingress 配置
|
||||
ingress:
|
||||
enabled: false # 是否启用 Ingress
|
||||
className: nginx # Ingress 类名
|
||||
annotations: {} # Ingress 注解
|
||||
hosts:
|
||||
- host: app.example.com # 绑定域名
|
||||
paths:
|
||||
- path: / # 路径
|
||||
pathType: Prefix # 路径类型
|
||||
tls: [] # TLS 配置
|
||||
|
||||
## 资源限制与请求
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m # 最大 CPU
|
||||
memory: 512Mi # 最大内存
|
||||
requests:
|
||||
cpu: 250m # 最小 CPU
|
||||
memory: 256Mi # 最小内存
|
||||
|
||||
## 存活探针
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health/live
|
||||
port: http
|
||||
initialDelaySeconds: 30 # 首次探测延迟
|
||||
periodSeconds: 10 # 探测周期
|
||||
|
||||
## 就绪探针
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: http
|
||||
initialDelaySeconds: 5 # 首次探测延迟
|
||||
periodSeconds: 5 # 探测周期
|
||||
|
||||
## 自动扩缩容
|
||||
autoscaling:
|
||||
enabled: false # 是否启用自动扩缩容
|
||||
minReplicas: 2 # 最小副本数
|
||||
maxReplicas: 10 # 最大副本数
|
||||
targetCPUUtilizationPercentage: 80 # 目标 CPU 利用率
|
||||
targetMemoryUtilizationPercentage: 80 # 目标内存利用率
|
||||
|
||||
## Pod 弹性预算
|
||||
podDisruptionBudget:
|
||||
enabled: true # 是否启用 PDB
|
||||
minAvailable: 1 # 最小可用副本数
|
||||
|
||||
## 节点调度相关
|
||||
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
|
||||
|
||||
## 环境变量
|
||||
env: [] # 额外环境变量
|
||||
# - name: LOG_LEVEL
|
||||
# value: "info"
|
||||
|
||||
## ConfigMap 配置
|
||||
configMap:
|
||||
enabled: true # 是否启用 ConfigMap
|
||||
data: {} # 配置数据
|
||||
# APP_MODE: production
|
||||
# DATABASE_HOST: postgres.example.com
|
||||
|
||||
## Secret 配置(生产建议用外部 secret 管理)
|
||||
secrets:
|
||||
enabled: false # 是否启用 Secret
|
||||
data: {}
|
||||
|
||||
## 持久化存储
|
||||
persistence:
|
||||
enabled: false # 是否启用持久化
|
||||
storageClass: "" # 存储类
|
||||
accessMode: ReadWriteOnce # 访问模式
|
||||
size: 10Gi # 存储大小
|
||||
annotations: {} # 存储注解
|
||||
|
||||
## PostgreSQL 依赖
|
||||
postgresql:
|
||||
enabled: false # 是否启用 PostgreSQL
|
||||
auth:
|
||||
database: myapp # 数据库名
|
||||
username: myapp # 用户名
|
||||
password: changeme # 密码
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true # 是否持久化
|
||||
size: 10Gi # 存储大小
|
||||
|
||||
## Redis 依赖
|
||||
redis:
|
||||
enabled: false # 是否启用 Redis
|
||||
auth:
|
||||
enabled: false # 是否启用认证
|
||||
master:
|
||||
persistence:
|
||||
enabled: false # 是否持久化
|
||||
|
||||
## Prometheus ServiceMonitor
|
||||
serviceMonitor:
|
||||
enabled: false # 是否启用 ServiceMonitor
|
||||
interval: 30s # 采集间隔
|
||||
scrapeTimeout: 10s # 超时时间
|
||||
labels: {} # 额外标签
|
||||
|
||||
## 网络策略
|
||||
networkPolicy:
|
||||
enabled: false # 是否启用网络策略
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress: [] # 入站规则
|
||||
egress: [] # 出站规则
|
||||
@@ -0,0 +1,509 @@
|
||||
# Helm Chart 结构参考
|
||||
|
||||
Helm Chart 组织结构、文件规范与最佳实践完整指南。
|
||||
|
||||
## 标准 Chart 目录结构
|
||||
|
||||
```
|
||||
my-app/
|
||||
├── Chart.yaml # Chart 元数据(必需)
|
||||
├── Chart.lock # 依赖锁定文件(自动生成)
|
||||
├── values.yaml # 默认配置值(必需)
|
||||
├── values.schema.json # values 验证 JSON Schema
|
||||
├── .helmignore # 打包时忽略的文件模式
|
||||
├── README.md # Chart 文档
|
||||
├── LICENSE # Chart 许可证
|
||||
├── charts/ # Chart 依赖(打包内置)
|
||||
│ └── postgresql-12.0.0.tgz
|
||||
├── crds/ # 自定义资源定义(CRD)
|
||||
│ └── my-crd.yaml
|
||||
├── templates/ # Kubernetes 清单模板(必需)
|
||||
│ ├── NOTES.txt # 安装后说明
|
||||
│ ├── _helpers.tpl # 模板辅助函数
|
||||
│ ├── deployment.yaml
|
||||
│ ├── service.yaml
|
||||
│ ├── ingress.yaml
|
||||
│ ├── configmap.yaml
|
||||
│ ├── secret.yaml
|
||||
│ ├── serviceaccount.yaml
|
||||
│ ├── hpa.yaml
|
||||
│ ├── pdb.yaml
|
||||
│ ├── networkpolicy.yaml
|
||||
│ └── tests/
|
||||
│ └── test-connection.yaml
|
||||
└── files/ # 附加文件
|
||||
└── config/
|
||||
└── app.conf
|
||||
```
|
||||
|
||||
## Chart.yaml 规范
|
||||
|
||||
### API 版本 v2(Helm 3+)
|
||||
|
||||
```yaml
|
||||
apiVersion: v2 # 必需:API 版本
|
||||
name: my-application # 必需:Chart 名称
|
||||
version: 1.2.3 # 必需:Chart 版本(SemVer)
|
||||
appVersion: "2.5.0" # 应用版本
|
||||
description: A Helm chart for my application # 必需
|
||||
type: application # Chart 类型:application 或 library
|
||||
keywords: # 搜索关键词
|
||||
- web
|
||||
- api
|
||||
- backend
|
||||
home: https://example.com # 项目主页
|
||||
sources: # 源码地址
|
||||
- https://github.com/example/my-app
|
||||
maintainers: # 维护者列表
|
||||
- name: John Doe
|
||||
email: john@example.com
|
||||
url: https://github.com/johndoe
|
||||
icon: https://example.com/icon.png # Chart 图标 URL
|
||||
kubeVersion: ">=1.24.0" # 兼容的 Kubernetes 版本
|
||||
deprecated: false # 标记为已弃用
|
||||
annotations: # 自定义注解
|
||||
example.com/release-notes: https://example.com/releases/v1.2.3
|
||||
dependencies: # Chart 依赖
|
||||
- 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 类型
|
||||
|
||||
### Application Chart(应用 Chart)
|
||||
|
||||
```yaml
|
||||
type: application
|
||||
```
|
||||
|
||||
- 标准 Kubernetes 应用
|
||||
- 可安装和管理
|
||||
- 包含 K8s 资源模板
|
||||
|
||||
### Library Chart(库 Chart)
|
||||
|
||||
```yaml
|
||||
type: library
|
||||
```
|
||||
|
||||
- 共享模板辅助函数
|
||||
- 不可直接安装
|
||||
- 作为其他 Chart 的依赖使用
|
||||
- 无 templates/ 目录
|
||||
|
||||
## Values 文件组织
|
||||
|
||||
### values.yaml(默认值)
|
||||
|
||||
```yaml
|
||||
# 全局值(与子 Chart 共享)
|
||||
global:
|
||||
imageRegistry: docker.io
|
||||
imagePullSecrets: []
|
||||
|
||||
# 镜像配置
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: myapp/web
|
||||
tag: "" # 默认使用 .Chart.AppVersion
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Deployment 配置
|
||||
replicaCount: 1
|
||||
revisionHistoryLimit: 10
|
||||
|
||||
# Pod 配置
|
||||
podAnnotations: {}
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
|
||||
# 容器安全
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
|
||||
# Service
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: http
|
||||
annotations: {}
|
||||
|
||||
# 资源限制
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
|
||||
# 自动伸缩
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
# 节点选择
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
|
||||
# 监控
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
interval: 30s
|
||||
```
|
||||
|
||||
### values.schema.json(值校验)
|
||||
|
||||
```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"]
|
||||
}
|
||||
```
|
||||
|
||||
## 模板文件
|
||||
|
||||
### 模板命名规范
|
||||
|
||||
- **小写加连字符**:`deployment.yaml`、`service-account.yaml`
|
||||
- **局部模板**:以下划线开头,如 `_helpers.tpl`
|
||||
- **测试文件**:放在 `templates/tests/` 目录下
|
||||
- **CRD**:放在 `crds/` 目录下(不做模板化)
|
||||
|
||||
### 常用模板
|
||||
|
||||
#### \_helpers.tpl
|
||||
|
||||
```yaml
|
||||
{{/*
|
||||
标准命名辅助函数
|
||||
*/}}
|
||||
{{- 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 -}}
|
||||
|
||||
{{/*
|
||||
通用标签
|
||||
*/}}
|
||||
{{- 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 -}}
|
||||
|
||||
{{/*
|
||||
镜像名称辅助函数
|
||||
*/}}
|
||||
{{- 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
|
||||
|
||||
```
|
||||
感谢安装 {{ .Chart.Name }}。
|
||||
|
||||
您的 Release 名称为 {{ .Release.Name }}。
|
||||
|
||||
查看 Release 详情,请运行:
|
||||
|
||||
$ helm status {{ .Release.Name }}
|
||||
$ helm get all {{ .Release.Name }}
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
|
||||
应用访问地址:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
|
||||
通过以下命令获取应用访问地址:
|
||||
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 "访问 http://127.0.0.1:8080"
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
## 依赖管理
|
||||
|
||||
### 声明依赖
|
||||
|
||||
```yaml
|
||||
# Chart.yaml
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: "12.0.0"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
condition: postgresql.enabled # 通过 values 启用/禁用
|
||||
tags: # 依赖分组
|
||||
- database
|
||||
import-values: # 从子 Chart 导入 values
|
||||
- child: database
|
||||
parent: database
|
||||
alias: db # 通过 .Values.db 引用
|
||||
```
|
||||
|
||||
### 管理依赖
|
||||
|
||||
```bash
|
||||
# 更新依赖
|
||||
helm dependency update
|
||||
|
||||
# 列出依赖
|
||||
helm dependency list
|
||||
|
||||
# 构建依赖
|
||||
helm dependency build
|
||||
```
|
||||
|
||||
### Chart.lock
|
||||
|
||||
由 `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
|
||||
|
||||
从 Chart 包中排除的文件:
|
||||
|
||||
```
|
||||
# 开发文件
|
||||
.git/
|
||||
.gitignore
|
||||
*.md
|
||||
docs/
|
||||
|
||||
# 构建产物
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
|
||||
# CI/CD
|
||||
.travis.yml
|
||||
.gitlab-ci.yml
|
||||
Jenkinsfile
|
||||
|
||||
# 测试
|
||||
test/
|
||||
*.test
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.iml
|
||||
```
|
||||
|
||||
## 自定义资源定义(CRDs)
|
||||
|
||||
将 CRD 放在 `crds/` 目录下:
|
||||
|
||||
```
|
||||
crds/
|
||||
├── my-app-crd.yaml
|
||||
└── another-crd.yaml
|
||||
```
|
||||
|
||||
**CRD 重要说明:**
|
||||
|
||||
- CRD 在所有模板之前安装
|
||||
- CRD 不支持模板化(不可使用 `{{ }}` 语法)
|
||||
- CRD 不会随 Chart 升级或删除
|
||||
- 使用 `helm install --skip-crds` 可跳过安装
|
||||
|
||||
## Chart 版本管理
|
||||
|
||||
### 语义化版本
|
||||
|
||||
- **Chart 版本**:Chart 有变更时递增
|
||||
- MAJOR:不兼容的破坏性变更
|
||||
- MINOR:新功能,向后兼容
|
||||
- PATCH:Bug 修复
|
||||
|
||||
- **App 版本**:所部署应用的版本号
|
||||
- 可为任意字符串
|
||||
- 不强制遵循 SemVer
|
||||
|
||||
```yaml
|
||||
version: 2.3.1 # Chart 版本
|
||||
appVersion: "1.5.0" # 应用版本
|
||||
```
|
||||
|
||||
## Chart 测试
|
||||
|
||||
### 测试文件
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
helm test my-release
|
||||
helm test my-release --logs
|
||||
```
|
||||
|
||||
## Hooks(钩子)
|
||||
|
||||
Helm Hooks 允许在特定生命周期节点介入执行:
|
||||
|
||||
```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 类型
|
||||
|
||||
- `pre-install`:模板渲染前执行
|
||||
- `post-install`:所有资源加载完成后执行
|
||||
- `pre-delete`:任何资源删除前执行
|
||||
- `post-delete`:所有资源删除后执行
|
||||
- `pre-upgrade`:升级前执行
|
||||
- `post-upgrade`:升级后执行
|
||||
- `pre-rollback`:回滚前执行
|
||||
- `post-rollback`:回滚后执行
|
||||
- `test`:配合 `helm test` 执行
|
||||
|
||||
### Hook 权重
|
||||
|
||||
控制 Hook 执行顺序(-5 到 5,数值越小越先执行)
|
||||
|
||||
### Hook 删除策略
|
||||
|
||||
- `before-hook-creation`:创建新 Hook 前删除上一个
|
||||
- `hook-succeeded`:执行成功后删除
|
||||
- `hook-failed`:执行失败后删除
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **使用辅助函数**处理重复的模板逻辑
|
||||
2. **字符串加引号**:`{{ .Values.name | quote }}`
|
||||
3. **使用 values.schema.json** 校验 values
|
||||
4. **在 values.yaml 中注释所有字段**
|
||||
5. **使用语义化版本**管理 Chart 版本
|
||||
6. **精确锁定依赖版本**
|
||||
7. **包含 NOTES.txt** 提供使用说明
|
||||
8. **为关键功能编写测试**
|
||||
9. **使用 Hooks** 处理数据库迁移
|
||||
10. **保持 Chart 职责单一**——每个 Chart 只负责一个应用
|
||||
|
||||
## Chart 仓库结构
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
### 创建仓库索引
|
||||
|
||||
```bash
|
||||
helm repo index . --url https://charts.example.com
|
||||
```
|
||||
|
||||
## 相关资源
|
||||
|
||||
- [Helm 官方文档](https://helm.sh/docs/)
|
||||
- [Chart 模板指南](https://helm.sh/docs/chart_template_guide/)
|
||||
- [最佳实践](https://helm.sh/docs/chart_best_practices/)
|
||||
264
skills/yanghuajun336/helm-chart-scaffolding/scripts/validate-chart.sh
Executable file
264
skills/yanghuajun336/helm-chart-scaffolding/scripts/validate-chart.sh
Executable file
@@ -0,0 +1,264 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CHART_DIR="${1:-.}"
|
||||
RELEASE_NAME="test-release"
|
||||
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Helm Chart Validation"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Helm Chart 校验"
|
||||
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,请先安装 Helm"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Chart directory: $CHART_DIR"
|
||||
echo ""
|
||||
echo "📦 Chart 目录: $CHART_DIR"
|
||||
|
||||
# 1. Check chart structure
|
||||
echo "1️⃣ Checking chart structure..."
|
||||
echo "1️⃣ 检查 Chart 结构..."
|
||||
if [ ! -f "$CHART_DIR/Chart.yaml" ]; then
|
||||
error "未找到 Chart.yaml"
|
||||
exit 1
|
||||
fi
|
||||
success "Chart.yaml exists"
|
||||
|
||||
if [ ! -f "$CHART_DIR/values.yaml" ]; then
|
||||
error "未找到 values.yaml"
|
||||
exit 1
|
||||
fi
|
||||
success "values.yaml exists"
|
||||
|
||||
if [ ! -d "$CHART_DIR/templates" ]; then
|
||||
error "未找到 templates/ 目录"
|
||||
exit 1
|
||||
fi
|
||||
success "templates/ directory exists"
|
||||
echo ""
|
||||
|
||||
# 2. Lint the chart
|
||||
echo "2️⃣ Linting chart..."
|
||||
echo "2️⃣ Lint 检查..."
|
||||
if helm lint "$CHART_DIR"; then
|
||||
success "Lint 检查通过"
|
||||
else
|
||||
error "Lint 检查未通过"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 3. Check Chart.yaml
|
||||
echo "3️⃣ Validating Chart.yaml..."
|
||||
echo "3️⃣ 校验 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 名称"
|
||||
exit 1
|
||||
fi
|
||||
success "Chart name: $CHART_NAME"
|
||||
|
||||
if [ -z "$CHART_VERSION" ]; then
|
||||
error "未找到 Chart 版本"
|
||||
exit 1
|
||||
fi
|
||||
success "Chart version: $CHART_VERSION"
|
||||
|
||||
if [ -z "$APP_VERSION" ]; then
|
||||
warning "未指定 App 版本"
|
||||
else
|
||||
success "App 版本: $APP_VERSION"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 4. Test template rendering
|
||||
echo "4️⃣ Testing template rendering..."
|
||||
echo "4️⃣ 测试模板渲染..."
|
||||
if helm template "$RELEASE_NAME" "$CHART_DIR" > /dev/null 2>&1; then
|
||||
success "模板渲染成功"
|
||||
else
|
||||
error "模板渲染失败"
|
||||
helm template "$RELEASE_NAME" "$CHART_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 5. Dry-run installation
|
||||
echo "5️⃣ Testing dry-run installation..."
|
||||
echo "5️⃣ Dry-run 安装测试..."
|
||||
if helm install "$RELEASE_NAME" "$CHART_DIR" --dry-run --debug > /dev/null 2>&1; then
|
||||
success "Dry-run 安装成功"
|
||||
else
|
||||
error "Dry-run 安装失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 6. Check for required Kubernetes resources
|
||||
echo "6️⃣ Checking generated resources..."
|
||||
echo "6️⃣ 检查生成的资源..."
|
||||
MANIFESTS=$(helm template "$RELEASE_NAME" "$CHART_DIR")
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "kind: Deployment"; then
|
||||
success "检测到 Deployment"
|
||||
else
|
||||
warning "未检测到 Deployment"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "kind: Service"; then
|
||||
success "检测到 Service"
|
||||
else
|
||||
warning "未检测到 Service"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "kind: ServiceAccount"; then
|
||||
success "检测到 ServiceAccount"
|
||||
else
|
||||
warning "未检测到 ServiceAccount"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 7. Check for security best practices
|
||||
echo "7️⃣ Checking security best practices..."
|
||||
echo "7️⃣ 检查安全最佳实践..."
|
||||
if echo "$MANIFESTS" | grep -q "runAsNonRoot: true"; then
|
||||
success "已设置非 root 用户运行"
|
||||
else
|
||||
warning "未显式设置非 root 用户运行"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "readOnlyRootFilesystem: true"; then
|
||||
success "已启用只读根文件系统"
|
||||
else
|
||||
warning "未启用只读根文件系统"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "allowPrivilegeEscalation: false"; then
|
||||
success "已禁用权限提升"
|
||||
else
|
||||
warning "未显式禁用权限提升"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 8. Check for resource limits
|
||||
echo "8️⃣ Checking resource configuration..."
|
||||
echo "8️⃣ 检查资源配置..."
|
||||
if echo "$MANIFESTS" | grep -q "resources:"; then
|
||||
if echo "$MANIFESTS" | grep -q "limits:"; then
|
||||
success "已定义资源 limits"
|
||||
else
|
||||
warning "未定义资源 limits"
|
||||
fi
|
||||
if echo "$MANIFESTS" | grep -q "requests:"; then
|
||||
success "已定义资源 requests"
|
||||
else
|
||||
warning "未定义资源 requests"
|
||||
fi
|
||||
else
|
||||
warning "未定义资源配置"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 9. Check for health probes
|
||||
echo "9️⃣ Checking health probes..."
|
||||
echo "9️⃣ 检查健康探针..."
|
||||
if echo "$MANIFESTS" | grep -q "livenessProbe:"; then
|
||||
success "已配置 livenessProbe"
|
||||
else
|
||||
warning "未配置 livenessProbe"
|
||||
fi
|
||||
|
||||
if echo "$MANIFESTS" | grep -q "readinessProbe:"; then
|
||||
success "已配置 readinessProbe"
|
||||
else
|
||||
warning "未配置 readinessProbe"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 10. Check dependencies
|
||||
if [ -f "$CHART_DIR/Chart.yaml" ] && grep -q "^dependencies:" "$CHART_DIR/Chart.yaml"; then
|
||||
echo "🔟 检查依赖..."
|
||||
if helm dependency list "$CHART_DIR" > /dev/null 2>&1; then
|
||||
success "依赖项有效"
|
||||
|
||||
if [ -f "$CHART_DIR/Chart.lock" ]; then
|
||||
success "Chart.lock 文件存在"
|
||||
else
|
||||
warning "缺少 Chart.lock 文件(请运行 'helm dependency update')"
|
||||
fi
|
||||
else
|
||||
error "依赖检查失败"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 11. Check for values schema
|
||||
if [ -f "$CHART_DIR/values.schema.json" ]; then
|
||||
echo "1️⃣1️⃣ 校验 values.schema.json..."
|
||||
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 是有效 JSON"
|
||||
else
|
||||
error "values.schema.json 不是有效 JSON"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo " Validation Complete!"
|
||||
echo " 校验完成!"
|
||||
echo "═══════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Chart: $CHART_NAME"
|
||||
echo "Version: $CHART_VERSION"
|
||||
echo "版本: $CHART_VERSION"
|
||||
if [ -n "$APP_VERSION" ]; then
|
||||
echo "App 版本: $APP_VERSION"
|
||||
fi
|
||||
echo ""
|
||||
success "All validations passed!"
|
||||
success "所有校验均通过!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " • helm package $CHART_DIR"
|
||||
echo " • helm package $CHART_DIR"
|
||||
echo " • helm install my-release $CHART_DIR"
|
||||
echo " • helm test my-release"
|
||||
echo " • helm install my-release $CHART_DIR"
|
||||
echo " • helm test my-release"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user