refactor: 구조 변경

This commit is contained in:
donghyeon-ka
2026-08-28 17:24:26 +09:00
parent a6f6c663e0
commit b8626946b1
192 changed files with 2251 additions and 206 deletions
+23
View File
@@ -0,0 +1,23 @@
# Platform Catalog
클러스터 전체에서 사용하는 addon과 controller의 재사용 구성을 둡니다.
예:
```text
platform/
├── ingress/
├── certificates/
├── external-dns/
├── external-secrets/
├── storage/
├── autoscaling/
└── observability/
```
실제로 사용하는 항목만 만듭니다. 각 component는 자신의 CRD, controller,
configuration과 values/patch를 응집해서 관리합니다. component 간 숨은 의존을
만들지 말고 cluster root 또는 선택한 GitOps controller의 ordering 기능으로
순서를 표현합니다.
새 component는 `_template`을 복사해 시작합니다.
+21
View File
@@ -0,0 +1,21 @@
# __REPLACE_ME_PLATFORM_COMPONENT_NAME__
## 책임
이 component가 소유하는 CRD, controller와 configuration을 적습니다.
## 의존성
선행 component, namespace, identity와 최소 Kubernetes version을 적습니다.
## 구성
- `base`: 모든 대상에서 공유하는 기본값
- `overlays`: 환경/규모별 차이가 실제로 있을 때만 추가
Helm을 사용하면 chart source/version, values와 release 리소스를 이 component
안에 함께 둡니다. 원격 version은 고정합니다.
## 운영
upgrade 순서, health check, rollback과 uninstall 영향을 runbook으로 연결합니다.
+7
View File
@@ -0,0 +1,7 @@
# Base
환경과 클러스터를 모르는 재사용 가능한 기본 manifest만 둡니다.
- 실제 domain, account ID, credential을 하드코딩하지 않습니다.
- resource request/limit와 security context의 안전한 기본값을 둡니다.
- 환경 차이는 `overlays`에서 patch합니다.
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: []
@@ -0,0 +1,7 @@
# Overlays
공통 base와 다른 값이 있을 때만 `<environment-or-profile>/` overlay를 만듭니다.
overlay는 base를 참조하고 patch만 포함해야 합니다.
`dev`, `prod` 전체 manifest 복사보다 replica, resource, retention처럼 실제로
달라지는 항목만 표현합니다.
@@ -0,0 +1,8 @@
# Argo CD control plane
Permission-scoped AppProject와 list-generated ApplicationSet inventory를
소유합니다. Bootstrap root는 이 경로를 직접 source로 사용하지 않고
`gitops/clusters/dev-k3s`를 통해 조립합니다.
새 inventory 항목은 `autoSync: "false"`로 시작하며 project, repository와
revision trust boundary를 template하지 않습니다.
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- platform-addons.yaml
- platform-services.yaml
- systems.yaml
- workloads.yaml
@@ -0,0 +1,122 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: platform-addons
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-5"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
spec:
goTemplate: true
goTemplateOptions:
- missingkey=error
generators:
- list:
elements:
- component: sealed-secrets
cluster: dev-k3s
server: https://kubernetes.default.svc
namespace: kube-system
repoURL: https://bitnami.github.io/sealed-secrets
chart: sealed-secrets
# renovate: datasource=helm depName=sealed-secrets registryUrl=https://bitnami.github.io/sealed-secrets
revision: 2.17.9
autoSync: "true"
helmValues: |
fullnameOverride: sealed-secrets-controller
keyrenewperiod: 720h
image:
# renovate: datasource=docker depName=bitnami/sealed-secrets-controller
repository: bitnami/sealed-secrets-controller
tag: "0.33.1@sha256:e7fad65c2d2f47e48d9ca17408ed56961bfa6a6dd74ccd4a1a214664156534bc"
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 250m
memory: 256Mi
- component: vault-agent-injector
cluster: dev-k3s
server: https://kubernetes.default.svc
namespace: vault
repoURL: https://helm.releases.hashicorp.com
chart: vault
# renovate: datasource=helm depName=vault registryUrl=https://helm.releases.hashicorp.com
revision: 0.32.0
autoSync: "false"
helmValues: |
global:
externalVaultAddr: http://vault.vault.svc.cluster.local:8200
tlsDisable: true
server:
enabled: false
injector:
enabled: true
authPath: auth/kubernetes
image:
# renovate: datasource=docker depName=hashicorp/vault-k8s
repository: hashicorp/vault-k8s
tag: "1.7.2@sha256:ae3d307658b72a1cf35dab9bdf92c995d45cdc7183af0516857714b5bd0ba84d"
webhook:
failurePolicy: Fail
namespaceSelector:
matchLabels:
vault-injection: enabled
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
agentImage:
# renovate: datasource=docker depName=hashicorp/vault
repository: hashicorp/vault
tag: "1.18.5@sha256:750bb37c1638fa194ab37053a81618c61bb0491ddec6fccac87c07a8e6cd8166"
template:
metadata:
name: "{{ .component }}-{{ .cluster }}"
annotations:
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
project-gitops.io/auto-sync-gate: "{{ .autoSync }}"
labels:
project-gitops.io/cluster: "{{ .cluster }}"
project-gitops.io/owner: platform
spec:
project: platform-addons
source:
repoURL: "{{ .repoURL }}"
chart: "{{ .chart }}"
targetRevision: "{{ .revision }}"
helm:
values: "{{ .helmValues }}"
destination:
server: "{{ .server }}"
namespace: "{{ .namespace }}"
syncPolicy:
syncOptions:
- CreateNamespace=true
- Prune=confirm
- PruneLast=true
- FailOnSharedResource=true
retry:
limit: 5
refresh: true
backoff:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 5
templatePatch: |
{{- if eq .autoSync "true" }}
spec:
syncPolicy:
automated:
enabled: true
prune: true
selfHeal: true
{{- end }}
syncPolicy:
applicationsSync: create-update
preserveResourcesOnDeletion: true
@@ -0,0 +1,64 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: platform-services
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-5"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
spec:
goTemplate: true
goTemplateOptions:
- missingkey=error
generators:
- list:
elements:
- component: vault
cluster: dev-k3s
server: https://kubernetes.default.svc
namespace: vault
path: gitops/clusters/dev-k3s/overlays/platform/vault
autoSync: "true"
template:
metadata:
name: "{{ .component }}-{{ .cluster }}"
annotations:
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
project-gitops.io/auto-sync-gate: "{{ .autoSync }}"
labels:
project-gitops.io/cluster: "{{ .cluster }}"
project-gitops.io/owner: platform
spec:
project: platform-services
source:
repoURL: https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops
targetRevision: main
path: "{{ .path }}"
destination:
server: "{{ .server }}"
namespace: "{{ .namespace }}"
syncPolicy:
syncOptions:
- CreateNamespace=true
- PruneLast=true
- FailOnSharedResource=true
retry:
limit: 5
refresh: true
backoff:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 5
templatePatch: |
{{- if eq .autoSync "true" }}
spec:
syncPolicy:
automated:
enabled: true
prune: true
selfHeal: true
{{- end }}
syncPolicy:
applicationsSync: create-update
preserveResourcesOnDeletion: true
@@ -0,0 +1,64 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: systems
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-5"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
spec:
goTemplate: true
goTemplateOptions:
- missingkey=error
generators:
- list:
elements:
- component: auth-system
cluster: dev-k3s
server: https://kubernetes.default.svc
namespace: auth-system-dev
path: gitops/clusters/dev-k3s/overlays/systems/auth-system
autoSync: "false"
template:
metadata:
name: "{{ .component }}-{{ .cluster }}"
annotations:
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
project-gitops.io/auto-sync-gate: "{{ .autoSync }}"
labels:
project-gitops.io/cluster: "{{ .cluster }}"
project-gitops.io/owner: systems
spec:
project: systems
source:
repoURL: https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops
targetRevision: main
path: "{{ .path }}"
destination:
server: "{{ .server }}"
namespace: "{{ .namespace }}"
syncPolicy:
syncOptions:
- CreateNamespace=true
- PruneLast=true
- FailOnSharedResource=true
retry:
limit: 5
refresh: true
backoff:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 5
templatePatch: |
{{- if eq .autoSync "true" }}
spec:
syncPolicy:
automated:
enabled: true
prune: true
selfHeal: true
{{- end }}
syncPolicy:
applicationsSync: create-update
preserveResourcesOnDeletion: true
@@ -0,0 +1,70 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: workloads
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-5"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
spec:
goTemplate: true
goTemplateOptions:
- missingkey=error
generators:
- list:
elements:
- component: auth-server
cluster: dev-k3s
server: https://kubernetes.default.svc
namespace: auth-dev
path: gitops/clusters/dev-k3s/overlays/workloads/auth-server
autoSync: "false"
- component: api-server
cluster: dev-k3s
server: https://kubernetes.default.svc
namespace: api-dev
path: gitops/clusters/dev-k3s/overlays/workloads/api-server
autoSync: "false"
template:
metadata:
name: "{{ .component }}-{{ .cluster }}"
annotations:
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
project-gitops.io/auto-sync-gate: "{{ .autoSync }}"
labels:
project-gitops.io/cluster: "{{ .cluster }}"
project-gitops.io/owner: workloads
spec:
project: workloads
source:
repoURL: https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops
targetRevision: main
path: "{{ .path }}"
destination:
server: "{{ .server }}"
namespace: "{{ .namespace }}"
syncPolicy:
syncOptions:
- CreateNamespace=true
- PruneLast=true
- FailOnSharedResource=true
retry:
limit: 5
refresh: true
backoff:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 5
templatePatch: |
{{- if eq .autoSync "true" }}
spec:
syncPolicy:
automated:
enabled: true
prune: true
selfHeal: true
{{- end }}
syncPolicy:
applicationsSync: create-update
preserveResourcesOnDeletion: true
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- projects
- application-sets
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- platform-addons.yaml
- platform-services.yaml
- systems.yaml
- workloads.yaml
@@ -0,0 +1,50 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: platform-addons
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-10"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
description: Cluster-scoped controllers installed from approved Helm repositories
sourceRepos:
- https://bitnami.github.io/sealed-secrets
- https://helm.releases.hashicorp.com
destinations:
- namespace: kube-system
server: https://kubernetes.default.svc
- namespace: vault
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
- group: apiextensions.k8s.io
kind: CustomResourceDefinition
- group: rbac.authorization.k8s.io
kind: ClusterRole
- group: rbac.authorization.k8s.io
kind: ClusterRoleBinding
- group: admissionregistration.k8s.io
kind: MutatingWebhookConfiguration
namespaceResourceWhitelist:
- group: ""
kind: ConfigMap
- group: ""
kind: Secret
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: policy
kind: PodDisruptionBudget
- group: rbac.authorization.k8s.io
kind: Role
- group: rbac.authorization.k8s.io
kind: RoleBinding
orphanedResources:
warn: true
@@ -0,0 +1,37 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: platform-services
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-10"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
description: Shared services owned by this standalone reference platform
sourceRepos:
- https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops
destinations:
- namespace: vault
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
- group: rbac.authorization.k8s.io
kind: ClusterRoleBinding
namespaceResourceWhitelist:
- group: ""
kind: ConfigMap
- group: ""
kind: PersistentVolumeClaim
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: networking.k8s.io
kind: NetworkPolicy
orphanedResources:
warn: true
@@ -0,0 +1,39 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: systems
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-10"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
description: Backing systems dedicated to an example product boundary
sourceRepos:
- https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops
destinations:
- namespace: auth-system-dev
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceWhitelist:
- group: ""
kind: ConfigMap
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: apps
kind: StatefulSet
- group: batch
kind: Job
- group: networking.k8s.io
kind: Ingress
- group: networking.k8s.io
kind: NetworkPolicy
orphanedResources:
warn: true
@@ -0,0 +1,41 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: workloads
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-10"
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
description: First-party application workloads
sourceRepos:
- https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops
destinations:
- namespace: auth-dev
server: https://kubernetes.default.svc
- namespace: api-dev
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceWhitelist:
- group: ""
kind: ConfigMap
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: bitnami.com
kind: SealedSecret
- group: apps
kind: Deployment
- group: batch
kind: Job
- group: networking.k8s.io
kind: Ingress
- group: networking.k8s.io
kind: NetworkPolicy
orphanedResources:
warn: true
@@ -0,0 +1,8 @@
# Vault shared service
여러 system이 소비하는 dev Vault service의 Kubernetes base입니다. Namespace,
single-node profile과 NetworkPolicy는
`gitops/clusters/dev-k3s/overlays/platform/vault`에서 결합합니다.
Vault API object는 이 경로가 아니라 `infrastructure/live/dev-k3s`의 세
Terraform state가 소유합니다.
@@ -0,0 +1,13 @@
ui = true
disable_mlock = true
listener "tcp" {
address = "0.0.0.0:8200"
cluster_address = "0.0.0.0:8201"
tls_disable = 1
}
storage "raft" {
path = "/vault/data"
node_id = "vault-0"
}
@@ -0,0 +1,14 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- vault-serviceaccount.yaml
- vault-auth-delegator.clusterrolebinding.yaml
- vault-pvc.yaml
- vault-service.yaml
- vault-deployment.yaml
configMapGenerator:
- name: vault-config
files:
- files/vault/vault.hcl
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-server-auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-server
namespace: vault
@@ -0,0 +1,91 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: vault
template:
metadata:
labels:
app: vault
spec:
serviceAccountName: vault-server
containers:
- name: vault
image: hashicorp/vault:1.18.5@sha256:750bb37c1638fa194ab37053a81618c61bb0491ddec6fccac87c07a8e6cd8166
command:
- /bin/sh
- -ec
env:
- name: VAULT_ADDR
value: http://127.0.0.1:8200
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: VAULT_API_ADDR
value: http://$(POD_IP):8200
- name: VAULT_CLUSTER_ADDR
value: http://$(POD_IP):8201
args:
- |
cp /vault/config/vault.hcl /tmp/vault.hcl
exec vault server -config=/tmp/vault.hcl
ports:
- containerPort: 8200
name: http
- containerPort: 8201
name: cluster
volumeMounts:
- name: vault-config
mountPath: /vault/config
readOnly: true
- name: vault-data
mountPath: /vault/data
readinessProbe:
exec:
command:
- sh
- -c
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1; code=$?; [ "$code" -eq 0 ] || [ "$code" -eq 2 ]
initialDelaySeconds: 20
periodSeconds: 15
timeoutSeconds: 5
startupProbe:
exec:
command:
- sh
- -c
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1; code=$?; [ "$code" -eq 0 ] || [ "$code" -eq 2 ]
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 30
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: vault-config
configMap:
name: vault-config
defaultMode: 0555
- name: vault-data
persistentVolumeClaim:
claimName: vault-data
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vault-data
annotations:
argocd.argoproj.io/sync-options: Prune=confirm,Delete=confirm
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: vault
spec:
selector:
app: vault
ports:
- name: http
port: 8200
targetPort: 8200
- name: cluster
port: 8201
targetPort: 8201
type: ClusterIP
@@ -0,0 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-server