commit ee24c09708b8996abb9a980b165e4ce29b6ef709 Author: changmin hyeon Date: Fri Oct 31 14:32:16 2025 +0900 init diff --git a/charts/generic/.helmignore b/charts/generic/.helmignore new file mode 100644 index 0000000..1287d3c --- /dev/null +++ b/charts/generic/.helmignore @@ -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 diff --git a/charts/generic/Chart.yaml b/charts/generic/Chart.yaml new file mode 100644 index 0000000..f5512e6 --- /dev/null +++ b/charts/generic/Chart.yaml @@ -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" diff --git a/charts/generic/templates/_helpers.tpl b/charts/generic/templates/_helpers.tpl new file mode 100644 index 0000000..fc86156 --- /dev/null +++ b/charts/generic/templates/_helpers.tpl @@ -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 -}} diff --git a/charts/generic/templates/configmap.yaml b/charts/generic/templates/configmap.yaml new file mode 100644 index 0000000..b3a1e65 --- /dev/null +++ b/charts/generic/templates/configmap.yaml @@ -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 }} diff --git a/charts/generic/templates/deployment.yaml b/charts/generic/templates/deployment.yaml new file mode 100644 index 0000000..2f27a71 --- /dev/null +++ b/charts/generic/templates/deployment.yaml @@ -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 }} diff --git a/charts/generic/templates/hpa.yaml b/charts/generic/templates/hpa.yaml new file mode 100644 index 0000000..5764133 --- /dev/null +++ b/charts/generic/templates/hpa.yaml @@ -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 }} diff --git a/charts/generic/templates/ingress.yaml b/charts/generic/templates/ingress.yaml new file mode 100644 index 0000000..6f4d2b3 --- /dev/null +++ b/charts/generic/templates/ingress.yaml @@ -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 }} diff --git a/charts/generic/templates/networkpolicy.yaml b/charts/generic/templates/networkpolicy.yaml new file mode 100644 index 0000000..2e41d2c --- /dev/null +++ b/charts/generic/templates/networkpolicy.yaml @@ -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 }} diff --git a/charts/generic/templates/pdb.yaml b/charts/generic/templates/pdb.yaml new file mode 100644 index 0000000..61ce8a8 --- /dev/null +++ b/charts/generic/templates/pdb.yaml @@ -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 }} diff --git a/charts/generic/templates/pvc.yaml b/charts/generic/templates/pvc.yaml new file mode 100644 index 0000000..8935a9c --- /dev/null +++ b/charts/generic/templates/pvc.yaml @@ -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 }} diff --git a/charts/generic/templates/secret.yaml b/charts/generic/templates/secret.yaml new file mode 100644 index 0000000..946f77a --- /dev/null +++ b/charts/generic/templates/secret.yaml @@ -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 }} diff --git a/charts/generic/templates/service.yaml b/charts/generic/templates/service.yaml new file mode 100644 index 0000000..81589c6 --- /dev/null +++ b/charts/generic/templates/service.yaml @@ -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 }} diff --git a/charts/generic/templates/serviceaccount.yaml b/charts/generic/templates/serviceaccount.yaml new file mode 100644 index 0000000..cef6fa1 --- /dev/null +++ b/charts/generic/templates/serviceaccount.yaml @@ -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 }} diff --git a/charts/generic/values.yaml b/charts/generic/values.yaml new file mode 100644 index 0000000..1227084 --- /dev/null +++ b/charts/generic/values.yaml @@ -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 -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 ---