All skills
Skillintermediate
CRD Patterns and Examples
Common Custom Resource Definition patterns and examples for Helm charts.
Claude Code Knowledge Pack7/10/2026
Overview
CRD Patterns and Examples
Common Custom Resource Definition patterns and examples for Helm charts.
Table of Contents
- cert-manager
- Prometheus Operator
- Istio
- ArgoCD
- Sealed Secrets
- External Secrets Operator
- Gateway API
- KEDA
- VerticalPodAutoscaler (VPA)
cert-manager
Certificate Resource
File: templates/certificate.yaml
{{- if .Values.certificate.enabled }}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "mychart.fullname" . }}-tls
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
secretName: {{ include "mychart.fullname" . }}-tls
issuerRef:
name: {{ .Values.certificate.issuer.name }}
kind: {{ .Values.certificate.issuer.kind | default "ClusterIssuer" }}
{{- with .Values.certificate.issuer.group }}
group: {{ . }}
{{- end }}
commonName: {{ .Values.certificate.commonName | default (first .Values.certificate.dnsNames) }}
dnsNames:
{{- range .Values.certificate.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- with .Values.certificate.ipAddresses }}
ipAddresses:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.uris }}
uris:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.duration }}
duration: {{ . }}
{{- end }}
{{- with .Values.certificate.renewBefore }}
renewBefore: {{ . }}
{{- end }}
{{- with .Values.certificate.usages }}
usages:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.privateKey }}
privateKey:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.keystores }}
keystores:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Corresponding values.yaml:
certificate:
enabled: false
issuer:
name: letsencrypt-prod
kind: ClusterIssuer
group: cert-manager.io
commonName: ""
dnsNames:
- example.com
- www.example.com
ipAddresses: []
uris: []
duration: 2160h # 90 days
renewBefore: 360h # 15 days
usages:
- digital signature
- key encipherment
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
rotationPolicy: Never
keystores: {}
# keystores:
# jks:
# create: true
# passwordSecretRef:
# name: jks-password
# key: password
ClusterIssuer Resource
File: templates/clusterissuer.yaml
{{- if .Values.certManager.clusterIssuer.create }}
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: {{ .Values.certManager.clusterIssuer.name }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
{{- if eq .Values.certManager.clusterIssuer.type "acme" }}
acme:
server: {{ .Values.certManager.clusterIssuer.acme.server }}
email: {{ required "certManager.clusterIssuer.acme.email is required!" .Values.certManager.clusterIssuer.acme.email }}
privateKeySecretRef:
name: {{ .Values.certManager.clusterIssuer.acme.privateKeySecretName }}
solvers:
{{- range .Values.certManager.clusterIssuer.acme.solvers }}
- {{ toYaml . | nindent 6 }}
{{- end }}
{{- else if eq .Values.certManager.clusterIssuer.type "ca" }}
ca:
secretName: {{ .Values.certManager.clusterIssuer.ca.secretName }}
{{- else if eq .Values.certManager.clusterIssuer.type "selfSigned" }}
selfSigned: {}
{{- end }}
{{- end }}
Corresponding values.yaml:
certManager:
clusterIssuer:
create: false
name: letsencrypt-prod
type: acme # acme, ca, selfSigned, vault, venafi
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretName: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginx
# - dns01:
# cloudflare:
# email: admin@example.com
# apiTokenSecretRef:
# name: cloudflare-api-token
# key: api-token
ca:
secretName: ca-key-pair
Prometheus Operator
ServiceMonitor Resource
File: templates/servicemonitor.yaml
{{- if .Values.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.metrics.serviceMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
endpoints:
- port: {{ .Values.metrics.serviceMonitor.port | default "metrics" }}
{{- with .Values.metrics.serviceMonitor.interval }}
interval: {{ . }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ . }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.path }}
path: {{ . }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.scheme }}
scheme: {{ . }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.tlsConfig }}
tlsConfig:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.relabelings }}
relabelings:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.metricRelabelings }}
metricRelabelings:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.namespaceSelector }}
namespaceSelector:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Corresponding values.yaml:
metrics:
enabled: true
port: 9090
serviceMonitor:
enabled: false
labels: {}
annotations: {}
port: metrics
interval: 30s
scrapeTimeout: 10s
path: /metrics
scheme: http
tlsConfig: {}
relabelings: []
metricRelabelings: []
namespaceSelector: {}
PrometheusRule Resource
File: templates/prometheusrule.yaml
{{- if .Values.metrics.prometheusRule.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.metrics.prometheusRule.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
groups:
{{- range .Values.metrics.prometheusRule.groups }}
- name: {{ .name }}
{{- with .interval }}
interval: {{ . }}
{{- end }}
rules:
{{- range .rules }}
- alert: {{ .alert }}
expr: {{ .expr }}
{{- with .for }}
for: {{ . }}
{{- end }}
{{- with .labels }}
labels:
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
{{- range $key, $value := .annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
Corresponding values.yaml:
metrics:
prometheusRule:
enabled: false
labels: {}
groups:
- name: mychart-alerts
interval: 30s
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 10m
labels:
severity: warning
annotations:
summary: "High error rate detected"
description: "Error rate is {{ $value }} errors per second"
- alert: PodDown
expr: up{job="mychart"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Pod is down"
description: "Pod {{ $labels.pod }} is down"
Istio
VirtualService Resource
File: templates/virtualservice.yaml
{{- if .Values.istio.virtualService.enabled }}
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
hosts:
{{- range .Values.istio.virtualService.hosts }}
- {{ . | quote }}
{{- end }}
{{- with .Values.istio.virtualService.gateways }}
gateways:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.istio.virtualService.http }}
http:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.istio.virtualService.tcp }}
tcp:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.istio.virtualService.tls }}
tls:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Corresponding values.yaml:
istio:
virtualService:
enabled: false
hosts:
- example.com
gateways:
- istio-system/gateway
http:
- match:
- uri:
prefix: /api
route:
- destination:
host: mychart-svc
port:
number: 80
weight: 90
- destination:
host: mychart-svc-canary
port:
number: 80
weight: 10
timeout: 30s
retries:
attempts: 3
perTryTimeout: 10s
tcp: []
tls: []
Gateway Resource
File: templates/gateway.yaml
{{- if .Values.istio.gateway.enabled }}
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
selector:
{{- toYaml .Values.istio.gateway.selector | nindent 4 }}
servers:
{{- range .Values.istio.gateway.servers }}
- port:
number: {{ .port.number }}
name: {{ .port.name }}
protocol: {{ .port.protocol }}
hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
{{- with .tls }}
tls:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- end }}
{{- end }}
Corresponding values.yaml:
istio:
gateway:
enabled: false
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- example.com
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- example.com
tls:
mode: SIMPLE
credentialName: example-com-tls
DestinationRule Resource
File: templates/destinationrule.yaml
{{- if .Values.istio.destinationRule.enabled }}
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
host: {{ .Values.istio.destinationRule.host | default (include "mychart.fullname" .) }}
{{- with .Values.istio.destinationRule.trafficPolicy }}
trafficPolicy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.istio.destinationRule.subsets }}
subsets:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Corresponding values.yaml:
istio:
destinationRule:
enabled: false
host: mychart-svc
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
http2MaxRequests: 100
loadBalancer:
simple: LEAST_REQUEST
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
ArgoCD
Application Resource
File: templates/argocd-application.yaml
{{- if .Values.argocd.application.enabled }}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: {{ include "mychart.fullname" . }}
namespace: {{ .Values.argocd.application.namespace | default "argocd" }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.argocd.application.finalizers }}
finalizers:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
project: {{ .Values.argocd.application.project | default "default" }}
source:
repoURL: {{ required "argocd.application.source.repoURL is required!" .Values.argocd.application.source.repoURL }}
targetRevision: {{ .Values.argocd.application.source.targetRevision | default "HEAD" }}
path: {{ .Values.argocd.application.source.path }}
{{- with .Values.argocd.application.source.helm }}
helm:
{{- toYaml . | nindent 6 }}
{{- end }}
destination:
server: {{ .Values.argocd.application.destination.server | default "https://kubernetes.default.svc" }}
namespace: {{ .Values.argocd.application.destination.namespace | default .Release.Namespace }}
syncPolicy:
{{- with .Values.argocd.application.syncPolicy }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.argocd.application.ignoreDifferences }}
ignoreDifferences:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Corresponding values.yaml:
argocd:
application:
enabled: false
namespace: argocd
project: default
finalizers:
- resources-finalizer.argocd.argoproj.io
source:
repoURL: https://github.com/example/repo
targetRevision: main
path: charts/mychart
helm:
releaseName: mychart
valueFiles:
- values.yaml
values: ""
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
ignoreDifferences: []
AppProject Resource
File: templates/argocd-appproject.yaml
{{- if .Values.argocd.appProject.enabled }}
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: {{ .Values.argocd.appProject.name }}
namespace: {{ .Values.argocd.appProject.namespace | default "argocd" }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.argocd.appProject.finalizers }}
finalizers:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
description: {{ .Values.argocd.appProject.description }}
sourceRepos:
{{- range .Values.argocd.appProject.sourceRepos }}
- {{ . | quote }}
{{- end }}
destinations:
{{- range .Values.argocd.appProject.destinations }}
- namespace: {{ .namespace }}
server: {{ .server }}
{{- end }}
{{- with .Values.argocd.appProject.clusterResourceWhitelist }}
clusterResourceWhitelist:
{{- toYaml . | nindent 4 }}
{{-