Reference
CDK8S Constructs API¶
Overview¶
GitLab BDA uses 15 CDK8S constructs to generate Kubernetes manifests. This reference documents each construct’s interface, parameters, generated resources, and usage.
Source location: deployments/gitlabbda/charts/constructs/
For WHY we use CDK8S, see CDK8S Approach Explanation.
Construct Catalog¶
Construct |
Purpose |
Resources Generated |
Sync Wave |
|---|---|---|---|
Create namespace |
Namespace |
Wave 0 |
|
[RbacConstruct](#rbacc construct) |
Service accounts, roles |
ServiceAccount (3), Role, RoleBinding |
Wave 1 |
Provision S3 buckets |
Bucket (8, Crossplane) |
Wave 1 |
|
S3 credential secrets |
ExternalSecret (2) |
Wave 1 |
|
Application secrets |
ExternalSecret (3) |
Wave 2 |
|
PostgreSQL cluster |
Cluster, Pooler, ObjectStore (CNPG) |
Waves 2-3 |
|
Redis cache |
PVC, StatefulSet, Service |
Wave 2 |
|
GitLab platform |
~100 resources (via Helm) |
Waves 3-4 |
|
Harbor configuration |
ConfigMap (3) |
Wave 4 |
|
Harbor registry |
Deployment (4), Service (4) |
Wave 4 |
|
Harbor ingress |
Ingress, IngressRoute (TCP) |
Wave 5 |
|
GitLab Pages ingress |
Ingress (wildcard) |
Wave 5 |
|
SSH routing via Traefik |
IngressRouteTCP |
Wave 5 |
|
Prometheus scraping |
ServiceMonitor (2) |
Wave 6 |
NamespaceConstruct¶
Purpose: Create Kubernetes namespace for all GitLab BDA resources.
Source: constructs/namespace.ts
Interface¶
export interface NamespaceProps {
name: string; // Namespace name
}
Parameters¶
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
Yes |
Kubernetes namespace name (DNS label format) |
Generated Resources¶
Namespace (1)
Example Usage¶
const namespace = new NamespaceConstruct(this, 'namespace', {
name: 'gitlabbda',
});
Generated Manifest¶
apiVersion: v1
kind: Namespace
metadata:
name: gitlabbda
annotations:
argocd.argoproj.io/sync-wave: "0"
labels:
app.kubernetes.io/part-of: gitlab
RbacConstruct¶
Purpose: Create ServiceAccounts and RBAC for GitLab, Harbor, and monitoring.
Source: constructs/rbac.ts
Interface¶
export interface RbacProps {
namespace: string; // Target namespace
}
Generated Resources¶
ServiceAccount (3):
gitlab,harbor,monitoringRole (1):
gitlab-role(permissions for all ServiceAccounts)RoleBinding (1): Binds ServiceAccounts to Role
ServiceAccounts Created¶
gitlab- Used by GitLab pods (webservice, gitaly, sidekiq, etc.)harbor- Used by Harbor pods (core, registry, jobservice, portal)monitoring- Used by monitoring resources (future)
Permissions Granted¶
# Role: gitlab-role
rules:
- apiGroups: [""]
resources: [secrets, configmaps]
verbs: [get, list, watch]
- apiGroups: [""]
resources: [pods, pods/log]
verbs: [get, list, watch]
Example Usage¶
const rbac = new RbacConstruct(this, 'rbac', {
namespace: 'gitlabbda',
});
// Reference ServiceAccount in other constructs
const gitlabSA = rbac.gitlabServiceAccount.name; // "gitlab"
Public Members¶
public readonly gitlabServiceAccount: KubeServiceAccount;
public readonly harborServiceAccount: KubeServiceAccount;
public readonly monitoringServiceAccount: KubeServiceAccount;
S3BucketsConstruct¶
Purpose: Provision 8 S3 buckets via Crossplane.
Source: constructs/s3-buckets.ts
Interface¶
export interface S3BucketsProps {
namespace: string; // Not used (buckets in crossplane-system)
buckets: {
artifacts: string;
uploads: string;
lfs: string;
pages: string;
registry: string;
backups: string;
postgresbackups: string;
cache: string;
};
}
Generated Resources¶
Bucket (8, Crossplane CRD) in
crossplane-systemnamespace
Bucket Configuration¶
All buckets use identical configuration:
apiVersion: s3.aws.upbound.io/v1beta2
kind: Bucket
metadata:
name: {bucket-name}
namespace: crossplane-system # NOT deployment namespace
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
forProvider:
region: fsn1 # Hetzner region
providerConfigRef:
name: hetzner-s3 # Infrastructure-managed ProviderConfig
managementPolicies: [Observe, Create, Delete] # Skip Update (no tagging)
deletionPolicy: Orphan # Safety: keep bucket on CR deletion
Buckets Created¶
Bucket |
Purpose |
Approximate Size (2-5 users) |
|---|---|---|
|
CI/CD artifacts |
5-20GB |
|
User uploads |
1-5GB |
|
Git LFS objects |
0-50GB (varies) |
|
GitLab Pages |
0.1-5GB |
|
Harbor images |
10-100GB |
|
GitLab backups |
20-50GB |
|
CNPG backups |
5-20GB |
|
Runner cache |
5-20GB |
Dependencies¶
Crossplane operator installed (cluster infrastructure)
provider-aws-s3 installed (Upbound provider)
ProviderConfig
hetzner-s3exists (cluster infrastructure)
Example Usage¶
const s3Buckets = new S3BucketsConstruct(this, 's3-buckets', {
namespace: 'gitlabbda',
buckets: {
artifacts: 'artifacts-gitlabbda-kup6s',
uploads: 'uploads-gitlabbda-kup6s',
// ... (8 total)
},
});
For complete S3 bucket details, see S3 Buckets Reference.
S3CredentialsConstruct¶
Purpose: Sync S3 credentials from application-secrets namespace via External Secrets Operator (ESO).
Source: constructs/s3-credentials.ts
Interface¶
export interface S3CredentialsProps {
namespace: string; // Target namespace for secrets
s3: {
endpoint: string;
region: string;
buckets: {
artifacts: string;
uploads: string;
lfs: string;
pages: string;
backups: string;
cache: string;
registry: string; // Harbor
postgresbackups: string; // CNPG
};
};
}
Generated Resources¶
ExternalSecret
gitlab-s3-credentials- GitLab S3 connection detailsExternalSecret
harbor-s3-credentials- Harbor registry S3 connection
Secrets Generated¶
gitlab-s3-credentials¶
Keys:
connection- GitLab S3 connection YAML (includes credentials, endpoint, buckets)s3cfg- s3cmd configuration (for Toolbox backups)AWS_ACCESS_KEY_ID- S3 access keyAWS_SECRET_ACCESS_KEY- S3 secret key
Used by: GitLab Webservice, Sidekiq, Toolbox, Pages
harbor-s3-credentials¶
Keys:
access-key-id- S3 access keysecret-access-key- S3 secret keyregion- S3 region (fsn1)bucket- Registry bucket nameendpoint- S3 endpoint URL
Used by: Harbor Registry
ClusterSecretStore Reference¶
Both ExternalSecrets reference application-secrets-store (cluster-wide):
spec:
secretStoreRef:
name: application-secrets-store
kind: ClusterSecretStore
data:
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
key: hetzner-s3 # Secret in application-secrets namespace
property: access-key-id
Example Usage¶
const s3Creds = new S3CredentialsConstruct(this, 's3-credentials', {
namespace: 'gitlabbda',
s3: config.s3,
});
For secrets architecture, see Secrets Reference.
AppSecretsConstruct¶
Purpose: Sync application secrets (SMTP, Harbor OAuth, Harbor registry) via ESO.
Source: constructs/app-secrets.ts
Interface¶
export interface AppSecretsProps {
namespace: string;
smtp: {
host: string;
port: number;
domain: string;
from: string;
replyTo: string;
};
}
Generated Resources¶
ExternalSecret
gitlab-smtp-password- SMTP credentialsExternalSecret
harbor-secrets- Harbor OAuth and registry secretExternalSecret
gitlab-initial-root-password- GitLab admin password
Secrets Generated¶
gitlab-smtp-password¶
Keys:
password- SMTP password (fromapplication-secrets/smtp)
Used by: GitLab Webservice (email delivery)
harbor-secrets¶
Keys:
gitlab-oauth-client-id- GitLab OAuth app IDgitlab-oauth-client-secret- GitLab OAuth app secretregistry-secret- Harbor internal secret (CORE_SECRET, JOBSERVICE_SECRET)
Used by: Harbor Core (OAuth authentication)
gitlab-initial-root-password¶
Keys:
password- GitLab root user password
Used by: GitLab initial setup (set root password)
Example Usage¶
const appSecrets = new AppSecretsConstruct(this, 'app-secrets', {
namespace: 'gitlabbda',
smtp: config.smtp,
});
DatabaseConstruct¶
Purpose: Deploy PostgreSQL cluster via CloudNativePG (CNPG).
Source: constructs/database.ts
Interface¶
export interface DatabaseProps {
namespace: string;
storageClass: string; // Longhorn storage class
storageSize: string; // PVC size (e.g., "10Gi")
s3BackupEndpoint: string; // S3 endpoint for backups
s3BackupRegion: string; // S3 region
s3BackupBucket: string; // Backup bucket name
}
Generated Resources¶
ObjectStore (Barman Cloud Plugin) - Wave 2
Cluster (CNPG) - Wave 3
Pooler (PgBouncer) - Wave 3
Cluster Specification¶
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: gitlab-postgres
spec:
instances: 2 # Primary + Standby
primaryUpdateStrategy: unsupervised # Auto-failover
postgresql:
parameters:
max_connections: "200"
shared_buffers: "256MB"
effective_cache_size: "1GB"
bootstrap:
initdb:
database: gitlab
owner: gitlab
postInitSQL:
- CREATE DATABASE harbor OWNER gitlab; # Harbor DB
storage:
storageClass: longhorn-redundant-app # 1 replica
size: 10Gi # Per instance
backup:
target: primary
retentionPolicy: 30d
plugins:
- name: barman-cloud.cloudnative-pg.io # S3 backups
resources:
requests: {memory: 256Mi, cpu: 100m}
limits: {memory: 512Mi, cpu: 500m}
monitoring:
enablePodMonitor: true # Prometheus scraping
affinity:
enablePodAntiAffinity: true # Spread across nodes
topologyKey: kubernetes.io/hostname
Pooler Specification¶
apiVersion: postgresql.cnpg.io/v1
kind: Pooler
metadata:
name: gitlab-postgres-pooler
spec:
cluster:
name: gitlab-postgres
instances: 2 # HA pooler
type: rw # Read-write pooler
pgbouncer:
poolMode: transaction # Connection pooling mode
parameters:
max_client_conn: "1000" # Max client connections
default_pool_size: "25" # Backend connections per user/db
Public Members¶
public readonly clusterName: string = 'gitlab-postgres';
public readonly objectStoreName: string = 'gitlab-postgres-backup';
Connection Details¶
Applications connect to: gitlab-postgres-pooler.gitlabbda.svc.cluster.local:5432
Databases created:
gitlab- GitLab dataharbor- Harbor data
User: gitlab (owner of both databases)
Password secret: gitlab-postgres-app (CNPG-generated, key: password)
Example Usage¶
const database = new DatabaseConstruct(this, 'database', {
namespace: 'gitlabbda',
storageClass: 'longhorn-redundant-app',
storageSize: '10Gi',
s3BackupEndpoint: 'https://fsn1.your-objectstorage.com',
s3BackupRegion: 'fsn1',
s3BackupBucket: 'postgresbackups-gitlabbda-kup6s',
});
// Use in GitLab configuration
const pgHost = `${database.clusterName}-pooler`; // "gitlab-postgres-pooler"
For PostgreSQL architecture, see GitLab Components: PostgreSQL.
RedisConstruct¶
Purpose: Deploy Redis single instance for cache and job queue.
Source: constructs/redis.ts
Interface¶
export interface RedisProps {
namespace: string;
storageClass: string; // Longhorn storage class
storageSize: string; // PVC size (e.g., "10Gi")
replicas?: number; // Default: 1
}
Generated Resources¶
PersistentVolumeClaim
redis-data- Wave 2StatefulSet
redis- Wave 2Service
redis(ClusterIP) - Wave 2
StatefulSet Specification¶
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 1
template:
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- --appendonly
- "yes"
- --save
- "60"
- "1"
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
resources:
requests: {cpu: 100m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
volumes:
- name: data
persistentVolumeClaim:
claimName: redis-data
Persistence Configuration¶
AOF:
--appendonly yes(every write logged)Snapshot:
--save 60 1(if ≥1 key changed in 60 seconds)
Public Members¶
public readonly service: KubeService;
Connection Details¶
Applications connect to: redis.gitlabbda.svc.cluster.local:6379
No authentication: GitLab and Harbor access Redis without password (within namespace).
Databases:
DB 0 - GitLab (sessions, cache, job queue)
DB 1 - Harbor JobService (job queue)
DB 2 - Harbor Registry (blob descriptor cache)
Example Usage¶
const redis = new RedisConstruct(this, 'redis', {
namespace: 'gitlabbda',
storageClass: 'longhorn', // 2 replicas
storageSize: '10Gi',
replicas: 1,
});
For Redis architecture, see GitLab Components: Redis.
GitLabHelmChart¶
Purpose: Render GitLab Helm chart to Kubernetes manifests using CDK8S.
Source: constructs/gitlab-helm.ts
Interface¶
export interface GitLabHelmProps {
namespace: string;
isFreshInstall: boolean; // Remove upgrade check hook if true
gitlabDomain: string;
pagesDomain: string;
registryDomain: string; // Not used (Harbor instead)
s3: {
endpoint: string;
region: string;
buckets: {
artifacts: string;
uploads: string;
lfs: string;
pages: string;
backups: string;
cache: string;
};
};
postgresql: {
host: string; # E.g., gitlab-postgres-pooler.gitlabbda.svc.cluster.local
port: number; # 5432
database: string; # gitlab
};
smtp: {
host: string;
port: number;
domain: string;
from: string;
replyTo: string;
};
}
Generated Resources¶
~100 resources including:
Deployment (webservice, gitaly, sidekiq, shell, pages, workhorse)
Service (webservice, gitaly, shell, pages)
Ingress (webservice, registry - disabled)
ConfigMap (20+)
Secret (10+)
ServiceAccount
Role, RoleBinding
HorizontalPodAutoscaler
PodDisruptionBudget
Helm Chart Rendering Process¶
// 1. Build Helm values object
const helmValues = {
global: {
edition: 'ce',
hosts: { gitlab: { name: gitlabDomain }, ... },
psql: { host, port, database, ... },
redis: { host: 'redis.gitlabbda.svc', ... },
minio: { enabled: false }, // Use S3 instead
},
postgresql: { install: false }, // Use CNPG instead
redis: { install: false }, // Use dedicated Redis
registry: { enabled: false }, // Use Harbor instead
gitlab: {
webservice: { minReplicas: 2, ... },
gitaly: { persistence: { storageClass: 'hcloud-volumes', size: '20Gi' } },
...
},
};
// 2. Write values to temp file
writeFileSync('/tmp/gitlab-helm-values.yaml', JSON.stringify(helmValues));
// 3. Render Helm chart to YAML
execSync(`helm template gitlab gitlab/gitlab --values /tmp/gitlab-helm-values.yaml > /tmp/gitlab-rendered.yaml`);
// 4. Post-process YAML (fix upgrade hook, add sync waves)
let yaml = readFileSync('/tmp/gitlab-rendered.yaml');
yaml = removeUpgradeCheckHook(yaml, isFreshInstall);
yaml = addSyncWaves(yaml);
// 5. Include rendered YAML in CDK8S
new Include(this, 'gitlab-manifests', {
url: `/tmp/gitlab-rendered.yaml`,
});
Key Helm Values¶
Disabled built-ins:
postgresql: {install: false} # Use CNPG
redis: {install: false} # Use dedicated Redis
registry: {enabled: false} # Use Harbor
minio: {enabled: false} # Use Hetzner S3
prometheus: {install: false} # Use cluster Prometheus
External dependencies:
global:
psql:
host: gitlab-postgres-pooler
password: {secret: gitlab-postgres-app, key: password}
redis:
host: redis.gitlabbda.svc
appConfig:
lfs: {bucket: lfs-gitlabbda-kup6s, connection: {secret: gitlab-s3-credentials}}
artifacts: {bucket: artifacts-gitlabbda-kup6s, ...}
uploads: {bucket: uploads-gitlabbda-kup6s, ...}
pages: {bucket: pages-gitlabbda-kup6s, ...}
Example Usage¶
const gitlabHelm = new GitLabHelmChart(this, 'gitlab-helm', {
namespace: 'gitlabbda',
isFreshInstall: false,
gitlabDomain: 'gitlab.staging.bluedynamics.eu',
pagesDomain: 'pages.staging.bluedynamics.eu',
registryDomain: 'registry.staging.bluedynamics.eu', # Not used
s3: config.s3,
postgresql: {
host: 'gitlab-postgres-pooler.gitlabbda.svc.cluster.local',
port: 5432,
database: 'gitlab',
},
smtp: config.smtp,
});
For Helm integration details, see CDK8S Approach: Helm Integration.
Harbor Constructs¶
Harbor is deployed via 3 constructs: Config, Core, Ingress.
HarborConfigConstruct¶
Purpose: Generate ConfigMaps for Harbor components.
Source: constructs/harbor-config.ts
Interface¶
export interface HarborConfigProps {
namespace: string;
harborDomain: string;
}
Generated Resources¶
ConfigMap
harbor-registry-config- Docker Registry v2 configurationConfigMap
harbor-jobservice-config- JobService worker pool configurationConfigMap
harbor-portal-config- Nginx reverse proxy configuration
Example Config¶
Registry ConfigMap:
# Docker Registry v2 config.yml
storage:
s3:
region: ${REGISTRY_STORAGE_S3_REGION}
bucket: ${REGISTRY_STORAGE_S3_BUCKET}
accesskey: ${REGISTRY_STORAGE_S3_ACCESSKEY}
secretkey: ${REGISTRY_STORAGE_S3_SECRETKEY}
regionendpoint: ${REGISTRY_STORAGE_S3_REGIONENDPOINT}
cache:
blobdescriptor: redis # Cache in Redis DB 2
redis:
addr: redis:6379
db: 2
HarborConstruct¶
Purpose: Deploy Harbor microservices (Core, Registry, JobService, Portal).
Source: constructs/harbor.ts
Interface¶
export interface HarborProps {
namespace: string;
serviceAccountName: string; # From RbacConstruct
harborDomain: string;
gitlabDomain: string; # For OAuth
harborVersion: string; # E.g., v2.14.0
}
Generated Resources¶
Deployment
harbor-core- API serverDeployment
harbor-registry- OCI image storageDeployment
harbor-jobservice- Background jobsDeployment
harbor-portal- Web UI (nginx)Service (4, ClusterIP) - One per deployment
Core Deployment¶
Key environment variables:
env:
# Database
- name: POSTGRESQL_HOST
value: gitlab-postgres-pooler
- name: POSTGRESQL_DATABASE
value: harbor
# Redis
- name: REDIS_HOST
value: redis
# OAuth
- name: AUTH_MODE
value: oidc_auth
- name: OIDC_ENDPOINT
value: https://gitlab.staging.bluedynamics.eu
- name: OIDC_CLIENT_ID
valueFrom: {secretKeyRef: {name: harbor-secrets, key: gitlab-oauth-client-id}}
Node placement:
nodeSelector:
kubernetes.io/arch: amd64 # Harbor images AMD64-only
tolerations:
- key: kubernetes.io/arch
operator: Equal
value: amd64
effect: NoSchedule
Public Members¶
public readonly coreService: KubeService;
public readonly portalService: KubeService;
HarborIngressConstruct¶
Purpose: Create Ingress for Harbor web UI and Docker API.
Source: constructs/harbor-ingress.ts
Interface¶
export interface HarborIngressProps {
namespace: string;
harborDomain: string;
}
Generated Resources¶
Ingress
harbor-ingress- HTTPS trafficIngressRouteTCP (via Traefik CRD) - Docker Registry v2 API
Ingress Specification¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: harbor-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
tls:
- hosts: [registry.staging.bluedynamics.eu]
secretName: harbor-tls
rules:
- host: registry.staging.bluedynamics.eu
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: harbor-portal
port: {number: 8080}
For Harbor architecture, see Harbor Integration.
PagesIngressConstruct¶
Purpose: Wildcard ingress for GitLab Pages static sites.
Source: constructs/pages-ingress.ts
Interface¶
export interface PagesIngressProps {
namespace: string;
pagesDomain: string; # E.g., pages.staging.bluedynamics.eu
}
Generated Resources¶
Ingress
gitlab-pages-ingress(wildcard)
Ingress Specification¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitlab-pages-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
tls:
- hosts: ['*.pages.staging.bluedynamics.eu']
secretName: gitlab-pages-tls
rules:
- host: '*.pages.staging.bluedynamics.eu'
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitlab-gitlab-pages
port: {number: 8090}
Wildcard DNS required: *.pages.staging.bluedynamics.eu must resolve to cluster LoadBalancer.
Example Usage¶
new PagesIngressConstruct(this, 'pages-ingress', {
namespace: 'gitlabbda',
pagesDomain: 'pages.staging.bluedynamics.eu',
});
GitLabSshRoutingConstruct¶
Purpose: Route SSH traffic (port 22) to GitLab Shell via Traefik.
Source: constructs/gitlab-ssh-routing.ts
Interface¶
export interface GitLabSshRoutingProps {
namespace: string;
}
Generated Resources¶
IngressRouteTCP
gitlab-ssh(Traefik CRD)
IngressRouteTCP Specification¶
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: gitlab-ssh
spec:
entryPoints: [ssh] # Traefik SSH entrypoint (port 22)
routes:
- match: HostSNI(`*`) # All SSH traffic
services:
- name: gitlab-gitlab-shell
port: 22
Why Traefik TCP routing?
Cost savings - No separate LoadBalancer for SSH (shares Traefik LB)
Consistent ingress - All traffic (HTTP, HTTPS, SSH) through single entry point
Traefik entrypoint configuration (cluster infrastructure):
# Traefik Helm values
ports:
ssh:
port: 22
expose: true
exposedPort: 22
protocol: TCP
Example Usage¶
new GitLabSshRoutingConstruct(this, 'ssh-routing', {
namespace: 'gitlabbda',
});
For SSH access, see Endpoints & Ports Reference.
MonitoringConstruct¶
Purpose: Create ServiceMonitors for Prometheus scraping.
Source: constructs/monitoring.ts
Interface¶
export interface MonitoringProps {
namespace: string;
}
Generated Resources¶
ServiceMonitor
gitlab-postgres(Prometheus Operator CRD)ServiceMonitor
harbor-core(future)
ServiceMonitor Specification¶
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: gitlab-postgres
spec:
selector:
matchLabels:
cnpg.io/cluster: gitlab-postgres
endpoints:
- port: metrics
interval: 30s
path: /metrics
Metrics collected:
PostgreSQL: Connections, queries, replication lag, disk usage
Harbor: (Future) API requests, image pulls/pushes, scan results
Example Usage¶
new MonitoringConstruct(this, 'monitoring', {
namespace: 'gitlabbda',
});
For monitoring setup, see Monitoring & Observability (future).
Sync Wave Strategy¶
ArgoCD sync waves ensure resources are created in dependency order:
Wave |
Resources |
Purpose |
|---|---|---|
0 |
Namespace |
Namespace must exist first |
1 |
RBAC, S3 Buckets, S3 Credentials |
Infrastructure and credentials |
2 |
App Secrets, Redis, ObjectStore (CNPG) |
Dependencies for applications |
3 |
PostgreSQL Cluster, Pooler |
Database ready for applications |
4 |
GitLab, Harbor |
Applications (depend on DB, Redis, S3) |
5 |
Ingresses |
External access (after applications ready) |
6 |
Monitoring |
Observability (after everything deployed) |
For sync wave details, see ArgoCD GitOps Workflow.
Type Safety¶
All constructs are type-checked at build time:
// TypeScript catches errors:
const database = new DatabaseConstruct(this, 'db', {
storageSize: 10, // ERROR: Type 'number' not assignable to 'string'
});
// Correct:
const database = new DatabaseConstruct(this, 'db', {
storageSize: '10Gi', // OK: string with Kubernetes quantity format
});
For type safety benefits, see CDK8S Approach: Type Safety.
Summary¶
15 CDK8S constructs generate ~150 Kubernetes resources:
Infrastructure (4): Namespace, RBAC, S3 Buckets, S3 Credentials
Secrets (1): App Secrets (SMTP, OAuth, passwords)
Databases (2): PostgreSQL (CNPG), Redis
Applications (2): GitLab (Helm), Harbor (custom)
Configuration (1): Harbor ConfigMaps
Ingress (3): Harbor, GitLab Pages, SSH routing
Monitoring (1): ServiceMonitors
Key patterns:
Separation of concerns - Each construct handles one responsibility
Dependency injection - Constructs receive dependencies via props
Type safety - TypeScript prevents configuration errors
Sync waves - Resources created in correct order via annotations
For usage examples, see:
CDK8S Approach - Architecture and rationale
Configuration Reference - Configuration values
GitLab Components - Component architecture