This commit is contained in:
changmin hyeon
2025-10-31 14:32:16 +09:00
commit ee24c09708
14 changed files with 478 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
cat > .helmignore <<'EOF'
# VCS / OS
.git/
.gitignore
.DS_Store
Thumbs.db
# Editors / tooling
.vscode/
.idea/
# Node / Python etc.
node_modules/
venv/
__pycache__/
# Helm artifacts
*.prov
Chart.lock
# Archives / backups / dumps
*.tgz
*.tar.gz
*.zip
*.bak
*.tmp
backups/
backup/
dump/
*.dump
*.sql
*.sql.gz
pvcops/
*.sh
# Local files you mentioned
EOF

View File

@@ -0,0 +1,6 @@
apiVersion: v2
name: generic-chart
description: Generic, reusable Helm chart for containerized apps
type: application
version: 1.0.0
appVersion: "1.0"

View File

@@ -0,0 +1,31 @@
{{/* name helper: prefer app.name then chart.name */}}
{{- define "generic.name" -}}
{{- default .Chart.Name .Values.app.name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/* fullname: fullnameOverride > app.fullnameOverride > smart compose (avoid dup) */}}
{{- define "generic.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else if .Values.app.fullnameOverride -}}
{{- .Values.app.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $rel := .Release.Name -}}
{{- $name := (include "generic.name" .) -}}
{{- if eq $rel $name -}}
{{- $name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" $rel $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "generic.labels" -}}
app.kubernetes.io/name: {{ include "generic.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
{{- with .Values.app.podLabels }}
{{ toYaml . }}
{{- end }}
{{- end -}}

View File

@@ -0,0 +1,10 @@
{{- if .Values.configMap.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ default (printf "%s-config" (include "generic.fullname" .)) .Values.configMap.name }}
labels:
{{- include "generic.labels" . | nindent 4 }}
data:
{{- toYaml .Values.configMap.data | nindent 2 }}
{{- end }}

View File

@@ -0,0 +1,146 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "generic.fullname" . }}
labels:
{{- include "generic.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.app.replicas | default 1 }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "generic.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "generic.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.app.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
serviceAccountName: {{ .Values.app.serviceAccountName | default "default" }}
automountServiceAccountToken: true
{{- with .Values.app.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.app.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.app.initContainers }}
initContainers:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
# ---- 메인 컨테이너 (여기서 메인 컨테이너의 모든 속성을 끝까지 적고 닫는다)
- name: {{ include "generic.name" . }}
image: "{{ .Values.app.image.repository }}:{{ .Values.app.image.tag }}"
imagePullPolicy: {{ .Values.app.image.pullPolicy | default "IfNotPresent" }}
{{- with .Values.app.lifecycle }}
lifecycle:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.app.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.app.command }}
command:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.app.args }}
args:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.app.envFrom }}
envFrom:
{{- toYaml .Values.app.envFrom | nindent 12 }}
{{- end }}
{{- with .Values.app.env }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.app.ports }}
ports:
{{- range .Values.app.ports }}
- name: {{ .name }}
containerPort: {{ .containerPort }}
{{- end }}
{{- end }}
{{- if or .Values.app.persistence.enabled .Values.app.extraVolumeMounts }}
volumeMounts:
{{- if .Values.app.persistence.enabled }}
- name: data
mountPath: {{ .Values.app.persistence.mountPath }}
{{- end }}
{{- with .Values.app.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- with .Values.app.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.app.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.app.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
# ---- (여기서) extraContainers를 메인 컨테이너 '형제'로 렌더
{{- with .Values.app.extraContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if or .Values.app.persistence.enabled .Values.app.extraVolumes }}
volumes:
{{- if .Values.app.persistence.enabled }}
{{- $claim := coalesce .Values.app.persistence.existingClaim .Values.app.persistence.name (printf "%s-pvc" (include "generic.fullname" .)) }}
- name: data
persistentVolumeClaim:
claimName: {{ $claim | quote }}
{{- end }}
{{- with .Values.app.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- with .Values.app.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.app.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.app.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.app.terminationGracePeriodSeconds }}
terminationGracePeriodSeconds: {{ . }}
{{- end }}

View File

@@ -0,0 +1,30 @@
{{- if .Values.hpa.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "generic.fullname" . }}
labels:
{{- include "generic.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "generic.fullname" . }}
minReplicas: {{ .Values.hpa.minReplicas }}
maxReplicas: {{ .Values.hpa.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.hpa.cpu.averageUtilization }}
{{- if .Values.hpa.memory.enabled }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.hpa.memory.averageUtilization }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "generic.fullname" . }}
labels:
{{- include "generic.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ include "generic.fullname" $ }}
port:
name: {{ .servicePortName | default "http" }}
{{- end }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if .Values.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "generic.fullname" . }}
labels:
{{- include "generic.labels" . | nindent 4 }}
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: {{ include "generic.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
policyTypes: ["Ingress"]
ingress:
{{- toYaml .Values.networkPolicy.ingress | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,14 @@
{{- if .Values.pdb.enabled }}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "generic.fullname" . }}
labels:
{{- include "generic.labels" . | nindent 4 }}
spec:
minAvailable: {{ .Values.pdb.minAvailable }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "generic.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

View File

@@ -0,0 +1,19 @@
{{- if and .Values.app.persistence.enabled (not .Values.app.persistence.existingClaim) }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ default (printf "%s-pvc" (include "generic.fullname" .)) .Values.app.persistence.name }}
labels:
{{- include "generic.labels" . | nindent 4 }}
spec:
accessModes:
{{- range .Values.app.persistence.accessModes }}
- {{ . }}
{{- end }}
{{- with .Values.app.persistence.storageClass }}
storageClassName: {{ . }}
{{- end }}
resources:
requests:
storage: {{ .Values.app.persistence.size }}
{{- end }}

View File

@@ -0,0 +1,11 @@
{{- if .Values.secret.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ default (printf "%s-secret" (include "generic.fullname" .)) .Values.secret.name }}
labels:
{{- include "generic.labels" . | nindent 4 }}
type: Opaque
stringData:
{{- toYaml .Values.secret.stringData | nindent 2 }}
{{- end }}

View File

@@ -0,0 +1,26 @@
{{- if .Values.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "generic.fullname" . }}
labels:
{{- include "generic.labels" . | nindent 4 }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if ne .Values.service.type "ClusterIP" }}
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | default "Cluster" }}
{{- end }}
selector:
app.kubernetes.io/name: {{ include "generic.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
ports:
{{- range .Values.service.ports }}
- name: {{ .name }}
port: {{ .port }}
targetPort: {{ .targetPort }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,8 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ default (include "generic.fullname" .) .Values.serviceAccount.name }}
labels:
{{- include "generic.labels" . | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,87 @@
controller:
kind: Deployment # Deployment | StatefulSet
app:
name: generic
fullnameOverride: ""
replicas: 1
image:
repository: nginx
tag: "latest"
pullPolicy: IfNotPresent
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
securityContext: {}
env: [] # [{ name: FOO, value: "bar" }]
envFrom: [] # [{ secretRef: { name: mysecret } }, { configMapRef: { name: mycm } }]
ports:
- { name: http, containerPort: 80, servicePort: 80 }
persistence:
enabled: false
existingClaim: ""
name: "" # auto-create PVC name; default <fullname>-pvc
storageClass: "" # e.g. managed-csi / azurefile-csi
accessModes: ["ReadWriteOnce"]
size: 10Gi
mountPath: /data
extraVolumes: [] # e.g. [{ name: extra, persistentVolumeClaim:{ claimName: mypvc }}]
extraVolumeMounts: [] # e.g. [{ name: extra, mountPath: /mnt/extra }]
initContainers: []
sidecars: []
service:
enabled: true
type: ClusterIP
annotations: {}
labels: {}
externalTrafficPolicy: Cluster
ports:
- { name: http, port: 80, targetPort: 80 }
ingress:
enabled: false
className: ""
annotations: {}
hosts: [] # [{ host: example.com, paths: [{ path: /, pathType: Prefix, servicePortName: http }] }]
tls: [] # [{ hosts: [example.com], secretName: example-tls }]
hpa:
enabled: false
minReplicas: 2
maxReplicas: 10
cpu:
averageUtilization: 65
memory:
enabled: false
averageUtilization: 70
pdb:
enabled: false
minAvailable: 1
networkPolicy:
enabled: false
ingress: [] # e.g. [{ from: [{ podSelector: {} }], ports: [{ port: 80, protocol: TCP }] }]
serviceAccount:
create: false
name: ""
configMap:
enabled: false
name: ""
data: {} # key: value
secret:
enabled: false
name: ""
stringData: {} # key: value (not base64)
# --- Example environment-specific files will override this file ---