init: 폴더구조 설계 및 인프라 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:31:53 +09:00
parent 34ad612281
commit f9c463f87a
1839 changed files with 323096 additions and 1 deletions
@@ -0,0 +1,30 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: identity-postgres-initdb
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
data:
01-create-databases.sh: |
#!/usr/bin/env bash
set -euo pipefail
KEYCLOAK_DB_PASSWORD="$(cat /run/secrets/keycloak-db/password)"
AUTH_SERVER_DB_PASSWORD="$(cat /run/secrets/auth-server-db/SPRING_DATASOURCE_PASSWORD)"
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-'SQL'
CREATE ROLE keycloak LOGIN;
CREATE DATABASE keycloak OWNER keycloak;
CREATE ROLE auth_server LOGIN;
CREATE DATABASE auth_server OWNER auth_server;
SQL
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
-c "ALTER ROLE keycloak PASSWORD '$(printf '%s' "$KEYCLOAK_DB_PASSWORD" | sed "s/'/''/g")';"
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
-c "ALTER ROLE auth_server PASSWORD '$(printf '%s' "$AUTH_SERVER_DB_PASSWORD" | sed "s/'/''/g")';"
@@ -0,0 +1,18 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- serviceaccount.yaml
- configmap-initdb.yaml
- service-headless.yaml
- service.yaml
- statefulset.yaml
labels:
- pairs:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
includeSelectors: false
includeTemplates: true
@@ -0,0 +1,22 @@
apiVersion: v1
kind: Service
metadata:
name: identity-postgres-headless
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
clusterIP: None
selector:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
ports:
- name: postgres
port: 5432
targetPort: postgres
protocol: TCP
appProtocol: postgresql
@@ -0,0 +1,22 @@
apiVersion: v1
kind: Service
metadata:
name: identity-postgres
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
ports:
- name: postgres
port: 5432
targetPort: postgres
protocol: TCP
appProtocol: postgresql
@@ -0,0 +1,12 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: identity-postgres-sa
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
automountServiceAccountToken: false
@@ -0,0 +1,174 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: identity-postgres
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
replicas: 1
serviceName: identity-postgres-headless
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Retain
selector:
matchLabels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
template:
metadata:
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
serviceAccountName: identity-postgres-sa
automountServiceAccountToken: false
terminationGracePeriodSeconds: 60
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
fsGroup: 999
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
containers:
- name: postgres
image: postgres:16.4
imagePullPolicy: IfNotPresent
ports:
- name: postgres
containerPort: 5432
protocol: TCP
env:
- name: POSTGRES_DB
value: postgres
- name: POSTGRES_USER_FILE
value: /run/secrets/superuser/username
- name: POSTGRES_PASSWORD_FILE
value: /run/secrets/superuser/password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: KEYCLOAK_DB_PASSWORD_FILE
value: /run/secrets/keycloak-db/password
- name: AUTH_SERVER_DB_PASSWORD_FILE
value: /run/secrets/auth-server-db/SPRING_DATASOURCE_PASSWORD
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: "1"
memory: 1Gi
startupProbe:
exec:
command:
- sh
- -c
- pg_isready -U "$(cat "$POSTGRES_USER_FILE")"
periodSeconds: 5
failureThreshold: 60
timeoutSeconds: 3
readinessProbe:
exec:
command:
- sh
- -c
- pg_isready -U "$(cat "$POSTGRES_USER_FILE")"
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 3
livenessProbe:
exec:
command:
- sh
- -c
- pg_isready -U "$(cat "$POSTGRES_USER_FILE")"
periodSeconds: 30
failureThreshold: 3
timeoutSeconds: 3
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: initdb
mountPath: /docker-entrypoint-initdb.d
readOnly: true
- name: superuser
mountPath: /run/secrets/superuser
readOnly: true
- name: keycloak-db
mountPath: /run/secrets/keycloak-db
readOnly: true
- name: auth-server-db
mountPath: /run/secrets/auth-server-db
readOnly: true
- name: tmp
mountPath: /tmp
- name: run
mountPath: /var/run/postgresql
volumes:
- name: initdb
configMap:
name: identity-postgres-initdb
defaultMode: 0755
- name: superuser
secret:
secretName: identity-postgres-superuser
defaultMode: 0400
- name: keycloak-db
secret:
secretName: keycloak-db
defaultMode: 0400
- name: auth-server-db
secret:
secretName: auth-server-db
defaultMode: 0400
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 128Mi
- name: run
emptyDir:
medium: Memory
sizeLimit: 64Mi
volumeClaimTemplates:
- metadata:
name: data
labels:
app.kubernetes.io/name: identity-postgres
app.kubernetes.io/instance: identity-postgres
app.kubernetes.io/version: "16.4"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
@@ -0,0 +1,19 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: auth-server-config
labels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
data:
SPRING_PROFILES_ACTIVE: dev
SPRING_DATASOURCE_URL: jdbc:postgresql://identity-postgres:5432/auth_server
APP_DATASOURCE_URL: jdbc:postgresql://identity-postgres:5432/auth_server
MANAGEMENT_SERVER_ADDRESS: 0.0.0.0
MANAGEMENT_SERVER_PORT: "8081"
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: health,prometheus
SERVER_PORT: "8080"
@@ -0,0 +1,128 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-server
labels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
replicas: 1
revisionHistoryLimit: 5
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
template:
metadata:
labels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
serviceAccountName: auth-server-sa
automountServiceAccountToken: false
terminationGracePeriodSeconds: 45
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
containers:
- name: auth-server
image: registry.example.com/auth-platform/auth-server:0.1.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 8081
protocol: TCP
envFrom:
- configMapRef:
name: auth-server-config
- secretRef:
name: auth-server-db
env:
- name: JAVA_TOOL_OPTIONS
value: "-XX:MaxRAMPercentage=75 -XX:+ExitOnOutOfMemoryError"
- name: SPRING_CONFIG_IMPORT
value: "optional:configtree:/etc/secrets/"
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
memory: 768Mi
startupProbe:
httpGet:
path: /actuator/health/liveness
port: metrics
periodSeconds: 5
failureThreshold: 24
timeoutSeconds: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: metrics
periodSeconds: 5
failureThreshold: 3
timeoutSeconds: 2
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: metrics
periodSeconds: 15
failureThreshold: 3
timeoutSeconds: 3
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: db-creds
mountPath: /etc/secrets
readOnly: true
- name: tmp
mountPath: /tmp
volumes:
- name: db-creds
secret:
secretName: auth-server-db
defaultMode: 0400
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 128Mi
@@ -0,0 +1,17 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- serviceaccount.yaml
- configmap.yaml
- deployment.yaml
- service.yaml
labels:
- pairs:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
includeSelectors: false
includeTemplates: true
@@ -0,0 +1,27 @@
apiVersion: v1
kind: Service
metadata:
name: auth-server
labels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
appProtocol: http
- name: metrics
port: 8081
targetPort: metrics
protocol: TCP
appProtocol: http
@@ -0,0 +1,12 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: auth-server-sa
labels:
app.kubernetes.io/name: auth-server
app.kubernetes.io/instance: auth-server
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
automountServiceAccountToken: false
@@ -0,0 +1,113 @@
apiVersion: k8s.keycloak.org/v2beta1
kind: Keycloak
metadata:
name: keycloak
labels:
app.kubernetes.io/name: keycloak
app.kubernetes.io/instance: keycloak
app.kubernetes.io/version: "26.6.1"
app.kubernetes.io/component: identity-provider
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: keycloak-operator
spec:
instances: 2
db:
vendor: postgres
host: identity-postgres
port: 5432
database: keycloak
usernameSecret:
name: keycloak-db-operator
key: username
passwordSecret:
name: keycloak-db-operator
key: password
poolInitialSize: 5
poolMinSize: 5
poolMaxSize: 20
bootstrapAdmin:
user:
secret: keycloak-bootstrap-admin-operator # 어떤 시크릿에서 읽을지 지정하는 거
hostname:
strict: true # 명시된 hostname을 기준으로 URL을 만든다.
backchannelDynamic: false # 백URL도 프론트 hostname과 동일하게 고정한다.
http:
httpEnabled: true
httpPort: 8080
serviceHttpPort: 80
serviceName: keycloak
labels:
app.kubernetes.io/name: keycloak
app.kubernetes.io/instance: keycloak
app.kubernetes.io/component: identity-provider
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: keycloak-operator
proxy:
headers: xforwarded # X-Forwarded-For X-Forwarded-Proto X-Forwarded-Host X-Forwarded-Port 해당 헤더들을 사용하겠다는 의미
ingress:
enabled: false
networkPolicy:
enabled: false
additionalOptions:
- name: cache
value: ispn # 애플리케이션의 캐시 엔진으로 ispn으로 사용
- name: cache-stack
value: jdbc-ping # 클러스터링된 서버끼리 서로를 찾는(Discovery) 방식을 JDBC-PING으로 정한 것
- name: health-enabled
value: "true" # 상태 확인(Health Check) 엔드포인트를 활성화
- name: metrics-enabled
value: "true" # 메트릭(성능 지표) 수집 기능을 켬
- name: log-console-output
value: json # 로그 형식을 JSON 구조로 변경
env:
- name: JAVA_OPTS_APPEND
value: "-XX:MaxRAMPercentage=70 -XX:InitialRAMPercentage=50 -XX:+ExitOnOutOfMemoryError"
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: "2"
memory: 2Gi
scheduling:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/instance: keycloak
app.kubernetes.io/managed-by: keycloak-operator
affinity: # 특정 노드에 다른 pod에 관계에 따라 배치 위치를 결정하는 규칙을 정의한다
podAntiAffinity: # 특정 조건을 만족하는 포드와는 같은 장소에 있지 않는다.
preferredDuringSchedulingIgnoredDuringExecution: # 가급적 지켜줘
- weight: 100 # 가중치가 100임 매우 중요하다고 알림
podAffinityTerm: # 어떤 파드를 피해다닐지
topologyKey: kubernetes.io/hostname # 피할 기준은 호스트 네임으로 설정
labelSelector:
matchLabels:
app.kubernetes.io/instance: keycloak # keycloak과 피하겠다
app.kubernetes.io/managed-by: keycloak-operator # keycloak-operator에 의해 관리되는
unsupported:
podTemplate:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
containers:
- name: keycloak
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
seccompProfile:
type: RuntimeDefault
@@ -0,0 +1,14 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- keycloak.yaml
labels:
- pairs:
app.kubernetes.io/name: keycloak
app.kubernetes.io/instance: keycloak
app.kubernetes.io/version: "26.6.1"
app.kubernetes.io/component: identity-provider
app.kubernetes.io/part-of: auth-platform
app.kubernetes.io/managed-by: kustomize
includeSelectors: false
includeTemplates: true