deploy-app
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDeploy App Workflow
部署应用工作流
End-to-end orchestration for deploying applications to the Kubernetes homelab with full monitoring integration.
用于将应用部署到Kubernetes家庭实验室的端到端编排能力,自带完整的监控集成。
Workflow Overview
工作流概览
┌─────────────────────────────────────────────────────────────────────┐
│ /deploy-app Workflow │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. RESEARCH │
│ ├─ Invoke kubesearch skill for real-world patterns │
│ ├─ Check if native Helm chart exists (helm search hub) │
│ ├─ Determine: native chart vs app-template │
│ └─ AskUserQuestion: Present findings, confirm approach │
│ │
│ 2. SETUP │
│ └─ task wt:new -- deploy-<app-name> │
│ (Creates isolated worktree + branch) │
│ │
│ 3. CONFIGURE (in worktree) │
│ ├─ kubernetes/platform/versions.env (add version) │
│ ├─ kubernetes/platform/namespaces.yaml (add namespace) │
│ ├─ kubernetes/platform/helm-charts.yaml (add input) │
│ ├─ kubernetes/platform/charts/<app>.yaml (create values) │
│ ├─ kubernetes/platform/kustomization.yaml (register) │
│ ├─ .github/renovate.json5 (add manager) │
│ └─ kubernetes/platform/config/<app>/ (optional extras) │
│ ├─ route.yaml (HTTPRoute if exposed) │
│ ├─ canary.yaml (health checks) │
│ ├─ prometheus-rules.yaml (custom alerts) │
│ └─ dashboard.yaml (Grafana ConfigMap) │
│ │
│ 4. VALIDATE │
│ ├─ task k8s:validate │
│ └─ task renovate:validate │
│ │
│ 5. TEST ON DEV (bypass Flux) │
│ ├─ helm install directly to dev cluster │
│ ├─ Wait for pods ready (kubectl wait) │
│ ├─ Verify ServiceMonitor discovered (Prometheus API) │
│ ├─ Verify no new alerts firing │
│ ├─ Verify canary passing (if created) │
│ └─ AskUserQuestion: Report status, confirm proceed │
│ │
│ 6. CLEANUP & PR │
│ ├─ helm uninstall from dev │
│ ├─ git commit (conventional commit format) │
│ ├─ git push + gh pr create │
│ └─ Report PR URL to user │
│ │
└─────────────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────────────┐
│ /deploy-app Workflow │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. RESEARCH │
│ ├─ Invoke kubesearch skill for real-world patterns │
│ ├─ Check if native Helm chart exists (helm search hub) │
│ ├─ Determine: native chart vs app-template │
│ └─ AskUserQuestion: Present findings, confirm approach │
│ │
│ 2. SETUP │
│ └─ task wt:new -- deploy-<app-name> │
│ (Creates isolated worktree + branch) │
│ │
│ 3. CONFIGURE (in worktree) │
│ ├─ kubernetes/platform/versions.env (add version) │
│ ├─ kubernetes/platform/namespaces.yaml (add namespace) │
│ ├─ kubernetes/platform/helm-charts.yaml (add input) │
│ ├─ kubernetes/platform/charts/<app>.yaml (create values) │
│ ├─ kubernetes/platform/kustomization.yaml (register) │
│ ├─ .github/renovate.json5 (add manager) │
│ └─ kubernetes/platform/config/<app>/ (optional extras) │
│ ├─ route.yaml (HTTPRoute if exposed) │
│ ├─ canary.yaml (health checks) │
│ ├─ prometheus-rules.yaml (custom alerts) │
│ └─ dashboard.yaml (Grafana ConfigMap) │
│ │
│ 4. VALIDATE │
│ ├─ task k8s:validate │
│ └─ task renovate:validate │
│ │
│ 5. TEST ON DEV (bypass Flux) │
│ ├─ helm install directly to dev cluster │
│ ├─ Wait for pods ready (kubectl wait) │
│ ├─ Verify ServiceMonitor discovered (Prometheus API) │
│ ├─ Verify no new alerts firing │
│ ├─ Verify canary passing (if created) │
│ └─ AskUserQuestion: Report status, confirm proceed │
│ │
│ 6. CLEANUP & PR │
│ ├─ helm uninstall from dev │
│ ├─ git commit (conventional commit format) │
│ ├─ git push + gh pr create │
│ └─ Report PR URL to user │
│ │
└─────────────────────────────────────────────────────────────────────┘Phase 1: Research
第一阶段:调研
1.1 Search Kubesearch for Real-World Examples
1.1 在Kubesearch中搜索实际落地示例
Invoke the kubesearch skill to find how other homelabs configure this chart:
/kubesearch <chart-name>This provides:
- Common configuration patterns
- Values.yaml examples from production homelabs
- Gotchas and best practices
调用kubesearch skill查找其他家庭实验室配置该Chart的方案:
/kubesearch <chart-name>返回结果包含:
- 通用配置模式
- 生产级家庭实验室的values.yaml示例
- 注意事项和最佳实践
1.2 Check for Native Helm Chart
1.2 检查是否存在原生Helm Chart
bash
helm search hub <app-name> --max-col-width=100Decision matrix:
| Scenario | Approach |
|---|---|
| Official/community chart exists | Use native Helm chart |
| Only container image available | Use app-template |
| Chart is unmaintained (>1 year) | Consider app-template |
| User preference for app-template | Use app-template |
bash
helm search hub <app-name> --max-col-width=100决策矩阵:
| 场景 | 方案 |
|---|---|
| 存在官方/社区维护的Chart | 使用原生Helm Chart |
| 仅提供容器镜像 | 使用app-template |
| Chart已停止维护(超过1年) | 考虑使用app-template |
| 用户偏好使用app-template | 使用app-template |
1.3 User Confirmation
1.3 用户确认
Use AskUserQuestion to present findings and confirm:
- Chart selection (native vs app-template)
- Exposure type: internal, external, or none
- Namespace selection (new or existing)
- Persistence requirements
使用AskUserQuestion呈现调研结果并确认以下信息:
- Chart选择(原生vs app-template)
- 暴露类型:内网、公网或不暴露
- 命名空间选择(新建或复用现有)
- 持久化存储需求
Phase 2: Setup
第二阶段:环境准备
2.1 Create Worktree
2.1 创建工作树
All deployment work happens in an isolated worktree:
bash
task wt:new -- deploy-<app-name>This creates:
- Branch:
deploy-<app-name> - Worktree:
../homelab-deploy-<app-name>/
所有部署工作都在隔离的工作树中完成:
bash
task wt:new -- deploy-<app-name>该命令会创建:
- 分支:
deploy-<app-name> - 工作树:
../homelab-deploy-<app-name>/
2.2 Change to Worktree
2.2 切换到工作树目录
bash
cd ../homelab-deploy-<app-name>All subsequent file operations happen in the worktree.
bash
cd ../homelab-deploy-<app-name>后续所有文件操作都在该工作树中完成。
Phase 3: Configure
第三阶段:配置
3.1 Add Version to versions.env
3.1 在versions.env中添加版本号
Add a version entry with a Renovate annotation. For annotation syntax and datasource selection, see the versions-renovate skill.
bash
undefined添加带Renovate注解的版本条目。注解语法和数据源选择可参考versions-renovate skill。
bash
undefinedkubernetes/platform/versions.env
kubernetes/platform/versions.env
<APP>_VERSION="x.y.z"
undefined<APP>_VERSION="x.y.z"
undefined3.2 Add Namespace to namespaces.yaml
3.2 在namespaces.yaml中添加命名空间
Add to inputs array:
kubernetes/platform/namespaces.yamlyaml
- name: <namespace>
dataplane: ambient
security: baseline # Choose: restricted, baseline, privileged
networkPolicy: false # Or object with profile/enforcementPodSecurity Level Selection:
| Level | Use When | Security Context Required |
|---|---|---|
| Standard controllers, databases, simple apps | Full restricted context on all containers |
| Apps needing elevated capabilities (e.g., | Moderate |
| Host access, BPF, device access | None |
If : You MUST set full security context in chart values (see step 3.4a below).
security: restrictedNetwork Policy Profile Selection:
| Profile | Use When |
|---|---|
| Batch jobs, workers with no inbound traffic |
| Internal dashboards/tools (internal gateway only) |
| Internal apps that call external APIs |
| Public-facing web apps (both gateways + HTTPS egress) |
Optional Access Labels (add if app needs these):
yaml
access.network-policy.homelab/postgres: "true" # Database access
access.network-policy.homelab/garage-s3: "true" # S3 storage access
access.network-policy.homelab/kube-api: "true" # Kubernetes API accessFor PostgreSQL provisioning patterns, see the cnpg-database skill.
添加到的inputs数组中:
kubernetes/platform/namespaces.yamlyaml
- name: <namespace>
dataplane: ambient
security: baseline # 可选值:restricted, baseline, privileged
networkPolicy: false # 或者包含profile/enforcement的对象PodSecurity等级选择:
| 等级 | 适用场景 | 所需安全上下文 |
|---|---|---|
| 标准控制器、数据库、简单应用 | 所有容器都需要配置完整的受限上下文 |
| 需要提升权限的应用(例如 | 中等安全要求 |
| 需要主机访问、BPF、设备访问的应用 | 无 |
如果配置:必须在Chart values中配置完整的安全上下文(参考下方步骤3.4a)。
security: restricted网络策略配置文件选择:
| 配置文件 | 适用场景 |
|---|---|
| 批量任务、无入站流量的工作节点 |
| 内部仪表盘/工具(仅允许内网网关访问) |
| 需要调用外部API的内部应用 |
| 对外提供服务的Web应用(支持双网关+HTTPS出站) |
可选访问标签(如果应用需要可添加):
yaml
access.network-policy.homelab/postgres: "true" # 数据库访问权限
access.network-policy.homelab/garage-s3: "true" # S3存储访问权限
access.network-policy.homelab/kube-api: "true" # Kubernetes API访问权限PostgreSQL配置模式可参考cnpg-database skill。
3.3 Add to helm-charts.yaml
3.3 添加到helm-charts.yaml
Add to inputs array:
kubernetes/platform/helm-charts.yamlyaml
- name: "<app-name>"
namespace: "<namespace>"
chart:
name: "<chart-name>"
version: "${<APP>_VERSION}"
url: "https://charts.example.com" # or oci://registry.io/path
dependsOn: [cilium] # Adjust based on dependenciesFor OCI registries:
yaml
url: "oci://ghcr.io/org/helm"添加到的inputs数组中:
kubernetes/platform/helm-charts.yamlyaml
- name: "<app-name>"
namespace: "<namespace>"
chart:
name: "<chart-name>"
version: "${<APP>_VERSION}"
url: "https://charts.example.com" # 或 oci://registry.io/path
dependsOn: [cilium] # 根据依赖调整OCI镜像源配置示例:
yaml
url: "oci://ghcr.io/org/helm"3.4 Create Values File
3.4 创建Values文件
Create :
kubernetes/platform/charts/<app-name>.yamlyaml
undefined创建:
kubernetes/platform/charts/<app-name>.yamlyaml
undefinedyaml-language-server: $schema=<schema-url-if-available>
yaml-language-server: $schema=<schema-url-if-available>
Helm values for <app-name>
Helm values for <app-name>
Based on kubesearch research and best practices
Based on kubesearch research and best practices
Enable monitoring
Enable monitoring
serviceMonitor:
enabled: true
serviceMonitor:
enabled: true
Use internal domain for ingress
Use internal domain for ingress
ingress:
enabled: true
hosts:
- host: <app-name>.${internal_domain}
See [references/file-templates.md](references/file-templates.md) for complete templates.ingress:
enabled: true
hosts:
- host: <app-name>.${internal_domain}
完整模板可参考[references/file-templates.md](references/file-templates.md)。3.4a Add Security Context for Restricted Namespaces
3.4a 为受限命名空间添加安全上下文
If the target namespace uses , add security context to the chart values. Check the container image's default user first -- if it runs as root, set .
security: restrictedrunAsUser: 65534yaml
undefined如果目标命名空间使用,需要在Chart values中添加安全上下文。先检查容器镜像的默认用户,如果默认以root运行,设置。
security: restrictedrunAsUser: 65534yaml
undefinedPod-level (key varies by chart: podSecurityContext, securityContext, pod.securityContext)
Pod级(不同Chart的key可能不同:podSecurityContext, securityContext, pod.securityContext)
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
Container-level (every container and init container)
容器级(所有容器和初始化容器都需要配置)
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
**Restricted namespaces**: cert-manager, external-secrets, system, database, kromgo.
**Validation gap**: `task k8s:validate` does NOT catch PodSecurity violations -- only server-side dry-run or actual deployment reveals them. Always verify security context manually for restricted namespaces.securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
**受限命名空间列表**:cert-manager, external-secrets, system, database, kromgo。
**校验注意事项**:`task k8s:validate`不会捕获PodSecurity违规,只有服务端 dry-run 或实际部署时才会暴露问题。请始终为受限命名空间手动校验安全上下文配置。3.5 Register in kustomization.yaml
3.5 在kustomization.yaml中注册
Add to configMapGenerator:
kubernetes/platform/kustomization.yamlyaml
configMapGenerator:
- name: platform-values
files:
# ... existing
- charts/<app-name>.yaml添加到的configMapGenerator中:
kubernetes/platform/kustomization.yamlyaml
configMapGenerator:
- name: platform-values
files:
# ... 现有配置
- charts/<app-name>.yaml3.6 Configure Renovate Tracking
3.6 配置Renovate版本追踪
Renovate tracks versions.env entries automatically via inline annotations (added in step 3.1). No changes to are needed unless you want to add grouping or automerge overrides. For the full annotation workflow, see the versions-renovate skill.
# renovate:.github/renovate.json5Renovate会通过步骤3.1中添加的注解自动追踪versions.env中的条目。除非需要添加分组或自动合并覆盖配置,否则不需要修改。完整注解工作流可参考versions-renovate skill。
# renovate:.github/renovate.json53.7 Optional: Additional Configuration
3.7 可选:额外配置
For apps that need extra resources, create :
kubernetes/platform/config/<app-name>/如果应用需要额外资源,创建目录:
kubernetes/platform/config/<app-name>/HTTPRoute (for exposed apps)
HTTPRoute(用于对外暴露的应用)
For detailed gateway routing and certificate configuration, see the gateway-routing skill.
yaml
undefined详细的网关路由和证书配置可参考gateway-routing skill。
yaml
undefinedconfig/<app-name>/route.yaml
config/<app-name>/route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: <app-name>
spec:
parentRefs:
- name: internal-gateway
namespace: gateway
hostnames:
- <app-name>.${internal_domain}
rules:
- backendRefs:
- name: <app-name>
port: 80
undefinedapiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: <app-name>
spec:
parentRefs:
- name: internal-gateway
namespace: gateway
hostnames:
- <app-name>.${internal_domain}
rules:
- backendRefs:
- name: <app-name>
port: 80
undefinedCanary Health Check
金丝雀健康检查
yaml
undefinedyaml
undefinedconfig/<app-name>/canary.yaml
config/<app-name>/canary.yaml
apiVersion: canaries.flanksource.com/v1
kind: Canary
metadata:
name: http-check-<app-name>
spec:
schedule: "@every 1m"
http:
- name: <app-name>-health
url: https://<app-name>.${internal_domain}/health
responseCodes: [200]
maxSSLExpiry: 7
undefinedapiVersion: canaries.flanksource.com/v1
kind: Canary
metadata:
name: http-check-<app-name>
spec:
schedule: "@every 1m"
http:
- name: <app-name>-health
url: https://<app-name>.${internal_domain}/health
responseCodes: [200]
maxSSLExpiry: 7
undefinedPrometheusRule (custom alerts)
PrometheusRule(自定义告警)
Only create if the chart doesn't include its own alerts:
yaml
undefined仅当Chart没有自带告警规则时创建:
yaml
undefinedconfig/<app-name>/prometheus-rules.yaml
config/<app-name>/prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: <app-name>-alerts
spec:
groups:
- name: <app-name>.rules
rules:
- alert: <AppName>Down
expr: up{job="<app-name>"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "<app-name> is down"
undefinedapiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: <app-name>-alerts
spec:
groups:
- name: <app-name>.rules
rules:
- alert: <AppName>Down
expr: up{job="<app-name>"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "<app-name> is down"
undefinedGrafana Dashboard
Grafana仪表盘
- Search grafana.com for community dashboards
- Add via gnetId in grafana values, OR
- Create ConfigMap:
yaml
undefined- 在grafana.com搜索社区仪表盘
- 在grafana values中通过gnetId添加,或者
- 创建ConfigMap:
yaml
undefinedconfig/<app-name>/dashboard.yaml
config/<app-name>/dashboard.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-dashboard-<app-name>
labels:
grafana_dashboard: "true"
annotations:
grafana_folder: "Applications"
data:
<app-name>.json: |
{ ... dashboard JSON ... }
See [references/monitoring-patterns.md](references/monitoring-patterns.md) for detailed examples.
---apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-dashboard-<app-name>
labels:
grafana_dashboard: "true"
annotations:
grafana_folder: "Applications"
data:
<app-name>.json: |
{ ... dashboard JSON ... }
详细示例可参考[references/monitoring-patterns.md](references/monitoring-patterns.md)。
---Phase 4: Validate
第四阶段:校验
4.1 Kubernetes Validation
4.1 Kubernetes配置校验
bash
task k8s:validateThis runs:
- kustomize build
- kubeconform schema validation
- yamllint checks
bash
task k8s:validate该命令会执行:
- kustomize build
- kubeconform schema校验
- yamllint检查
4.2 Renovate Validation
4.2 Renovate配置校验
bash
task renovate:validateFix any errors before proceeding.
bash
task renovate:validate继续下一步前请修复所有错误。
Phase 5: Test on Dev
第五阶段:开发集群测试
The dev cluster is a sandbox — iterate freely until the deployment works.
开发集群是沙箱环境,可自由迭代直到部署正常运行。
5.1 Suspend Flux (if needed)
5.1 暂停Flux同步(如需要)
If Flux would reconcile over your changes, suspend the relevant Kustomization:
bash
task k8s:flux-suspend -- <kustomization-name>如果Flux会覆盖你的修改,暂停对应的Kustomization同步:
bash
task k8s:flux-suspend -- <kustomization-name>5.2 Deploy Directly
5.2 直接部署
Install or upgrade the chart directly on dev:
bash
undefined在开发集群上直接安装或升级Chart:
bash
undefinedStandard Helm repo
标准Helm仓库
KUBECONFIG=~/.kube/dev.yaml helm install <app-name> <repo>/<chart>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
KUBECONFIG=~/.kube/dev.yaml helm install <app-name> <repo>/<chart>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
OCI chart
OCI Chart
KUBECONFIG=~/.kube/dev.yaml helm install <app-name> oci://registry/<path>/<chart>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
For iterating on values, use `helm upgrade`:
```bash
KUBECONFIG=~/.kube/dev.yaml helm upgrade <app-name> <repo>/<chart> \
-n <namespace> \
-f kubernetes/platform/charts/<app-name>.yaml \
--version <version>KUBECONFIG=~/.kube/dev.yaml helm install <app-name> oci://registry/<path>/<chart>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
-n <namespace> --create-namespace
-f kubernetes/platform/charts/<app-name>.yaml
--version <version>
迭代values配置时使用`helm upgrade`:
```bash
KUBECONFIG=~/.kube/dev.yaml helm upgrade <app-name> <repo>/<chart> \
-n <namespace> \
-f kubernetes/platform/charts/<app-name>.yaml \
--version <version>5.3 Wait for Pods
5.3 等待Pod启动
bash
KUBECONFIG=~/.kube/dev.yaml kubectl -n <namespace> \
wait --for=condition=Ready pod -l app.kubernetes.io/name=<app-name> --timeout=300sbash
KUBECONFIG=~/.kube/dev.yaml kubectl -n <namespace> \
wait --for=condition=Ready pod -l app.kubernetes.io/name=<app-name> --timeout=300s5.4 Verify Network Connectivity
5.4 验证网络连通性
CRITICAL: Network policies are enforced - verify traffic flows correctly:
bash
undefined重要:网络策略已生效,请验证流量流转正常:
bash
undefinedSetup Hubble access (run once per session)
配置Hubble访问(每个会话执行一次)
KUBECONFIG=~/.kube/dev.yaml kubectl port-forward -n kube-system svc/hubble-relay 4245:80 &
KUBECONFIG=~/.kube/dev.yaml kubectl port-forward -n kube-system svc/hubble-relay 4245:80 &
Check for dropped traffic (should be empty for healthy app)
检查被丢弃的流量(应用健康时应该无输出)
hubble observe --verdict DROPPED --namespace <namespace> --since 5m
hubble observe --verdict DROPPED --namespace <namespace> --since 5m
Verify gateway can reach the app (if exposed)
验证网关可以访问应用(如果已暴露)
hubble observe --from-namespace istio-gateway --to-namespace <namespace> --since 2m
hubble observe --from-namespace istio-gateway --to-namespace <namespace> --since 2m
Verify app can reach database (if using postgres access label)
验证应用可以访问数据库(如果使用了postgres访问标签)
hubble observe --from-namespace <namespace> --to-namespace database --since 2m
**Common issues:**
- Missing profile label → gateway traffic blocked
- Missing access label → database/S3 traffic blocked
- Wrong profile → external API calls blocked (use `internal-egress` or `standard`)hubble observe --from-namespace <namespace> --to-namespace database --since 2m
**常见问题:**
- 缺少配置文件标签 → 网关流量被拦截
- 缺少访问标签 → 数据库/S3流量被拦截
- 配置文件选择错误 → 外部API调用被拦截(使用`internal-egress`或`standard`)5.5 Verify Monitoring
5.5 验证监控配置
Use the helper scripts:
bash
undefined使用辅助脚本:
bash
undefinedCheck deployment health
检查部署健康状态
.claude/skills/deploy-app/scripts/check-deployment-health.sh <namespace> <app-name>
.claude/skills/deploy-app/scripts/check-deployment-health.sh <namespace> <app-name>
Check ServiceMonitor discovery (requires port-forward)
检查ServiceMonitor发现状态(需要开启端口转发)
.claude/skills/deploy-app/scripts/check-servicemonitor.sh <app-name>
.claude/skills/deploy-app/scripts/check-servicemonitor.sh <app-name>
Check no new alerts
检查无新增告警
.claude/skills/deploy-app/scripts/check-alerts.sh
.claude/skills/deploy-app/scripts/check-alerts.sh
Check canary status (if created)
检查金丝雀状态(如果已创建)
.claude/skills/deploy-app/scripts/check-canary.sh <app-name>
undefined.claude/skills/deploy-app/scripts/check-canary.sh <app-name>
undefined5.6 Iterate
5.6 迭代优化
If something isn't right, fix the manifests/values and re-apply. This is the dev sandbox — iterate until it works. Update Helm values, ResourceSet configs, network policy labels, etc. and re-deploy.
如果存在问题,修复清单/values后重新部署。这是开发沙箱,可反复迭代直到正常运行。更新Helm values、ResourceSet配置、网络策略标签等后重新部署即可。
Phase 6: Validate GitOps & PR
第六阶段:GitOps校验与PR提交
6.1 Reconcile and Validate
6.1 同步与校验
Before opening a PR, prove the manifests work through the GitOps path:
bash
undefined提交PR前,验证清单可以通过GitOps路径正常工作:
bash
undefinedUninstall the direct helm install
卸载直接部署的Helm应用
KUBECONFIG=~/.kube/dev.yaml helm uninstall <app-name> -n <namespace>
KUBECONFIG=~/.kube/dev.yaml helm uninstall <app-name> -n <namespace>
Resume Flux and validate clean convergence
恢复Flux同步并验证干净收敛
task k8s:reconcile-validate
If reconciliation fails, fix the manifests and try again. The goal is a clean state where Flux can deploy everything from git.task k8s:reconcile-validate
如果同步失败,修复清单后重试。目标是达到Flux可以从Git部署所有资源的干净状态。6.2 Commit Changes
6.2 提交变更
bash
git add -A
git commit -m "feat(k8s): deploy <app-name> to platform
- Add <app-name> HelmRelease via ResourceSet
- Configure monitoring (ServiceMonitor, alerts)
- Add Renovate manager for version updates
$([ -f kubernetes/platform/config/<app-name>/canary.yaml ] && echo "- Add canary health checks")
$([ -f kubernetes/platform/config/<app-name>/route.yaml ] && echo "- Configure HTTPRoute for ingress")"bash
git add -A
git commit -m "feat(k8s): deploy <app-name> to platform
- Add <app-name> HelmRelease via ResourceSet
- Configure monitoring (ServiceMonitor, alerts)
- Add Renovate manager for version updates
$([ -f kubernetes/platform/config/<app-name>/canary.yaml ] && echo "- Add canary health checks")
$([ -f kubernetes/platform/config/<app-name>/route.yaml ] && echo "- Configure HTTPRoute for ingress")"6.3 Push and Create PR
6.3 推送代码并创建PR
bash
git push -u origin deploy-<app-name>
gh pr create --title "feat(k8s): deploy <app-name>" --body "$(cat <<'EOF'bash
git push -u origin deploy-<app-name>
gh pr create --title "feat(k8s): deploy <app-name>" --body "$(cat <<'EOF'Summary
Summary
- Deploy <app-name> to the Kubernetes platform
- Full monitoring integration (ServiceMonitor + alerts)
- Automated version updates via Renovate
- Deploy <app-name> to the Kubernetes platform
- Full monitoring integration (ServiceMonitor + alerts)
- Automated version updates via Renovate
Test plan
Test plan
- Validated with
task k8s:validate - Tested on dev cluster with direct helm install
- ServiceMonitor targets discovered by Prometheus
- No new alerts firing
- Canary health checks passing (if applicable)
Generated with Claude Code
EOF
)"
undefined- Validated with
task k8s:validate - Tested on dev cluster with direct helm install
- ServiceMonitor targets discovered by Prometheus
- No new alerts firing
- Canary health checks passing (if applicable)
Generated with Claude Code
EOF
)"
undefined6.4 Report PR URL
6.4 返回PR URL
Output the PR URL for the user.
Note: The worktree is intentionally kept until PR is merged. User cleans up with:
bash
task wt:remove -- deploy-<app-name>向用户输出PR URL。
注意:工作树会被保留到PR合并后,用户可通过以下命令清理:
bash
task wt:remove -- deploy-<app-name>Secrets Handling
密钥处理
For detailed secret management workflows including persistent SSM-backed secrets, see the secrets skill.
┌─────────────────────────────────────────────────────────────────────┐
│ Secrets Decision Tree │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ App needs a secret? │
│ │ │
│ ├─ Random/generated (password, API key, encryption key) │
│ │ └─ Use secret-generator annotation: │
│ │ secret-generator.v1.mittwald.de/autogenerate: "key" │
│ │ │
│ ├─ External service (OAuth, third-party API) │
│ │ └─ Create ExternalSecret → AWS SSM │
│ │ Instruct user to add secret to Parameter Store │
│ │ │
│ └─ Unclear which type? │
│ └─ AskUserQuestion: "Can this be randomly generated?" │
│ │
└─────────────────────────────────────────────────────────────────────┘包含持久化SSM-backed密钥的详细密钥管理工作流可参考secrets skill。
┌─────────────────────────────────────────────────────────────────────┐
│ Secrets Decision Tree │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ App needs a secret? │
│ │ │
│ ├─ Random/generated (password, API key, encryption key) │
│ │ └─ Use secret-generator annotation: │
│ │ secret-generator.v1.mittwald.de/autogenerate: "key" │
│ │ │
│ ├─ External service (OAuth, third-party API) │
│ │ └─ Create ExternalSecret → AWS SSM │
│ │ Instruct user to add secret to Parameter Store │
│ │ │
│ └─ Unclear which type? │
│ └─ AskUserQuestion: "Can this be randomly generated?" │
│ │
└─────────────────────────────────────────────────────────────────────┘Auto-Generated Secrets
自动生成密钥
yaml
apiVersion: v1
kind: Secret
metadata:
name: <app-name>-secret
annotations:
secret-generator.v1.mittwald.de/autogenerate: "password,api-key"
type: Opaqueyaml
apiVersion: v1
kind: Secret
metadata:
name: <app-name>-secret
annotations:
secret-generator.v1.mittwald.de/autogenerate: "password,api-key"
type: OpaqueExternal Secrets
外部密钥
yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: <app-name>-secret
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: aws-parameter-store
target:
name: <app-name>-secret
data:
- secretKey: api-token
remoteRef:
key: /homelab/kubernetes/${cluster_name}/<app-name>/api-tokenyaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: <app-name>-secret
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: aws-parameter-store
target:
name: <app-name>-secret
data:
- secretKey: api-token
remoteRef:
key: /homelab/kubernetes/${cluster_name}/<app-name>/api-tokenError Handling
错误处理
| Error | Response |
|---|---|
| No chart found | Suggest app-template, ask user |
| Validation fails | Show error, fix, retry |
| CrashLoopBackOff | Show logs, propose fix, ask user |
| Alerts firing | Show alerts, determine if related, ask user |
| Namespace exists | Ask user: reuse or new name |
| Secret needed | Apply decision tree above |
| Port-forward fails | Check if Prometheus is running in dev |
| Pods rejected by PodSecurity | Missing security context for restricted namespace |
| 错误 | 处理方案 |
|---|---|
| 未找到Chart | 建议使用app-template,询问用户 |
| 校验失败 | 展示错误,修复后重试 |
| CrashLoopBackOff | 展示日志,提出修复方案,询问用户 |
| 告警触发 | 展示告警,判断是否相关,询问用户 |
| 命名空间已存在 | 询问用户:复用还是重命名 |
| 需要密钥 | 参考上方决策树处理 |
| 端口转发失败 | 检查Prometheus是否在开发集群运行 |
| Pod被PodSecurity拒绝 | 受限命名空间缺少安全上下文配置 |
User Interaction Points
用户交互节点
| Phase | Interaction | Purpose |
|---|---|---|
| Research | AskUserQuestion | Present kubesearch findings, confirm chart choice |
| Research | AskUserQuestion | Native helm vs app-template decision |
| Research | AskUserQuestion | Exposure type (internal/external/none) |
| Dev Test | AskUserQuestion | Report test results, confirm PR creation |
| Failure | AskUserQuestion | Report error, propose fix, ask to retry |
| 阶段 | 交互 | 目的 |
|---|---|---|
| 调研 | AskUserQuestion | 呈现kubesearch结果,确认Chart选择 |
| 调研 | AskUserQuestion | 选择原生Helm还是app-template |
| 调研 | AskUserQuestion | 确认暴露类型(内网/公网/不暴露) |
| 开发测试 | AskUserQuestion | 上报测试结果,确认创建PR |
| 失败 | AskUserQuestion | 上报错误,提出修复方案,询问是否重试 |
References
参考文档
- File Templates - Copy-paste templates for all config files
- Monitoring Patterns - ServiceMonitor, PrometheusRule, Canary examples
- flux-gitops skill - ResourceSet patterns
- app-template skill - For apps without native charts
- kubesearch skill - Research workflow
- 文件模板 - 所有配置文件的可复用模板
- 监控模式 - ServiceMonitor、PrometheusRule、Canary示例
- flux-gitops skill - ResourceSet模式
- app-template skill - 无原生Chart的应用处理方案
- kubesearch skill - 调研工作流