refactor: 폴더 구조 변경
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# gitops AGENTS
|
||||
|
||||
Role:
|
||||
- own Kubernetes/K3s source-of-truth manifests and Kustomize composition
|
||||
- keep catalog bases, environment overlays, cluster entrypoints, and Vault Secrets Operator assets separate
|
||||
- make render / validate / diff / apply possible from Git without relying on live cluster state
|
||||
|
||||
Scope:
|
||||
- `apps/`: app-owned workload/data/operation catalogs
|
||||
- `platform/`: shared services and operator catalogs
|
||||
- `policies/`: security and governance catalogs
|
||||
- `tenants/`: namespace/RBAC/quota catalogs
|
||||
- `clusters/<env>/<cluster>/namespaces` and `stages/`: deployable environment composition
|
||||
- `clusters/<env>/<cluster>/all/`: render/audit aggregate only
|
||||
|
||||
Read first:
|
||||
- `/docs/standards/infra/architecture-environments.md`
|
||||
- `/docs/standards/infra/kustomize.md`
|
||||
- `/docs/standards/infra/k3s-specific.md`
|
||||
- `/docs/standards/infra/operations-runbook-upgrade-rollback.md`
|
||||
|
||||
Rules:
|
||||
- prefer `kubectl kustomize`, `kubectl diff -k`, and `kubectl apply -k`
|
||||
- apply stage entrypoints only; never apply an environment `all/` aggregate
|
||||
- do not use server-local manifests as source of truth
|
||||
- do not place environment differences in a catalog `base/`
|
||||
- do not place base resource definitions directly in overlays unless the resource is environment-only by design
|
||||
- do not commit production secret values
|
||||
- keep scripts as helpers; manifests remain declarative source
|
||||
|
||||
Catalog base contract:
|
||||
- shared labels, selectors, probes, resources, services, storage and policy shape are allowed
|
||||
- environment hostnames, cluster contexts, production-only sizing, rollout image
|
||||
references, deletion overrides and secret values are forbidden
|
||||
- every base must be reusable by lab, staging and prod overlays
|
||||
- ownership must remain visible in the catalog unit path
|
||||
@@ -0,0 +1,20 @@
|
||||
# Project catalog ownership
|
||||
|
||||
| Catalog | Ownership |
|
||||
| --- | --- |
|
||||
| `apps/auth-server` | API workload와 lab ingress |
|
||||
| `apps/identity-postgres` | auth platform 전용 PostgreSQL |
|
||||
| `apps/auth-migration` | versioned Flyway migration Job |
|
||||
| `apps/keycloak-realm-import` | versioned realm/client import |
|
||||
| `platform/forward-auth` | oauth2-proxy와 Traefik ForwardAuth component |
|
||||
| `platform/keycloak` | Keycloak instance와 ingress |
|
||||
| `platform/minio` | MinIO Tenant |
|
||||
| `platform/registry` | Docker registry |
|
||||
| `platform/vault` | Vault workload |
|
||||
| `platform/secret-delivery` | VSO auth/connection, Helm values와 VaultStaticSecret |
|
||||
| `platform/*-operator` | cluster-scoped controller source와 environment patch |
|
||||
| `policies/baseline` | namespace 보안 baseline |
|
||||
| `tenants/mnt` | `mnt` namespace 경계 |
|
||||
|
||||
Catalog는 직접 controller root로 지정하지 않습니다. 실제 환경은
|
||||
`gitops/clusters/<...>` 아래 entrypoint에서 필요한 catalog만 선택합니다.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Project GitOps layout
|
||||
|
||||
Project-specific Kubernetes resources are split into reusable catalogs and
|
||||
cluster entrypoints.
|
||||
|
||||
```text
|
||||
gitops/
|
||||
├── apps/
|
||||
│ ├── auth-server/
|
||||
│ ├── identity-postgres/
|
||||
│ ├── auth-migration/
|
||||
│ └── keycloak-realm-import/
|
||||
├── platform/
|
||||
│ ├── cert-manager/
|
||||
│ ├── forward-auth/
|
||||
│ ├── keycloak/
|
||||
│ ├── keycloak-operator/
|
||||
│ ├── minio/
|
||||
│ ├── registry/
|
||||
│ ├── secret-delivery/
|
||||
│ ├── traefik/
|
||||
│ └── vault/
|
||||
├── policies/baseline/
|
||||
├── tenants/mnt/
|
||||
└── clusters/lab/main/
|
||||
├── stages/
|
||||
└── all/
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Catalog `base`는 환경 중립 shape를 소유하고 `overlays/<env>`는 차이만
|
||||
표현합니다.
|
||||
- `clusters/lab/main/stages/*`만 현재 deployable entrypoint입니다.
|
||||
- `clusters/lab/main/all`은 전체 렌더와 정적 검사 전용이며 apply하지 않습니다.
|
||||
- operator readiness, Vault init, Secret 생성과 Job 완료는 stage 사이에서
|
||||
`scripts/bin/bootstrap.sh`가 확인합니다.
|
||||
- 새 deployable entrypoint는 `tests/kustomize-entrypoints.txt`에 추가합니다.
|
||||
|
||||
```bash
|
||||
kubectl kustomize gitops/clusters/lab/main/all >/tmp/project-infra-lab.yaml
|
||||
export KUBE_CONTEXT_LAB='<expected-context>'
|
||||
bash scripts/bin/bootstrap.sh lab
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# GitOps Desired State
|
||||
|
||||
Kubernetes API 안에서 지속적으로 reconcile할 desired state를 관리합니다.
|
||||
GitOps controller를 사용하지 않는 초기 단계에도 `kubectl kustomize`로 같은
|
||||
entrypoint를 렌더할 수 있습니다.
|
||||
|
||||
```text
|
||||
platform ─┐
|
||||
policies ─┼──▶ clusters/<...> ◀── GitOps controller root
|
||||
tenants ─┤
|
||||
apps ─┘
|
||||
```
|
||||
|
||||
- `clusters`: 클러스터별 최종 조립점
|
||||
- `platform`: cluster-wide addon과 controller
|
||||
- `policies`: cluster-wide admission과 거버넌스 규칙
|
||||
- `tenants`: 구체적인 namespace/RBAC/quota/NetworkPolicy
|
||||
- `apps`: application 배포 정의
|
||||
|
||||
Catalog 디렉터리를 controller root로 직접 지정하지 않습니다. cluster entrypoint가
|
||||
필요한 base/overlay를 선택하고 의존 순서를 명시합니다.
|
||||
|
||||
## 기본 규칙
|
||||
|
||||
- `base`는 환경을 모르며 재사용 가능한 기본값만 가집니다.
|
||||
- `overlays`는 차이만 patch하고 전체 manifest를 복사하지 않습니다.
|
||||
- CRD/controller가 필요한 리소스는 controller 이후에 reconcile합니다.
|
||||
- resource namespace, ownership label과 버전을 명시합니다.
|
||||
- raw `Secret` 또는 실제 비밀값을 커밋하지 않습니다.
|
||||
- 원격 base/chart를 참조할 때 immutable version 또는 digest를 사용합니다.
|
||||
|
||||
Flux/Argo CD 고유 리소스와 sync ordering은 선택한 controller를 기록한 ADR에
|
||||
문서화합니다.
|
||||
@@ -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
|
||||
@@ -0,0 +1,45 @@
|
||||
# gitops/clusters AGENTS
|
||||
|
||||
Role:
|
||||
- own environment-specific Kustomize composition
|
||||
- express only the differences between environments and reusable bases
|
||||
- make environment-level render, diff, apply, audit, and GitOps sync straightforward
|
||||
|
||||
Scope:
|
||||
- `<environment>/<region-or-cluster>/stages/`
|
||||
- `<environment>/<region-or-cluster>/all/`
|
||||
|
||||
Allowed:
|
||||
- namespace selection
|
||||
- replicas
|
||||
- resource requests/limits overrides
|
||||
- image tags or image references
|
||||
- ingress host/TLS differences
|
||||
- environment-specific patches
|
||||
- environment-specific secret references
|
||||
- storage class and retention differences
|
||||
|
||||
Forbidden:
|
||||
- copying full base manifests into overlays
|
||||
- redefining base resources wholesale without a clear environment-only reason
|
||||
- placing production secret values in Git
|
||||
- changing service ownership or workload kind without updating the base and standards
|
||||
- mixing multiple environments in one overlay
|
||||
|
||||
Read first:
|
||||
- `/docs/standards/infra/kustomize.md`
|
||||
- `/docs/standards/infra/architecture-environments.md`
|
||||
- `/docs/standards/infra/config-and-secrets.md`
|
||||
- `/docs/standards/infra/network-ingress-tls.md`
|
||||
- `/docs/standards/infra/resources-probes-availability.md`
|
||||
- `/docs/standards/infra/security-hardening.md`
|
||||
- `/docs/standards/infra/operations-runbook-upgrade-rollback.md`
|
||||
|
||||
Rules:
|
||||
- cluster entrypoints are environment-first by design
|
||||
- `stages/*` are deployable entrypoints; `all/` is validation-only
|
||||
- controller readiness and one-shot completion belong between stage applies
|
||||
- keep patches small and named by target and intent
|
||||
- render and diff the target environment before apply
|
||||
- prod overlays must be the most conservative environment
|
||||
- if an overlay starts re-declaring most of a resource, move common shape back into its catalog `base`
|
||||
@@ -0,0 +1,37 @@
|
||||
# Cluster Entrypoints
|
||||
|
||||
클러스터별 최종 desired state 진입점입니다. GitOps controller의 root는 이
|
||||
디렉터리 아래 **하나의 실제 cluster leaf**만 가리킵니다.
|
||||
|
||||
소규모:
|
||||
|
||||
```text
|
||||
clusters/
|
||||
└── dev/
|
||||
└── main/
|
||||
└── kustomization.yaml
|
||||
```
|
||||
|
||||
다중 환경·리전:
|
||||
|
||||
```text
|
||||
clusters/
|
||||
├── dev/ap-northeast-2/dev-a/
|
||||
├── staging/ap-northeast-2/staging-a/
|
||||
└── prod/
|
||||
├── ap-northeast-2/prod-a/
|
||||
└── ap-southeast-1/prod-b/
|
||||
```
|
||||
|
||||
cluster leaf에는 catalog 구현을 복사하지 않고 선택 목록과 cluster 고유 patch만
|
||||
둡니다. 계정 또는 조직 경계가 필요하면 경로 segment를 추가할 수 있지만 자동화가
|
||||
고정 depth에 의존하지 않도록 합니다.
|
||||
|
||||
`_template`을 실제 경로로 복사해 시작합니다.
|
||||
|
||||
## Current lab exception
|
||||
|
||||
`lab/main`은 CRD, Vault, Secret과 one-shot operation의 readiness 경계 때문에
|
||||
단일 direct leaf 대신 `namespaces`와 ordered `stages/*` leaf를 사용합니다.
|
||||
현재는 `scripts/bin/bootstrap.sh`가 순서를 보장합니다. `all/`은 감사
|
||||
aggregate이므로 controller root로 지정하거나 apply하지 않습니다.
|
||||
@@ -0,0 +1,31 @@
|
||||
# __REPLACE_ME_CLUSTER_NAME__
|
||||
|
||||
## 대상
|
||||
|
||||
- Environment: __REPLACE_ME_ENVIRONMENT__
|
||||
- Region: __REPLACE_ME_REGION__
|
||||
- Cluster: __REPLACE_ME_CLUSTER_NAME__
|
||||
- Owner: __REPLACE_ME_OWNER__
|
||||
|
||||
## 구성
|
||||
|
||||
`kustomization.yaml`의 `resources`에 필요한 platform, policy, tenant와 app의
|
||||
base 또는 overlay를 추가합니다. 예:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- ../../../platform/core/base
|
||||
- ../../../policies/baseline/base
|
||||
- ../../../apps/example-api/overlays/prod
|
||||
```
|
||||
|
||||
위 예시는 `clusters/dev/main` 경로를 기준으로 합니다. 실제 상대 경로는 cluster
|
||||
leaf 깊이에 맞게 조정합니다.
|
||||
|
||||
## 규칙
|
||||
|
||||
- 이 디렉터리가 해당 클러스터의 유일한 root입니다.
|
||||
- 공통 manifest를 복사하지 않습니다.
|
||||
- 클러스터 고유 차이만 local patch로 둡니다.
|
||||
- dependency/sync 순서와 장애 시 reconcile 중지 절차를 문서화합니다.
|
||||
- `_template` 자체를 GitOps controller에 연결하지 않습니다.
|
||||
@@ -0,0 +1,5 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# Add reusable platform, policy, tenant and app paths after copying this template.
|
||||
resources: []
|
||||
@@ -0,0 +1,22 @@
|
||||
# lab / main cluster entrypoints
|
||||
|
||||
현재 `lab`은 readiness 경계를 가진 push-based staged deployment를 사용합니다.
|
||||
|
||||
```text
|
||||
namespaces
|
||||
stages/
|
||||
├── 00-platform
|
||||
├── 10-vault
|
||||
├── 20-secrets
|
||||
├── 30-data
|
||||
├── 35-registry
|
||||
├── 40-operations
|
||||
└── 50-apps
|
||||
```
|
||||
|
||||
- `namespaces`와 각 stage는 독립적으로 렌더 가능한 cluster 배포 entrypoint입니다.
|
||||
- `scripts/bin/bootstrap.sh lab`만 준비 상태를 확인하며 순차 적용합니다.
|
||||
- `all/`은 모든 stage를 합친 감사용 Kustomization입니다. apply하거나 GitOps
|
||||
controller root로 연결하지 않습니다.
|
||||
- Argo CD를 채택하면 stage별 Application/sync-wave/health gate를, Flux를
|
||||
채택하면 Kustomization `dependsOn`/`healthChecks`를 먼저 설계한 뒤 전환합니다.
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# Audit/render entrypoint only. Do not apply this aggregate: controllers and
|
||||
# one-shot operations have readiness boundaries that Kustomize cannot express.
|
||||
resources:
|
||||
- ../stages/00-platform
|
||||
- ../stages/10-vault
|
||||
- ../stages/20-secrets
|
||||
- ../stages/30-data
|
||||
- ../stages/35-registry
|
||||
- ../stages/40-operations
|
||||
- ../stages/50-apps
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# Namespace creation is a separate cluster entrypoint because server-side
|
||||
# dry-run cannot create a Namespace and validate namespaced resources against
|
||||
# it in the same request.
|
||||
resources:
|
||||
- ../../../../tenants/mnt/base
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# Cluster prerequisites and the deny-by-default policy are applied before any
|
||||
# workload. This stage is intentionally free of application CRs.
|
||||
resources:
|
||||
- ../../../../../tenants/mnt/base
|
||||
- ../../../../../platform/cert-manager/overlays/lab
|
||||
- ../../../../../platform/keycloak-operator/overlays/lab
|
||||
- ../../../../../platform/traefik/overlays/lab
|
||||
- ../../../../../policies/baseline/overlays/lab
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../../../../platform/vault/overlays/lab
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# The VSO controller is installed by the bootstrap task before this stage.
|
||||
resources:
|
||||
- ../../../../../platform/secret-delivery/overlays/lab/operator
|
||||
- ../../../../../platform/secret-delivery/overlays/lab/identity
|
||||
- ../../../../../platform/secret-delivery/overlays/lab/storage
|
||||
- ../../../../../platform/secret-delivery/overlays/lab/apps
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../../../../apps/identity-postgres/overlays/lab
|
||||
- ../../../../../platform/minio/overlays/lab
|
||||
- ../../../../../platform/keycloak/overlays/lab
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../../../../platform/secret-delivery/overlays/lab/storage/registry-minio
|
||||
- ../../../../../platform/registry/overlays/lab
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# One-shot resources. bootstrap.sh waits for their prerequisites before apply.
|
||||
resources:
|
||||
- ../../../../../apps/auth-migration/overlays/lab
|
||||
- ../../../../../apps/keycloak-realm-import/overlays/lab
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../../../../apps/auth-server/overlays/lab
|
||||
- ../../../../../platform/forward-auth/overlays/lab
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
example.com/environment: lab
|
||||
example.com/owner-team: platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,6 @@
|
||||
# gitops/platform AGENTS
|
||||
|
||||
Shared platform services and environment-neutral operator sources live in
|
||||
unit-level `base` directories. Cluster-specific CIDRs, namespaces, ingress,
|
||||
service mesh, load balancer, and K3s packaged-component configuration belong
|
||||
in focused overlays selected by a cluster stage.
|
||||
@@ -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`을 복사해 시작합니다.
|
||||
@@ -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으로 연결합니다.
|
||||
@@ -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,5 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.yaml
|
||||
@@ -0,0 +1,95 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/part-of: certificate-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: cert-manager
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /spec/revisionHistoryLimit
|
||||
value: 5
|
||||
- op: add
|
||||
path: /spec/progressDeadlineSeconds
|
||||
value: 600
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/runAsUser
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/runAsGroup
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/fsGroup
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/resources
|
||||
value:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: cert-manager-cainjector
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /spec/revisionHistoryLimit
|
||||
value: 5
|
||||
- op: add
|
||||
path: /spec/progressDeadlineSeconds
|
||||
value: 600
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/runAsUser
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/runAsGroup
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/fsGroup
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/resources
|
||||
value:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: cert-manager-webhook
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /spec/revisionHistoryLimit
|
||||
value: 5
|
||||
- op: add
|
||||
path: /spec/progressDeadlineSeconds
|
||||
value: 600
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/runAsUser
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/runAsGroup
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext/fsGroup
|
||||
value: 1000
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/resources
|
||||
value:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
memory: 128Mi
|
||||
@@ -0,0 +1,115 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: oauth2-proxy
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 5
|
||||
progressDeadlineSeconds: 600
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
spec:
|
||||
serviceAccountName: oauth2-proxy-sa
|
||||
automountServiceAccountToken: false
|
||||
terminationGracePeriodSeconds: 30
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
fsGroup: 65532
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: oauth2-proxy
|
||||
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --config=/etc/oauth2-proxy/oauth2-proxy.cfg
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4180
|
||||
protocol: TCP
|
||||
- name: metrics
|
||||
containerPort: 44180
|
||||
protocol: TCP
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: http
|
||||
periodSeconds: 5
|
||||
failureThreshold: 12
|
||||
timeoutSeconds: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
timeoutSeconds: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: http
|
||||
periodSeconds: 15
|
||||
failureThreshold: 3
|
||||
timeoutSeconds: 3
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/oauth2-proxy
|
||||
readOnly: true
|
||||
- name: secrets
|
||||
mountPath: /etc/oauth2-proxy-secrets
|
||||
readOnly: true
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: oauth2-proxy-config
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: oauth2-proxy-secrets
|
||||
defaultMode: 0400
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 64Mi
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- serviceaccount.yaml
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/version: "7.15.2"
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: oauth2-proxy
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
ports:
|
||||
- name: http
|
||||
port: 4180
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
appProtocol: http
|
||||
- name: metrics
|
||||
port: 44180
|
||||
targetPort: metrics
|
||||
protocol: TCP
|
||||
appProtocol: http
|
||||
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: oauth2-proxy-sa
|
||||
automountServiceAccountToken: false
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
|
||||
resources:
|
||||
- ../base
|
||||
- oauth2-proxy-config.yaml
|
||||
- oauth2-proxy-ingress.yaml
|
||||
- oauth2-proxy-middleware.yaml
|
||||
- oauth2-proxy-networkpolicy.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: Ingress
|
||||
name: auth-server
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /metadata/annotations/traefik.ingress.kubernetes.io~1router.middlewares
|
||||
value: mnt-oauth2-proxy-errors@kubernetescrd,mnt-oauth2-proxy-auth@kubernetescrd,kube-system-security-headers@kubernetescrd
|
||||
@@ -0,0 +1,46 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: oauth2-proxy-config
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/version: "7.15.2"
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
data:
|
||||
oauth2-proxy.cfg: |
|
||||
provider = "keycloak-oidc"
|
||||
http_address = "0.0.0.0:4180"
|
||||
metrics_address = "0.0.0.0:44180"
|
||||
redirect_url = "http://auth.local.test/oauth2/callback"
|
||||
|
||||
oidc_issuer_url = "http://keycloak.local.test/realms/platform"
|
||||
skip_oidc_discovery = true
|
||||
login_url = "http://keycloak.local.test/realms/platform/protocol/openid-connect/auth"
|
||||
redeem_url = "http://keycloak.mnt.svc.cluster.local/realms/platform/protocol/openid-connect/token"
|
||||
profile_url = "http://keycloak.mnt.svc.cluster.local/realms/platform/protocol/openid-connect/userinfo"
|
||||
validate_url = "http://keycloak.mnt.svc.cluster.local/realms/platform/protocol/openid-connect/userinfo"
|
||||
oidc_jwks_url = "http://keycloak.mnt.svc.cluster.local/realms/platform/protocol/openid-connect/certs"
|
||||
|
||||
client_id = "auth-server-ingress"
|
||||
client_secret_file = "/etc/oauth2-proxy-secrets/client-secret"
|
||||
cookie_secret_file = "/etc/oauth2-proxy-secrets/cookie-secret"
|
||||
reverse_proxy = true
|
||||
upstreams = [ "static://202" ]
|
||||
email_domains = [ "*" ]
|
||||
scope = "openid profile email"
|
||||
insecure_oidc_allow_unverified_email = true
|
||||
skip_provider_button = true
|
||||
cookie_secure = false
|
||||
cookie_samesite = "lax"
|
||||
cookie_csrf_per_request = true
|
||||
cookie_refresh = "4m"
|
||||
set_xauthrequest = true
|
||||
set_authorization_header = true
|
||||
pass_access_token = true
|
||||
pass_authorization_header = true
|
||||
ssl_insecure_skip_verify = false
|
||||
whitelist_domains = [ "auth.local.test" ]
|
||||
trusted_proxy_ips = [ "10.42.0.0/16" ]
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: oauth2-proxy
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/version: "7.15.2"
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
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: /oauth2/
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: oauth2-proxy
|
||||
port:
|
||||
name: http
|
||||
@@ -0,0 +1,45 @@
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: oauth2-proxy-auth
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/version: "7.15.2"
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
forwardAuth:
|
||||
address: http://oauth2-proxy.mnt.svc.cluster.local:4180/oauth2/auth
|
||||
trustForwardHeader: true
|
||||
authResponseHeaders:
|
||||
- Authorization
|
||||
- X-Auth-Request-Access-Token
|
||||
- X-Auth-Request-Email
|
||||
- X-Auth-Request-Preferred-Username
|
||||
- X-Auth-Request-User
|
||||
- X-Forwarded-Email
|
||||
- X-Forwarded-User
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: oauth2-proxy-errors
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/version: "7.15.2"
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
errors:
|
||||
status:
|
||||
- "401"
|
||||
statusRewrites:
|
||||
"401": 302
|
||||
service:
|
||||
name: oauth2-proxy
|
||||
port: 4180
|
||||
query: /oauth2/start?rd={url}
|
||||
@@ -0,0 +1,55 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: oauth2-proxy-ingress-traefik
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: traefik
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 4180
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: oauth2-proxy-egress-keycloak
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
components:
|
||||
- ../../component
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/26.6.1/kubernetes/keycloaks.k8s.keycloak.org-v1.yml
|
||||
- https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/26.6.1/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml
|
||||
- https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/26.6.1/kubernetes/kubernetes.yml
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- networkpolicy.yaml
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/instance: keycloak-operator
|
||||
app.kubernetes.io/component: identity-operator
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: ClusterRoleBinding
|
||||
name: keycloak-operator-clusterrole-binding
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /subjects/0/namespace
|
||||
value: mnt
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: keycloak-operator
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /spec/revisionHistoryLimit
|
||||
value: 5
|
||||
- op: add
|
||||
path: /spec/progressDeadlineSeconds
|
||||
value: 600
|
||||
- op: add
|
||||
path: /spec/template/spec/securityContext
|
||||
value:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/securityContext
|
||||
value:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts
|
||||
value:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes
|
||||
value:
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
sizeLimit: 128Mi
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/startupProbe/failureThreshold
|
||||
value: 18
|
||||
@@ -0,0 +1,29 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: keycloak-operator-egress-kubernetes-api
|
||||
labels:
|
||||
app.kubernetes.io/name: keycloak-operator
|
||||
app.kubernetes.io/instance: keycloak-operator
|
||||
app.kubernetes.io/component: identity-operator
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: keycloak-operator
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.43.0.0/16
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.208.141.0/24
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 6443
|
||||
@@ -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
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: keycloak-admin
|
||||
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
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
traefik.ingress.kubernetes.io/router.middlewares: mnt-keycloak-security-headers@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: keycloak-admin.local.test
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: keycloak
|
||||
port:
|
||||
name: http
|
||||
@@ -0,0 +1,48 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: keycloak-public
|
||||
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
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
traefik.ingress.kubernetes.io/router.middlewares: mnt-keycloak-security-headers@kubernetescrd # frameDeny 제외 — admin 콘솔의 silent SSO iframe 허용
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: keycloak.local.test
|
||||
http:
|
||||
paths:
|
||||
- path: /realms/
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: keycloak
|
||||
port:
|
||||
name: http
|
||||
- path: /resources/
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: keycloak
|
||||
port:
|
||||
name: http
|
||||
- path: /.well-known/
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: keycloak
|
||||
port:
|
||||
name: http
|
||||
- path: /js/
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: keycloak
|
||||
port:
|
||||
name: http
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: k8s.keycloak.org/v2beta1
|
||||
kind: Keycloak
|
||||
metadata:
|
||||
name: keycloak
|
||||
spec:
|
||||
hostname:
|
||||
hostname: http://keycloak.local.test
|
||||
admin: http://keycloak-admin.local.test
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- middleware.yaml
|
||||
- ingress-public.yaml
|
||||
- ingress-admin.yaml
|
||||
- networkpolicy.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: Keycloak
|
||||
name: keycloak
|
||||
path: keycloak-hostname-patch.yaml
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: keycloak-security-headers
|
||||
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: kustomize
|
||||
spec:
|
||||
headers:
|
||||
browserXssFilter: true
|
||||
contentTypeNosniff: true
|
||||
referrerPolicy: strict-origin-when-cross-origin
|
||||
@@ -0,0 +1,140 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: keycloak-peer
|
||||
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: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: keycloak-ingress-traefik
|
||||
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: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
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: keycloak-egress-postgres
|
||||
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: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: identity-postgres
|
||||
app.kubernetes.io/instance: identity-postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: keycloak-ingress-auth-server
|
||||
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: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: auth-server
|
||||
app.kubernetes.io/instance: auth-server
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: keycloak-ingress-oauth2-proxy
|
||||
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: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: keycloak
|
||||
app.kubernetes.io/managed-by: keycloak-operator
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/instance: oauth2-proxy
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- tenant.yaml
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/version: "2025.01.20"
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,92 @@
|
||||
apiVersion: minio.min.io/v2
|
||||
kind: Tenant
|
||||
metadata:
|
||||
name: minio
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/version: "2025.01.20"
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
image: minio/minio:RELEASE.2025-01-20T14-49-07Z
|
||||
imagePullPolicy: IfNotPresent
|
||||
mountPath: /export
|
||||
configuration:
|
||||
name: minio-tenant-env
|
||||
requestAutoCert: true
|
||||
certConfig:
|
||||
commonName: minio
|
||||
organizationName:
|
||||
- example.com
|
||||
dnsNames:
|
||||
- minio
|
||||
- minio-hl
|
||||
pools:
|
||||
- name: pool-0
|
||||
servers: 4
|
||||
volumesPerServer: 4
|
||||
volumeClaimTemplate:
|
||||
metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 20Gi
|
||||
storageClassName: replace-in-overlay
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 1Gi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 2Gi
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containerSecurityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
features:
|
||||
bucketDNS: false
|
||||
prometheusOperator: false
|
||||
podManagementPolicy: Parallel
|
||||
exposeServices:
|
||||
minio: false
|
||||
console: false
|
||||
logging:
|
||||
anonymous: false
|
||||
json: true
|
||||
quiet: false
|
||||
---
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: minio-pdb
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/version: "2025.01.20"
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
maxUnavailable: 1
|
||||
unhealthyPodEvictionPolicy: AlwaysAllow
|
||||
selector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
@@ -0,0 +1,32 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- networkpolicy.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
group: minio.min.io
|
||||
version: v2
|
||||
kind: Tenant
|
||||
name: minio
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/certConfig/dnsNames
|
||||
value:
|
||||
- minio
|
||||
- minio-hl
|
||||
- minio.mnt.svc.cluster.local
|
||||
- "*.minio-hl.mnt.svc.cluster.local"
|
||||
- op: replace
|
||||
path: /spec/requestAutoCert
|
||||
value: false
|
||||
- op: replace
|
||||
path: /spec/pools/0/volumesPerServer
|
||||
value: 1
|
||||
- op: replace
|
||||
path: /spec/pools/0/volumeClaimTemplate/spec/storageClassName
|
||||
value: local-path
|
||||
@@ -0,0 +1,140 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: minio-ingress-peer
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 9000
|
||||
- protocol: TCP
|
||||
port: 9001
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: minio-ingress-operator
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: minio-operator
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: minio-operator
|
||||
app.kubernetes.io/name: operator
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 9000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: minio-ingress-clients
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 9000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: minio-egress-peer
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 9000
|
||||
- protocol: TCP
|
||||
port: 9001
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: minio-egress-kubernetes-api
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio
|
||||
app.kubernetes.io/component: object-storage
|
||||
app.kubernetes.io/part-of: storage-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.43.0.0/16
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.208.141.0/24
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 6443
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: docker-registry-config
|
||||
data:
|
||||
REGISTRY_HTTP_ADDR: "0.0.0.0:5000"
|
||||
REGISTRY_LOG_FORMATTER: "json"
|
||||
REGISTRY_STORAGE: "s3"
|
||||
REGISTRY_STORAGE_S3_REGION: "us-east-1"
|
||||
REGISTRY_STORAGE_S3_REGIONENDPOINT: "https://minio"
|
||||
REGISTRY_STORAGE_S3_BUCKET: "docker-registry"
|
||||
REGISTRY_STORAGE_S3_FORCEPATHSTYLE: "true"
|
||||
REGISTRY_STORAGE_S3_SKIPVERIFY: "true"
|
||||
REGISTRY_STORAGE_REDIRECT_DISABLE: "true"
|
||||
REGISTRY_STORAGE_DELETE_ENABLED: "true"
|
||||
@@ -0,0 +1,94 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: docker-registry
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 5
|
||||
progressDeadlineSeconds: 600
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
spec:
|
||||
serviceAccountName: docker-registry
|
||||
automountServiceAccountToken: false
|
||||
terminationGracePeriodSeconds: 45
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
runAsGroup: 10001
|
||||
fsGroup: 10001
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: registry
|
||||
image: registry:2.8.3
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 5000
|
||||
protocol: TCP
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: docker-registry-config
|
||||
- secretRef:
|
||||
name: docker-registry-minio
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
memory: 512Mi
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /v2/
|
||||
port: http
|
||||
periodSeconds: 5
|
||||
failureThreshold: 12
|
||||
timeoutSeconds: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /v2/
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
timeoutSeconds: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /v2/
|
||||
port: http
|
||||
periodSeconds: 30
|
||||
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: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 64Mi
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- serviceaccount.yaml
|
||||
- configmap.yaml
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
app.kubernetes.io/version: "2.8.3"
|
||||
app.kubernetes.io/component: registry
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: docker-registry
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
ports:
|
||||
- name: http
|
||||
port: 5000
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
appProtocol: http
|
||||
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: docker-registry
|
||||
automountServiceAccountToken: false
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: docker-registry-public
|
||||
labels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
app.kubernetes.io/version: "2.8.3"
|
||||
app.kubernetes.io/component: registry
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
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,mnt-docker-registry-basic-auth@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: registry.project.com
|
||||
http:
|
||||
paths:
|
||||
- path: /v2
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: docker-registry
|
||||
port:
|
||||
name: http
|
||||
@@ -0,0 +1,22 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- middleware.yaml
|
||||
- ingress-public.yaml
|
||||
- networkpolicy.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: ConfigMap
|
||||
name: docker-registry-config
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /data/REGISTRY_STORAGE_S3_REGIONENDPOINT
|
||||
value: http://minio
|
||||
- op: replace
|
||||
path: /data/REGISTRY_STORAGE_S3_SKIPVERIFY
|
||||
value: "false"
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: docker-registry-basic-auth
|
||||
labels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
app.kubernetes.io/component: registry
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
basicAuth:
|
||||
secret: docker-registry-basic-auth
|
||||
realm: docker-registry
|
||||
@@ -0,0 +1,82 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: docker-registry-ingress-intra
|
||||
labels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
app.kubernetes.io/component: registry
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector: {}
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: docker-registry-ingress-traefik
|
||||
labels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
app.kubernetes.io/component: registry
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: traefik
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: docker-registry-egress-minio
|
||||
labels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
app.kubernetes.io/component: registry
|
||||
app.kubernetes.io/part-of: platform-registry
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: docker-registry
|
||||
app.kubernetes.io/instance: docker-registry
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
v1.min.io/tenant: minio
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
- protocol: TCP
|
||||
port: 9000
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
defaultVaultConnection:
|
||||
enabled: false
|
||||
|
||||
controller:
|
||||
# VSO 는 전용 namespace 에 설치하지만 같은 restricted baseline 을 강제한다.
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
manager:
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
kubeRbacProxy:
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
# kubeRBACProxy : metrics 접근 제어
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- serviceaccount.yaml
|
||||
- vault-connection.yaml
|
||||
- vault-auth.yaml
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
app.kubernetes.io/name: vault-secrets-operator
|
||||
app.kubernetes.io/instance: vso
|
||||
app.kubernetes.io/version: "0.9.0"
|
||||
app.kubernetes.io/component: secret-delivery
|
||||
app.kubernetes.io/part-of: security-platform
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
includeSelectors: false
|
||||
includeTemplates: true
|
||||
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: vault-secrets-operator
|
||||
automountServiceAccountToken: true
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: vault-auth-auth-platform
|
||||
spec:
|
||||
vaultConnectionRef: vault-connection
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: vso-auth-platform
|
||||
serviceAccount: vault-secrets-operator
|
||||
audiences:
|
||||
- vault
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: vault-auth-storage
|
||||
spec:
|
||||
vaultConnectionRef: vault-connection
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: vso-storage
|
||||
serviceAccount: vault-secrets-operator
|
||||
audiences:
|
||||
- vault
|
||||
@@ -0,0 +1,7 @@
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultConnection
|
||||
metadata:
|
||||
name: vault-connection
|
||||
spec:
|
||||
address: http://vault.mnt.svc.cluster.local:8200
|
||||
skipTLSVerify: false
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mnt
|
||||
|
||||
resources:
|
||||
- oauth2-proxy.yaml
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: oauth2-proxy-secrets
|
||||
spec:
|
||||
vaultAuthRef: vault-auth-auth-platform
|
||||
mount: secret
|
||||
path: oauth2-proxy/forward-auth
|
||||
refreshAfter: 60s
|
||||
type: kv-v2
|
||||
destination:
|
||||
name: oauth2-proxy-secrets
|
||||
create: true
|
||||
overwrite: true
|
||||
labels:
|
||||
app.kubernetes.io/name: oauth2-proxy
|
||||
app.kubernetes.io/component: auth-proxy
|
||||
app.kubernetes.io/managed-by: vault-secrets-operator
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
client-secret:
|
||||
text: '{{ if index .Secrets "client_secret" }}{{ index .Secrets "client_secret" }}{{ else }}{{ index .Secrets "client-secret" }}{{ end }}'
|
||||
cookie-secret:
|
||||
text: '{{ if index .Secrets "cookie_secret" }}{{ index .Secrets "cookie_secret" }}{{ else }}{{ index .Secrets "cookie-secret" }}{{ end }}'
|
||||
rolloutRestartTargets:
|
||||
- kind: Deployment
|
||||
name: oauth2-proxy
|
||||
@@ -0,0 +1,94 @@
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: keycloak-bootstrap-admin
|
||||
spec:
|
||||
vaultAuthRef: vault-auth-auth-platform
|
||||
mount: secret
|
||||
type: kv-v2
|
||||
path: keycloak/bootstrap-admin
|
||||
refreshAfter: 60s
|
||||
destination:
|
||||
name: keycloak-bootstrap-admin
|
||||
create: true
|
||||
overwrite: true
|
||||
labels:
|
||||
app.kubernetes.io/name: keycloak
|
||||
app.kubernetes.io/component: identity-provider
|
||||
app.kubernetes.io/managed-by: vault-secrets-operator
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: keycloak-bootstrap-admin-operator
|
||||
spec:
|
||||
vaultAuthRef: vault-auth-auth-platform
|
||||
mount: secret
|
||||
type: kv-v2
|
||||
path: keycloak/bootstrap-admin
|
||||
refreshAfter: 60s
|
||||
destination:
|
||||
name: keycloak-bootstrap-admin-operator
|
||||
create: true
|
||||
overwrite: true
|
||||
labels:
|
||||
app.kubernetes.io/name: keycloak
|
||||
app.kubernetes.io/component: identity-provider
|
||||
app.kubernetes.io/managed-by: vault-secrets-operator
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
username:
|
||||
text: '{{ .Secrets.KEYCLOAK_ADMIN }}'
|
||||
password:
|
||||
text: '{{ .Secrets.KEYCLOAK_ADMIN_PASSWORD }}'
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: keycloak-db-operator
|
||||
spec:
|
||||
vaultAuthRef: vault-auth-auth-platform
|
||||
mount: secret
|
||||
type: kv-v2
|
||||
path: keycloak/db
|
||||
refreshAfter: 60s
|
||||
destination:
|
||||
name: keycloak-db-operator
|
||||
create: true
|
||||
overwrite: true
|
||||
labels:
|
||||
app.kubernetes.io/name: keycloak
|
||||
app.kubernetes.io/component: database
|
||||
app.kubernetes.io/managed-by: vault-secrets-operator
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
username:
|
||||
text: keycloak
|
||||
password:
|
||||
text: '{{ .Secrets.password }}'
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: keycloak-client-auth-server-ingress
|
||||
spec:
|
||||
vaultAuthRef: vault-auth-auth-platform
|
||||
mount: secret
|
||||
type: kv-v2
|
||||
path: keycloak/clients/auth-server-ingress
|
||||
refreshAfter: 60s
|
||||
destination:
|
||||
name: keycloak-client-auth-server-ingress
|
||||
create: true
|
||||
overwrite: true
|
||||
labels:
|
||||
app.kubernetes.io/name: keycloak
|
||||
app.kubernetes.io/component: identity-provider
|
||||
app.kubernetes.io/managed-by: vault-secrets-operator
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
client-secret:
|
||||
text: '{{ .Secrets.client_secret }}'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user