refactor: 폴더 구조 변경
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# gitops/apps AGENTS
|
||||
|
||||
Application-owned workloads, stateful dependencies, and independently runnable
|
||||
operations live here. Keep environment-neutral manifests in each unit's `base`.
|
||||
Ingress hosts, image rollout references, environment labels, storage classes,
|
||||
retention, and Secret delivery differences belong in `overlays/<env>`.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Application Deployment Catalog
|
||||
|
||||
애플리케이션의 source code가 아니라 Kubernetes 배포 정의를 둡니다. app 팀이
|
||||
별도 source/deploy 저장소를 소유하면 이곳에는 immutable artifact를 참조하는
|
||||
GitOps 리소스만 둘 수 있습니다.
|
||||
|
||||
```text
|
||||
apps/
|
||||
└── example-api/
|
||||
├── base/
|
||||
└── overlays/
|
||||
├── dev/
|
||||
└── prod/
|
||||
```
|
||||
|
||||
base는 환경을 모르고, overlay에는 replica/resource/config처럼 필요한 차이만
|
||||
둡니다. image는 mutable tag 대신 조직 정책에 따른 고정 tag 또는 digest를
|
||||
사용합니다.
|
||||
@@ -0,0 +1,22 @@
|
||||
# __REPLACE_ME_APPLICATION_NAME__
|
||||
|
||||
## 소유자
|
||||
|
||||
Team: __REPLACE_ME_OWNER__
|
||||
|
||||
repository와 on-call 정보를 적습니다.
|
||||
|
||||
## 배포 계약
|
||||
|
||||
- Namespace:
|
||||
- Image/artifact source:
|
||||
- Ports/protocol:
|
||||
- Dependency:
|
||||
- SLO/alerts:
|
||||
|
||||
## 구성
|
||||
|
||||
- `base`: 공통 Kubernetes 배포 정의
|
||||
- `overlays`: 환경별 replica, resource, config 차이
|
||||
|
||||
비밀은 ExternalSecret 같은 참조 또는 승인된 암호화 형식으로만 추가합니다.
|
||||
@@ -0,0 +1,4 @@
|
||||
# Base
|
||||
|
||||
환경을 모르는 application의 공통 manifest를 둡니다. namespace 자체의 소유권이
|
||||
tenant catalog에 있다면 이곳에서 중복 생성하지 않습니다.
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources: []
|
||||
@@ -0,0 +1,6 @@
|
||||
# Overlays
|
||||
|
||||
필요한 환경에만 overlay를 추가합니다. 각 overlay는 `../../base`를 참조하고
|
||||
환경별 patch만 포함합니다.
|
||||
|
||||
비밀값, 임시 debug 설정과 수동 hotfix 결과를 overlay에 커밋하지 않습니다.
|
||||
@@ -0,0 +1,5 @@
|
||||
# gitops/apps/auth-migration AGENTS
|
||||
|
||||
Jobs and CronJobs live here. Operations are versioned, independently runnable
|
||||
units and must not be hidden inside an application base. Define completion,
|
||||
retry, timeout, rollback, and rerun semantics before changing them.
|
||||
@@ -0,0 +1,80 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: auth-server-migrate-sql
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/component: migration
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
data:
|
||||
V1__create_users_table.sql: |
|
||||
create schema if not exists auth;
|
||||
|
||||
create or replace function auth.set_updated_at()
|
||||
returns trigger as $$
|
||||
begin
|
||||
new.updated_at := current_timestamp;
|
||||
return new;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
create table auth.users (
|
||||
id uuid not null,
|
||||
email text not null,
|
||||
encoded_password text not null,
|
||||
name text not null,
|
||||
provider text not null,
|
||||
created_at timestamp with time zone not null default current_timestamp,
|
||||
updated_at timestamp with time zone not null default current_timestamp,
|
||||
constraint pk_users primary key (id),
|
||||
constraint uq_users__email unique (email),
|
||||
constraint ck_users__provider check (provider in ('LOCAL', 'GOOGLE', 'GITHUB'))
|
||||
);
|
||||
|
||||
create index ix_users__created_at on auth.users (created_at);
|
||||
|
||||
create trigger trg_users__set_updated_at
|
||||
before update on auth.users
|
||||
for each row
|
||||
when (old.* is distinct from new.*)
|
||||
execute function auth.set_updated_at();
|
||||
V2__add_oauth_login_columns.sql: |
|
||||
alter table auth.users alter column encoded_password drop not null;
|
||||
|
||||
alter table auth.users add column provider_subject text;
|
||||
|
||||
alter table auth.users
|
||||
add constraint uq_users__provider_provider_subject unique (provider, provider_subject);
|
||||
V3__add_user_provider_field_constraints.sql: |
|
||||
alter table auth.users
|
||||
add constraint ck_users__local_password_required
|
||||
check (
|
||||
(provider = 'LOCAL' and encoded_password is not null and provider_subject is null)
|
||||
or (provider <> 'LOCAL')
|
||||
);
|
||||
|
||||
alter table auth.users
|
||||
add constraint ck_users__social_subject_required
|
||||
check (
|
||||
(provider <> 'LOCAL' and provider_subject is not null and encoded_password is null)
|
||||
or (provider = 'LOCAL')
|
||||
);
|
||||
V4__add_keycloak_provider.sql: |
|
||||
alter table auth.users drop constraint ck_users__provider;
|
||||
|
||||
alter table auth.users
|
||||
add constraint ck_users__provider check (provider in ('LOCAL', 'KEYCLOAK', 'GOOGLE', 'GITHUB'));
|
||||
V5__keycloak_only_provider.sql: |
|
||||
alter table auth.users drop constraint if exists ck_users__local_password_required;
|
||||
alter table auth.users drop constraint if exists ck_users__social_subject_required;
|
||||
alter table auth.users drop constraint if exists ck_users__provider;
|
||||
|
||||
alter table auth.users drop column if exists encoded_password;
|
||||
|
||||
alter table auth.users alter column provider_subject set not null;
|
||||
|
||||
alter table auth.users
|
||||
add constraint ck_users__provider check (provider = 'KEYCLOAK');
|
||||
@@ -0,0 +1,119 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: auth-server-migrate-0-1-0
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/component: migration
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
parallelism: 1
|
||||
completions: 1
|
||||
backoffLimit: 0
|
||||
activeDeadlineSeconds: 1800
|
||||
ttlSecondsAfterFinished: 86400
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/component: migration
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
serviceAccountName: auth-server-migrate-sa
|
||||
automountServiceAccountToken: false
|
||||
restartPolicy: Never
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
initContainers:
|
||||
- name: flyway-info
|
||||
image: flyway/flyway:10.20.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["/bin/sh", "-c"]
|
||||
args: ["FLYWAY_USER=\"$(cat /run/secrets/db/SPRING_DATASOURCE_USERNAME)\" FLYWAY_PASSWORD=\"$(cat /run/secrets/db/SPRING_DATASOURCE_PASSWORD)\" exec /flyway/flyway info"]
|
||||
env: &flywayEnv
|
||||
- name: FLYWAY_URL
|
||||
value: jdbc:postgresql://identity-postgres:5432/auth_server
|
||||
- name: FLYWAY_LOCATIONS
|
||||
value: filesystem:/flyway/sql
|
||||
- name: FLYWAY_SCHEMAS
|
||||
value: auth
|
||||
- name: FLYWAY_DEFAULT_SCHEMA
|
||||
value: auth
|
||||
- name: FLYWAY_TABLE
|
||||
value: flyway_schema_history
|
||||
- name: FLYWAY_VALIDATE_ON_MIGRATE
|
||||
value: "true"
|
||||
- name: FLYWAY_BASELINE_ON_MIGRATE
|
||||
value: "false"
|
||||
- name: FLYWAY_OUT_OF_ORDER
|
||||
value: "false"
|
||||
- name: FLYWAY_MIXED
|
||||
value: "false"
|
||||
- name: FLYWAY_CLEAN_DISABLED
|
||||
value: "true"
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
securityContext: &flywaySC
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
volumeMounts: &flywayVM
|
||||
- name: sql
|
||||
mountPath: /flyway/sql
|
||||
readOnly: true
|
||||
- name: db-secret
|
||||
mountPath: /run/secrets/db
|
||||
readOnly: true
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
containers:
|
||||
- name: flyway-migrate
|
||||
image: flyway/flyway:10.20.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["/bin/sh", "-c"]
|
||||
args: ["FLYWAY_USER=\"$(cat /run/secrets/db/SPRING_DATASOURCE_USERNAME)\" FLYWAY_PASSWORD=\"$(cat /run/secrets/db/SPRING_DATASOURCE_PASSWORD)\" exec /flyway/flyway migrate"]
|
||||
env: *flywayEnv
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
memory: 512Mi
|
||||
securityContext: *flywaySC
|
||||
volumeMounts: *flywayVM
|
||||
volumes:
|
||||
- name: sql
|
||||
configMap:
|
||||
name: auth-server-migrate-sql
|
||||
- name: db-secret
|
||||
secret:
|
||||
secretName: auth-server-db
|
||||
defaultMode: 0400
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 128Mi
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- serviceaccount.yaml
|
||||
- configmap-sql.yaml
|
||||
- job.yaml
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/component: migration
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: auth-server-migrate-sa
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/component: migration
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
automountServiceAccountToken: false
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- networkpolicy.yaml
|
||||
@@ -0,0 +1,26 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: auth-server-migrate-egress-postgres
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
app.kubernetes.io/component: migration
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: identity-postgres
|
||||
app.kubernetes.io/instance: identity-postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
@@ -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,27 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
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
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
traefik.ingress.kubernetes.io/router.middlewares: kube-system-security-headers@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: auth.local.test
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: auth-server
|
||||
port:
|
||||
name: http
|
||||
@@ -0,0 +1,40 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- ingress.yaml
|
||||
- networkpolicy.yaml
|
||||
|
||||
images:
|
||||
- name: registry.example.com/auth-platform/auth-server
|
||||
newName: registry.project.com/auth-platform/auth-server
|
||||
newTag: manual-20260512071751
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: ConfigMap
|
||||
name: auth-server-config
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /data/APP_SECURITY_KEYCLOAK_ISSUER_URI
|
||||
value: http://keycloak.local.test/realms/platform
|
||||
- op: add
|
||||
path: /data/SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI
|
||||
value: http://keycloak.local.test/realms/platform
|
||||
- op: add
|
||||
path: /data/SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI
|
||||
value: http://keycloak/realms/platform/protocol/openid-connect/certs
|
||||
- op: add
|
||||
path: /data/SERVER_MAX_HTTP_REQUEST_HEADER_SIZE
|
||||
value: 64KB
|
||||
- target:
|
||||
kind: ServiceAccount
|
||||
name: auth-server-sa
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /imagePullSecrets
|
||||
value:
|
||||
- name: docker-registry-pull-credentials
|
||||
@@ -0,0 +1,63 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: auth-server-ingress-traefik
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: traefik
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: auth-server-egress
|
||||
labels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: identity-postgres
|
||||
app.kubernetes.io/instance: identity-postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
@@ -0,0 +1,5 @@
|
||||
# gitops/apps/identity-postgres AGENTS
|
||||
|
||||
Stateful data services live here. Read the storage, backup, security, and
|
||||
component standard before changing a StatefulSet, Tenant, PVC, or retention
|
||||
policy. Environment storage classes and deletion behavior belong in overlays.
|
||||
@@ -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: replace-in-overlay
|
||||
volumeMode: Filesystem
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
@@ -0,0 +1,23 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- networkpolicy.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: StatefulSet
|
||||
name: identity-postgres
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/persistentVolumeClaimRetentionPolicy/whenDeleted
|
||||
value: Delete
|
||||
- op: replace
|
||||
path: /spec/persistentVolumeClaimRetentionPolicy/whenScaled
|
||||
value: Delete
|
||||
- op: replace
|
||||
path: /spec/volumeClaimTemplates/0/spec/storageClassName
|
||||
value: local-path
|
||||
@@ -0,0 +1,34 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: identity-postgres-ingress-clients
|
||||
labels:
|
||||
app.kubernetes.io/name: identity-postgres
|
||||
app.kubernetes.io/instance: identity-postgres
|
||||
app.kubernetes.io/component: database
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: identity-postgres
|
||||
app.kubernetes.io/instance: identity-postgres
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server-migrate-0-1-0
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- platform-realm-import.yaml
|
||||
@@ -0,0 +1,62 @@
|
||||
apiVersion: k8s.keycloak.org/v2beta1
|
||||
kind: KeycloakRealmImport
|
||||
metadata:
|
||||
name: platform-realm-v1
|
||||
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: kustomize
|
||||
spec:
|
||||
keycloakCRName: keycloak
|
||||
placeholders:
|
||||
AUTH_SERVER_INGRESS_CLIENT_SECRET:
|
||||
secret:
|
||||
name: keycloak-client-auth-server-ingress
|
||||
key: client-secret
|
||||
realm:
|
||||
realm: platform
|
||||
enabled: true
|
||||
sslRequired: external
|
||||
registrationAllowed: true
|
||||
loginWithEmailAllowed: true
|
||||
accessTokenLifespan: 300
|
||||
defaultRoles:
|
||||
- user
|
||||
roles:
|
||||
realm:
|
||||
- name: user
|
||||
clients:
|
||||
- clientId: auth-server-ingress
|
||||
name: auth-server-ingress
|
||||
protocol: openid-connect
|
||||
publicClient: false
|
||||
clientAuthenticatorType: client-secret
|
||||
secret: ${AUTH_SERVER_INGRESS_CLIENT_SECRET}
|
||||
standardFlowEnabled: true
|
||||
directAccessGrantsEnabled: false
|
||||
serviceAccountsEnabled: false
|
||||
defaultClientScopes:
|
||||
- profile
|
||||
- email
|
||||
- roles
|
||||
protocolMappers:
|
||||
- name: realm roles in id token
|
||||
protocol: openid-connect
|
||||
protocolMapper: oidc-usermodel-realm-role-mapper
|
||||
config:
|
||||
user.attribute: foo
|
||||
claim.name: realm_access.roles
|
||||
jsonType.label: String
|
||||
multivalued: "true"
|
||||
access.token.claim: "true"
|
||||
id.token.claim: "true"
|
||||
introspection.token.claim: "true"
|
||||
redirectUris:
|
||||
- http://auth.local.test/oauth2/callback
|
||||
webOrigins:
|
||||
- http://auth.local.test
|
||||
rootUrl: http://auth.local.test
|
||||
baseUrl: http://auth.local.test
|
||||
Reference in New Issue
Block a user