From 1c948d357d97bf4b5b1c3293f3355a55874f35b8 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 20 Oct 2025 23:01:07 +0100 Subject: [PATCH 01/25] feat: created kubernetes namespace --- k8s/00-namespace.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 k8s/00-namespace.yml diff --git a/k8s/00-namespace.yml b/k8s/00-namespace.yml new file mode 100644 index 0000000..4dcca1a --- /dev/null +++ b/k8s/00-namespace.yml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: aviation \ No newline at end of file From d0740b2ad40f0b0ebc69996cfb4c1307210149e9 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 20 Oct 2025 23:02:37 +0100 Subject: [PATCH 02/25] feat: created kubernetes manifests for the flights service --- k8s/flights/cache.yml | 36 ++++++++++++++++++++++ k8s/flights/database.yml | 56 +++++++++++++++++++++++++++++++++ k8s/flights/migrations.yml | 37 ++++++++++++++++++++++ k8s/flights/service.yml | 63 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 k8s/flights/cache.yml create mode 100644 k8s/flights/database.yml create mode 100644 k8s/flights/migrations.yml create mode 100644 k8s/flights/service.yml diff --git a/k8s/flights/cache.yml b/k8s/flights/cache.yml new file mode 100644 index 0000000..354ed88 --- /dev/null +++ b/k8s/flights/cache.yml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-cache + namespace: aviation +spec: + ports: + - port: 6379 + selector: + app: flights-cache +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flights-cache + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: flights-cache + template: + metadata: + labels: + app: flights-cache + spec: + containers: + - name: redis + image: redis:8.2 + ports: + - containerPort: 6379 + readinessProbe: + exec: + command: [ "redis-cli","ping" ] + initialDelaySeconds: 5 + periodSeconds: 5 \ No newline at end of file diff --git a/k8s/flights/database.yml b/k8s/flights/database.yml new file mode 100644 index 0000000..e088fbe --- /dev/null +++ b/k8s/flights/database.yml @@ -0,0 +1,56 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-database + namespace: aviation +spec: + clusterIP: None + ports: + - port: 5432 + selector: + app: flights-database +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: flights-database + namespace: aviation +spec: + serviceName: flights-database + replicas: 1 + selector: + matchLabels: + app: flights-database + template: + metadata: + labels: + app: flights-database + spec: + containers: + - name: postgres + image: postgres:17.6 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: flights + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + value: postgres + readinessProbe: + exec: + command: [ "pg_isready","-U","postgres","-d","flights" ] + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/flights/migrations.yml b/k8s/flights/migrations.yml new file mode 100644 index 0000000..4c2951d --- /dev/null +++ b/k8s/flights/migrations.yml @@ -0,0 +1,37 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: flights-migrations + namespace: aviation +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for Postgres to become available..." + until nc -z flights-database.aviation.svc.cluster.local 5432; do + echo "Still waiting for DB..."; sleep 2; + done + echo "Database is ready!" + containers: + - name: migrate + image: migrate/migrate:4 + command: + - sh + - -c + - | + set -e + echo "Cloning migration repo..." + apk add --no-cache git curl >/dev/null + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Running migrations..." + migrate -path /repo/services/flights/migrations \ + -database "postgres://postgres:postgres@flights-database:5432/flights?sslmode=disable" up + echo "Migrations completed successfully." \ No newline at end of file diff --git a/k8s/flights/service.yml b/k8s/flights/service.yml new file mode 100644 index 0000000..3c8c5c3 --- /dev/null +++ b/k8s/flights/service.yml @@ -0,0 +1,63 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-service + namespace: aviation +spec: + ports: + - port: 8081 + selector: + app: flights-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flights-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: flights-service + template: + metadata: + labels: + app: flights-service + spec: + initContainers: + - name: wait-for-db + image: busybox + command: [ "sh", "-c", "until nc -z flights-database.aviation.svc.cluster.local 5432; do sleep 2; done;" ] + - name: wait-for-cache + image: busybox + command: [ "sh", "-c", "until nc -z flights-cache.aviation.svc.cluster.local 6379; do sleep 2; done;" ] + containers: + - name: flights-service + image: ghcr.io/edinstance/distributed-aviation-system-services/flights:latest + ports: + - containerPort: 8081 + env: + - name: DATABASE_URL + value: "postgres://postgres:postgres@flights-database:5432/flights?sslmode=disable" + - name: CACHE_URL + value: "redis://flights-cache:6379" + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "8081" + - name: AIRCRAFT_SERVICE_GRPC_URL + value: host.docker.internal:9090 + - name: OTLP_GRPC_URL + value: host.docker.internal:4317 + - name: KAFKA_BROKER_URL + value: host.docker.internal:9092 + - name: KAFKA_SCHEMA_REGISTRY_URL + value: http://host.docker.internal:8081 + - name: KAFKA_FLIGHTS_TOPIC + value: flights + readinessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 10 + periodSeconds: 10 \ No newline at end of file From e5eb74bcff0f27205760935783ebe8964d7bf50a Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 20 Oct 2025 23:02:51 +0100 Subject: [PATCH 03/25] docs: created kubernetes readme --- k8s/README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 k8s/README.md diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000..780887c --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,82 @@ +# Kubernetes Deployment + +This directory contains Kubernetes manifests for deploying the distributed aviation system components. + + + +## Components + +### Namespace + +- **File**: `00-namespace.yml` +- **Purpose**: Creates the `aviation` namespace for all resources + +### Flights Service Stack + +Located in the `flights/` directory: + +#### Database + +- **Type**: PostgreSQL 17.6 StatefulSet +- **Storage**: 1Gi persistent volume +- **Port**: 5432 +- **Credentials**: postgres/postgres +- **Database**: flights + +#### Cache + +- **Type**: Redis 8.2 Deployment +- **Port**: 6379 +- **Purpose**: Caching layer for flights service + +#### Migrations + +- **Type**: Job +- **Image**: `migrate:migrate` +- **Dependencies**: Waits for database to be ready + +#### Service + +- **Type**: Deployment with Service +- **Port**: 8081 +- **Image**: `ghcr.io/edinstance/distributed-aviation-system-services/flights:latest` +- **Dependencies**: Waits for database, migrations and cache to be ready +- **Health Check**: `/health` endpoint + +## Deployment + +1. Apply the namespace first: + ```bash + kubectl apply -f 00-namespace.yml + ``` + +2. Deploy the flights stack: + ```bash + kubectl apply -f flights/ + ``` + +3. Verify deployment: + ```bash + kubectl get pods -n aviation + ``` + +Or you can deploy everything with: + +```bash +kubectl apply -R -f k8s/ +``` + +## Environment Variables + +The flights service is configured with: + +- Database connection to internal PostgreSQL +- Redis cache connection +- Kafka broker and schema registry endpoints +- OTLP observability endpoint +- gRPC aircraft service endpoint + +## Notes + +- All services run in the `aviation` namespace +- Database uses persistent storage via StatefulSet From 11657866dc8d3fad9322bd0948436013c43d1cd8 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 20 Oct 2025 23:36:48 +0100 Subject: [PATCH 04/25] feat: setup aircraft in kubernetes --- k8s/aircraft/cache.yml | 36 +++++++++++++++++ k8s/aircraft/database.yml | 56 +++++++++++++++++++++++++++ k8s/aircraft/migrations.yml | 57 +++++++++++++++++++++++++++ k8s/aircraft/service.yml | 77 +++++++++++++++++++++++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 k8s/aircraft/cache.yml create mode 100644 k8s/aircraft/database.yml create mode 100644 k8s/aircraft/migrations.yml create mode 100644 k8s/aircraft/service.yml diff --git a/k8s/aircraft/cache.yml b/k8s/aircraft/cache.yml new file mode 100644 index 0000000..69ece02 --- /dev/null +++ b/k8s/aircraft/cache.yml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Service +metadata: + name: aircraft-cache + namespace: aviation +spec: + ports: + - port: 6379 + selector: + app: aircraft-cache +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: aircraft-cache + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: aircraft-cache + template: + metadata: + labels: + app: aircraft-cache + spec: + containers: + - name: redis + image: redis:8.2 + ports: + - containerPort: 6379 + readinessProbe: + exec: + command: [ "redis-cli","ping" ] + initialDelaySeconds: 5 + periodSeconds: 5 \ No newline at end of file diff --git a/k8s/aircraft/database.yml b/k8s/aircraft/database.yml new file mode 100644 index 0000000..4efd74b --- /dev/null +++ b/k8s/aircraft/database.yml @@ -0,0 +1,56 @@ +apiVersion: v1 +kind: Service +metadata: + name: aircraft-database + namespace: aviation +spec: + clusterIP: None + ports: + - port: 5432 + selector: + app: aircraft-database +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: aircraft-database + namespace: aviation +spec: + serviceName: aircraft-database + replicas: 1 + selector: + matchLabels: + app: aircraft-database + template: + metadata: + labels: + app: aircraft-database + spec: + containers: + - name: postgres + image: postgres:17.6 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: aircraft + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + value: postgres + readinessProbe: + exec: + command: [ "pg_isready","-U","postgres","-d","aircraft" ] + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/aircraft/migrations.yml b/k8s/aircraft/migrations.yml new file mode 100644 index 0000000..6a0f1d1 --- /dev/null +++ b/k8s/aircraft/migrations.yml @@ -0,0 +1,57 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: aircraft-migrations + namespace: aviation +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for Postgres to become available..." + until nc -z aircraft-database.aviation.svc.cluster.local 5432; do + echo "Still waiting for DB..."; sleep 2; + done + echo "Database is ready!" + - name: fetch-repo + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning Liquibase project repo..." + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Repository cloned successfully." + volumeMounts: + - name: repo-volume + mountPath: /repo + containers: + - name: liquibase + image: liquibase/liquibase:4.31 + command: + - sh + - -c + - | + set -e + echo "Running Liquibase migrations..." + cd /repo/services/aircraft/src/main/resources/db + liquibase \ + --url=jdbc:postgresql://aircraft-database:5432/aircraft \ + --username=postgres \ + --password=postgres \ + --changelog-file=changelog/db.changelog-master.xml \ + update + echo "Liquibase migrations completed successfully." + volumeMounts: + - name: repo-volume + mountPath: /repo + volumes: + - name: repo-volume + emptyDir: {} \ No newline at end of file diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml new file mode 100644 index 0000000..9879114 --- /dev/null +++ b/k8s/aircraft/service.yml @@ -0,0 +1,77 @@ +apiVersion: v1 +kind: Service +metadata: + name: aircraft-service + namespace: aviation +spec: + ports: + - port: 8080 + selector: + app: aircraft-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: aircraft-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: aircraft-service + template: + metadata: + labels: + app: aircraft-service + spec: + initContainers: + - name: wait-for-db + image: busybox + command: [ "sh", "-c", "until nc -z aircraft-database.aviation.svc.cluster.local 5432; do sleep 2; done;" ] + - name: wait-for-cache + image: busybox + command: [ "sh", "-c", "until nc -z aircraft-cache.aviation.svc.cluster.local 6379; do sleep 2; done;" ] + containers: + - name: aircraft-service + image: ghcr.io/edinstance/distributed-aviation-system-services/aircraft:latest + ports: + - containerPort: 8080 + env: + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "8080" + - name: GRPC_PORT + value: "9090" + - name: DATABASE_URL + value: "jdbc:postgresql://aircraft-database:5432/aircraft" + - name: DATABASE_USERNAME + value: "postgres" + - name: DATABASE_PASSWORD + value: "postgres" + - name: CACHE_URL + value: "redis://aircraft-cache:6379" + - name: LIQUIBASE_ENABLED + value: "false" + - name: OTEL_SERVICE_NAME + value: "aircraft-service" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://host.docker.internal:4317" + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: "grpc" + - name: OTEL_TRACES_EXPORTER + value: "otlp" + - name: OTEL_METRICS_EXPORTER + value: "otlp" + - name: OTEL_LOGS_EXPORTER + value: "otlp" + - name: OTEL_METRIC_EXPORT_INTERVAL + value: "5000" + - name: OTEL_BSP_SCHEDULE_DELAY + value: "5000" + readinessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 \ No newline at end of file From ac4ea0943a61c4a52592b03deb8f7db28f0378b4 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 20 Oct 2025 23:36:57 +0100 Subject: [PATCH 05/25] docs: updated k8s docs --- k8s/README.md | 32 -------------------------------- k8s/aircraft/README.md | 29 +++++++++++++++++++++++++++++ k8s/flights/README.md | 29 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 k8s/aircraft/README.md create mode 100644 k8s/flights/README.md diff --git a/k8s/README.md b/k8s/README.md index 780887c..5b1e0b7 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -11,38 +11,6 @@ This directory contains Kubernetes manifests for deploying the distributed aviat - **File**: `00-namespace.yml` - **Purpose**: Creates the `aviation` namespace for all resources -### Flights Service Stack - -Located in the `flights/` directory: - -#### Database - -- **Type**: PostgreSQL 17.6 StatefulSet -- **Storage**: 1Gi persistent volume -- **Port**: 5432 -- **Credentials**: postgres/postgres -- **Database**: flights - -#### Cache - -- **Type**: Redis 8.2 Deployment -- **Port**: 6379 -- **Purpose**: Caching layer for flights service - -#### Migrations - -- **Type**: Job -- **Image**: `migrate:migrate` -- **Dependencies**: Waits for database to be ready - -#### Service - -- **Type**: Deployment with Service -- **Port**: 8081 -- **Image**: `ghcr.io/edinstance/distributed-aviation-system-services/flights:latest` -- **Dependencies**: Waits for database, migrations and cache to be ready -- **Health Check**: `/health` endpoint - ## Deployment 1. Apply the namespace first: diff --git a/k8s/aircraft/README.md b/k8s/aircraft/README.md new file mode 100644 index 0000000..0e44af6 --- /dev/null +++ b/k8s/aircraft/README.md @@ -0,0 +1,29 @@ +### Aircraft Service Stack + +#### Database + +- **Type**: PostgreSQL 17.6 StatefulSet +- **Storage**: 1Gi persistent volume +- **Port**: 5432 +- **Credentials**: postgres/postgres +- **Database**: aircraft + +#### Cache + +- **Type**: Redis 8.2 Deployment +- **Port**: 6379 +- **Purpose**: Caching layer for aircraft service + +#### Migrations + +- **Type**: Job +- **Image**: `liquibase/liquibase:4.31` +- **Dependencies**: Waits for database to be ready + +#### Service + +- **Type**: Deployment with Service +- **Port**: 8080 +- **Image**: `ghcr.io/edinstance/distributed-aviation-system-services/aircraft:latest` +- **Dependencies**: Waits for database, migrations and cache to be ready +- **Health Check**: `/health` endpoint diff --git a/k8s/flights/README.md b/k8s/flights/README.md new file mode 100644 index 0000000..ec7ac32 --- /dev/null +++ b/k8s/flights/README.md @@ -0,0 +1,29 @@ +### Flights Service Stack + +#### Database + +- **Type**: PostgreSQL 17.6 StatefulSet +- **Storage**: 1Gi persistent volume +- **Port**: 5432 +- **Credentials**: postgres/postgres +- **Database**: flights + +#### Cache + +- **Type**: Redis 8.2 Deployment +- **Port**: 6379 +- **Purpose**: Caching layer for flights service + +#### Migrations + +- **Type**: Job +- **Image**: `migrate:migrate` +- **Dependencies**: Waits for database to be ready + +#### Service + +- **Type**: Deployment with Service +- **Port**: 8081 +- **Image**: `ghcr.io/edinstance/distributed-aviation-system-services/flights:latest` +- **Dependencies**: Waits for database, migrations and cache to be ready +- **Health Check**: `/health` endpoint From 0b55f2e7afed06a1998b2a232a8b1fa5249aeffc Mon Sep 17 00:00:00 2001 From: edinstance Date: Tue, 21 Oct 2025 00:20:22 +0100 Subject: [PATCH 06/25] feat: added ingress controlling and updated services --- k8s/01-ingress-controller.yml | 673 ++++++++++++++++++++++++++++++++++ k8s/02-ingress.yml | 41 +++ k8s/aircraft/service.yml | 5 +- k8s/flights/service.yml | 3 + 4 files changed, 721 insertions(+), 1 deletion(-) create mode 100644 k8s/01-ingress-controller.yml create mode 100644 k8s/02-ingress.yml diff --git a/k8s/01-ingress-controller.yml b/k8s/01-ingress-controller.yml new file mode 100644 index 0000000..a667894 --- /dev/null +++ b/k8s/01-ingress-controller.yml @@ -0,0 +1,673 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + name: ingress-nginx +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx + namespace: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - coordination.k8s.io + resourceNames: + - ingress-nginx-leader + resources: + - leases + verbs: + - get + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission + namespace: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + - namespaces + verbs: + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission +rules: + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx + namespace: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx +subjects: + - kind: ServiceAccount + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission + namespace: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx-admission +subjects: + - kind: ServiceAccount + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx +subjects: + - kind: ServiceAccount + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx-admission +subjects: + - kind: ServiceAccount + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: v1 +data: null +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller + namespace: ingress-nginx +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller + namespace: ingress-nginx +spec: + externalTrafficPolicy: Local + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - appProtocol: http + name: http + port: 80 + protocol: TCP + targetPort: http + - appProtocol: https + name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + type: LoadBalancer +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller-admission + namespace: ingress-nginx +spec: + ports: + - appProtocol: https + name: https-webhook + port: 443 + targetPort: webhook + selector: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller + namespace: ingress-nginx +spec: + minReadySeconds: 0 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + strategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + spec: + automountServiceAccountToken: true + containers: + - args: + - /nginx-ingress-controller + - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller + - --election-id=ingress-nginx-leader + - --controller-class=k8s.io/ingress-nginx + - --ingress-class=nginx + - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller + - --validating-webhook=:8443 + - --validating-webhook-certificate=/usr/local/certificates/cert + - --validating-webhook-key=/usr/local/certificates/key + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + image: registry.k8s.io/ingress-nginx/controller:v1.13.3@sha256:1b044f6dcac3afbb59e05d98463f1dec6f3d3fb99940bc12ca5d80270358e3bd + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /wait-shutdown + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: controller + ports: + - containerPort: 80 + name: http + protocol: TCP + - containerPort: 443 + name: https + protocol: TCP + - containerPort: 8443 + name: webhook + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: false + runAsGroup: 82 + runAsNonRoot: true + runAsUser: 101 + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /usr/local/certificates/ + name: webhook-cert + readOnly: true + dnsPolicy: ClusterFirst + nodeSelector: + kubernetes.io/os: linux + serviceAccountName: ingress-nginx + terminationGracePeriodSeconds: 300 + volumes: + - name: webhook-cert + secret: + secretName: ingress-nginx-admission +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-create + namespace: ingress-nginx +spec: + template: + metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-create + spec: + automountServiceAccountToken: true + containers: + - args: + - create + - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name=ingress-nginx-admission + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.3@sha256:3d671cf20a35cd94efc5dcd484970779eb21e7938c98fbc3673693b8a117cf39 + imagePullPolicy: IfNotPresent + name: create + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + ttlSecondsAfterFinished: 0 +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-patch + namespace: ingress-nginx +spec: + template: + metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-patch + spec: + automountServiceAccountToken: true + containers: + - args: + - patch + - --webhook-name=ingress-nginx-admission + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name=ingress-nginx-admission + - --patch-failure-policy=Fail + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.3@sha256:3d671cf20a35cd94efc5dcd484970779eb21e7938c98fbc3673693b8a117cf39 + imagePullPolicy: IfNotPresent + name: patch + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + ttlSecondsAfterFinished: 0 +--- +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: nginx +spec: + controller: k8s.io/ingress-nginx +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: ingress-nginx-controller-admission + namespace: ingress-nginx + path: /networking/v1/ingresses + port: 443 + failurePolicy: Fail + matchPolicy: Equivalent + name: validate.nginx.ingress.kubernetes.io + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + sideEffects: None \ No newline at end of file diff --git a/k8s/02-ingress.yml b/k8s/02-ingress.yml new file mode 100644 index 0000000..e962270 --- /dev/null +++ b/k8s/02-ingress.yml @@ -0,0 +1,41 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: aviation-ingress + namespace: aviation + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$1 +spec: + ingressClassName: nginx + rules: + - host: api.aviation.local + http: + paths: + - path: /flights/(.*) + pathType: ImplementationSpecific + backend: + service: + name: flights-service + port: + number: 8081 + - path: /flights + pathType: Prefix + backend: + service: + name: flights-service + port: + number: 8081 + - path: /aircraft/(.*) + pathType: ImplementationSpecific + backend: + service: + name: aircraft-service + port: + number: 8080 + - path: /aircraft + pathType: Prefix + backend: + service: + name: aircraft-service + port: + number: 8080 \ No newline at end of file diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml index 9879114..a7b34b1 100644 --- a/k8s/aircraft/service.yml +++ b/k8s/aircraft/service.yml @@ -4,8 +4,11 @@ metadata: name: aircraft-service namespace: aviation spec: + type: ClusterIP ports: - port: 8080 + targetPort: 8080 + protocol: TCP selector: app: aircraft-service --- @@ -71,7 +74,7 @@ spec: value: "5000" readinessProbe: httpGet: - path: /health + path: /details/health port: 8080 initialDelaySeconds: 10 periodSeconds: 10 \ No newline at end of file diff --git a/k8s/flights/service.yml b/k8s/flights/service.yml index 3c8c5c3..1ebc9c3 100644 --- a/k8s/flights/service.yml +++ b/k8s/flights/service.yml @@ -4,8 +4,11 @@ metadata: name: flights-service namespace: aviation spec: + type: ClusterIP ports: - port: 8081 + targetPort: 8081 + protocol: TCP selector: app: flights-service --- From 682c805f006b1da5a505997a7adade14201de9fe Mon Sep 17 00:00:00 2001 From: edinstance Date: Tue, 21 Oct 2025 00:40:06 +0100 Subject: [PATCH 07/25] feat: configured resources for services --- k8s/aircraft/cache.yml | 9 ++++++++- k8s/aircraft/database.yml | 7 +++++++ k8s/aircraft/service.yml | 9 ++++++++- k8s/flights/cache.yml | 9 ++++++++- k8s/flights/database.yml | 7 +++++++ k8s/flights/service.yml | 9 ++++++++- 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/k8s/aircraft/cache.yml b/k8s/aircraft/cache.yml index 69ece02..c37a03f 100644 --- a/k8s/aircraft/cache.yml +++ b/k8s/aircraft/cache.yml @@ -33,4 +33,11 @@ spec: exec: command: [ "redis-cli","ping" ] initialDelaySeconds: 5 - periodSeconds: 5 \ No newline at end of file + periodSeconds: 5 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/aircraft/database.yml b/k8s/aircraft/database.yml index 4efd74b..554d63c 100644 --- a/k8s/aircraft/database.yml +++ b/k8s/aircraft/database.yml @@ -46,6 +46,13 @@ spec: volumeMounts: - name: postgres-data mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi volumeClaimTemplates: - metadata: name: postgres-data diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml index a7b34b1..5f73f0d 100644 --- a/k8s/aircraft/service.yml +++ b/k8s/aircraft/service.yml @@ -77,4 +77,11 @@ spec: path: /details/health port: 8080 initialDelaySeconds: 10 - periodSeconds: 10 \ No newline at end of file + periodSeconds: 10 + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/flights/cache.yml b/k8s/flights/cache.yml index 354ed88..5eb46f9 100644 --- a/k8s/flights/cache.yml +++ b/k8s/flights/cache.yml @@ -33,4 +33,11 @@ spec: exec: command: [ "redis-cli","ping" ] initialDelaySeconds: 5 - periodSeconds: 5 \ No newline at end of file + periodSeconds: 5 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/flights/database.yml b/k8s/flights/database.yml index e088fbe..df244a8 100644 --- a/k8s/flights/database.yml +++ b/k8s/flights/database.yml @@ -46,6 +46,13 @@ spec: volumeMounts: - name: postgres-data mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi volumeClaimTemplates: - metadata: name: postgres-data diff --git a/k8s/flights/service.yml b/k8s/flights/service.yml index 1ebc9c3..f70d595 100644 --- a/k8s/flights/service.yml +++ b/k8s/flights/service.yml @@ -63,4 +63,11 @@ spec: path: /health port: 8081 initialDelaySeconds: 10 - periodSeconds: 10 \ No newline at end of file + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file From 2a4e257c1a8ac6f4fd487fdd4ea22c6111e77fff Mon Sep 17 00:00:00 2001 From: edinstance Date: Tue, 21 Oct 2025 20:47:53 +0100 Subject: [PATCH 08/25] feat!: created authentication k8s config and added fixes to auth --- k8s/02-ingress.yml | 16 +- k8s/authentication/database.yml | 63 ++++++++ k8s/authentication/keygen.yml | 63 ++++++++ k8s/authentication/migrations.yml | 74 +++++++++ k8s/authentication/secrets.yml | 9 ++ k8s/authentication/service.yml | 141 ++++++++++++++++++ .../authentication/authentication/settings.py | 16 +- services/authentication/docker-compose.yml | 6 +- 8 files changed, 384 insertions(+), 4 deletions(-) create mode 100644 k8s/authentication/database.yml create mode 100644 k8s/authentication/keygen.yml create mode 100644 k8s/authentication/migrations.yml create mode 100644 k8s/authentication/secrets.yml create mode 100644 k8s/authentication/service.yml diff --git a/k8s/02-ingress.yml b/k8s/02-ingress.yml index e962270..7a1d276 100644 --- a/k8s/02-ingress.yml +++ b/k8s/02-ingress.yml @@ -38,4 +38,18 @@ spec: service: name: aircraft-service port: - number: 8080 \ No newline at end of file + number: 8080 + - path: /auth/(.*) + pathType: ImplementationSpecific + backend: + service: + name: authentication-service + port: + number: 8000 + - path: /auth + pathType: Prefix + backend: + service: + name: authentication-service + port: + number: 8000 \ No newline at end of file diff --git a/k8s/authentication/database.yml b/k8s/authentication/database.yml new file mode 100644 index 0000000..948a922 --- /dev/null +++ b/k8s/authentication/database.yml @@ -0,0 +1,63 @@ +apiVersion: v1 +kind: Service +metadata: + name: authentication-database + namespace: aviation +spec: + clusterIP: None + ports: + - port: 5432 + selector: + app: authentication-database +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: authentication-database + namespace: aviation +spec: + serviceName: authentication-database + replicas: 1 + selector: + matchLabels: + app: authentication-database + template: + metadata: + labels: + app: authentication-database + spec: + containers: + - name: postgres + image: postgres:17.6 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: authentication + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + value: postgres + readinessProbe: + exec: + command: [ "pg_isready","-U","postgres","-d","authentication" ] + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/authentication/keygen.yml b/k8s/authentication/keygen.yml new file mode 100644 index 0000000..b7bc030 --- /dev/null +++ b/k8s/authentication/keygen.yml @@ -0,0 +1,63 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: authentication-keygen + namespace: aviation +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + containers: + - name: keygen + image: python:3.12-alpine + workingDir: /app + command: + - sh + - -c + - | + set -e + echo "Installing dependencies..." + pip install --no-cache-dir cryptography==46.0.2 + echo "Cloning repository..." + apk add --no-cache git >/dev/null + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + cd /repo/services/authentication/keys + echo "Generating keys..." + python generate_keys.py + echo "Key generation completed successfully." + env: + - name: KEYS_DIR + value: "/keys" + - name: KEY_PASSWORD + valueFrom: { + secretKeyRef: + key: authentication-key-password + } + volumeMounts: + - name: keys-volume + mountPath: /keys + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 256Mi + volumes: + - name: keys-volume + persistentVolumeClaim: + claimName: authentication-keys-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: authentication-keys-pvc + namespace: aviation +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi +--- \ No newline at end of file diff --git a/k8s/authentication/migrations.yml b/k8s/authentication/migrations.yml new file mode 100644 index 0000000..b558aef --- /dev/null +++ b/k8s/authentication/migrations.yml @@ -0,0 +1,74 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: authentication-migrations + namespace: aviation +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for PostgreSQL to become available..." + until nc -z authentication-database.aviation.svc.cluster.local 5432; do + echo "Still waiting for DB..."; sleep 2; + done + echo "Database is ready!" + - name: wait-for-keys + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for keys to be generated..." + until [ -f /keys/private.pem ] && [ -f /keys/public.pem ]; do + echo "Still waiting for keys..."; sleep 2; + done + echo "Keys are ready!" + volumeMounts: + - name: keys-volume + mountPath: /keys + containers: + - name: authentication-service + image: ghcr.io/edinstance/distributed-aviation-system-services/authentication-migrate:dev + env: + - name: SECRET_KEY + value: insecure-key + - name: KEYS_DIR + value: /keys + - name: KEY_PASSWORD + valueFrom: { + secretKeyRef: + key: authentication-key-password + } + - name: DATABASE_NAME + value: authentication + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + value: postgres + - name: DATABASE_HOST + value: authentication-database + - name: DATABASE_PORT + value: "5432" + volumeMounts: + - name: keys-volume + mountPath: /keys + readOnly: true + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi + volumes: + - name: keys-volume + persistentVolumeClaim: + claimName: authentication-keys-pvc \ No newline at end of file diff --git a/k8s/authentication/secrets.yml b/k8s/authentication/secrets.yml new file mode 100644 index 0000000..496df6a --- /dev/null +++ b/k8s/authentication/secrets.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: authentication-key-password + namespace: aviation +type: Opaque +data: + password: "password" +--- \ No newline at end of file diff --git a/k8s/authentication/service.yml b/k8s/authentication/service.yml new file mode 100644 index 0000000..85a55ea --- /dev/null +++ b/k8s/authentication/service.yml @@ -0,0 +1,141 @@ +apiVersion: v1 +kind: Service +metadata: + name: authentication-service + namespace: aviation +spec: + type: ClusterIP + ports: + - port: 8000 + targetPort: 8000 + protocol: TCP + selector: + app: authentication-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: authentication-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: authentication-service + template: + metadata: + labels: + app: authentication-service + spec: + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: [ "sh", "-c", "until nc -z authentication-database.aviation.svc.cluster.local 5432; do sleep 2; done;" ] + - name: wait-for-keygen + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for key generation to complete..." + until [ -f /keys/private.pem ] && [ -f /keys/public.pem ]; do + echo "Keys not ready, waiting..."; sleep 2; + done + echo "Keys are ready!" + volumeMounts: + - name: keys-volume + mountPath: /keys + - name: wait-for-migrations + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Checking if migrations job completed..." + # In a real setup, you'd check job status via API or use a different approach + # For now, we'll just wait a bit after keys are ready + sleep 10 + echo "Migrations should be complete!" + containers: + - name: authentication-service + image: ghcr.io/edinstance/distributed-aviation-system-services/authentication-web:dev + ports: + - containerPort: 8000 + env: + - name: SECRET_KEY + value: insecure-key + - name: DEBUG + value: "False" + - name: ALLOWED_HOSTS + value: localhost,127.0.0.1,authentication-service.aviation.svc.cluster.local,*.aviation.svc.cluster.local,api.aviation.local + - name: DATABASE_NAME + value: authentication + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + value: postgres + - name: DATABASE_HOST + value: authentication-database + - name: DATABASE_PORT + value: "5432" + - name: CORS_ALLOWED_ORIGINS + value: http://localhost:3000,http://127.0.0.1:3000,https://aviation-frontend.cluster.local + - name: CORS_ALLOW_ALL_ORIGINS + value: "False" + - name: CORS_ALLOW_CREDENTIALS + value: "True" + - name: CORS_ALLOWED_HEADERS + value: accept,accept-encoding,authorization,content-type,dnt,origin,user-agent,x-csrftoken,x-requested-with,x-tenant-id + - name: LOG_LEVEL + value: INFO + - name: ENVIRONMENT + value: dev + - name: OTEL_SERVICE_NAME + value: authentication-service + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://otel-collector:4317 + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: grpc + - name: OTEL_TRACES_EXPORTER + value: otlp + - name: OTEL_METRICS_EXPORTER + value: otlp + - name: OTEL_LOGS_EXPORTER + value: otlp + - name: OTEL_METRIC_EXPORT_INTERVAL + value: "5000" + - name: OTEL_BSP_SCHEDULE_DELAY + value: "5000" + - name: PORT + value: "8000" + - name: KEYS_DIR + value: /keys + - name: KEY_PASSWORD + valueFrom: { + secretKeyRef: + key: authentication-key-password + } + volumeMounts: + - name: keys-volume + mountPath: /keys + readOnly: true + readinessProbe: + httpGet: + path: /health + port: 8000 + httpHeaders: + - name: Host + value: authentication-service.aviation.svc.cluster.local + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi + volumes: + - name: keys-volume + persistentVolumeClaim: + claimName: authentication-keys-pvc \ No newline at end of file diff --git a/services/authentication/authentication/settings.py b/services/authentication/authentication/settings.py index 1a5ff30..4cf65a1 100644 --- a/services/authentication/authentication/settings.py +++ b/services/authentication/authentication/settings.py @@ -31,7 +31,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = config('DEBUG', default=True, cast=bool) -ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost,127.0.0.1', cast=lambda v: [s.strip() for s in v.split(',')]) +ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost,127.0.0.1,*', cast=lambda v: [s.strip() for s in v.split(',')]) # Application definition SHARED_APPS = [ @@ -209,6 +209,20 @@ def load_verifying_key(): default="http://localhost:3000,http://127.0.0.1:3000", cast=lambda v: [s.strip() for s in v.split(",")], ) +CORS_ALLOW_CREDENTIALS = config("CORS_ALLOW_CREDENTIALS", default=True, cast=bool) +CORS_ALLOWED_HEADERS = config( + "CORS_ALLOWED_HEADERS", + default="accept,accept-encoding,authorization,content-type,dnt,origin,user-agent,x-csrftoken,x-requested-with,x-tenant-id", + cast=lambda v: [s.strip() for s in v.split(",")], +) +CORS_ALLOW_METHODS = [ + "DELETE", + "GET", + "OPTIONS", + "PATCH", + "POST", + "PUT", +] # Logging Configuration LOG_LEVEL = config("LOG_LEVEL", default="INFO") diff --git a/services/authentication/docker-compose.yml b/services/authentication/docker-compose.yml index b715f4d..b51ba79 100644 --- a/services/authentication/docker-compose.yml +++ b/services/authentication/docker-compose.yml @@ -7,14 +7,16 @@ services: environment: SECRET_KEY: ${SECRET_KEY:-insecure-key} DEBUG: ${DEBUG:-False} - ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost,127.0.0.1,authentication-service} + ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost,127.0.0.1,authentication-service,host.docker.internal} DATABASE_NAME: ${DATABASE_NAME:-authentication} DATABASE_USER: ${DATABASE_USER:-postgres} DATABASE_PASSWORD: ${DATABASE_PASSWORD:-postgres} DATABASE_HOST: ${DATABASE_HOST:-authentication-database} DATABASE_PORT: ${DATABASE_PORT:-5432} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-http://localhost:3000,http://127.0.0.1:3000,http://gateway-service:4001} - CORS_ALLOW_ALL_ORIGINS: ${CORS_ALLOW_ALL_ORIGINS:-True} + CORS_ALLOW_ALL_ORIGINS: ${CORS_ALLOW_ALL_ORIGINS:-False} + CORS_ALLOW_CREDENTIALS: ${CORS_ALLOW_CREDENTIALS:-True} + CORS_ALLOWED_HEADERS: ${CORS_ALLOWED_HEADERS:-accept,accept-encoding,authorization,content-type,dnt,origin,user-agent,x-csrftoken,x-requested-with,x-tenant-id} LOG_LEVEL: ${LOG_LEVEL:-INFO} ENVIRONMENT: ${ENVIRONMENT:-dev} OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-authentication-service} From 07adc8a67c622e20b9ef217feb88e23903803570 Mon Sep 17 00:00:00 2001 From: edinstance Date: Wed, 22 Oct 2025 02:17:06 +0100 Subject: [PATCH 09/25] feat: changed services to use kubernetes secrets --- k8s/aircraft/database.yml | 5 ++++- k8s/aircraft/migrations.yml | 22 ++++++++++++++++++---- k8s/aircraft/secrets.yml | 9 +++++++++ k8s/aircraft/service.yml | 5 ++++- k8s/authentication/database.yml | 5 ++++- k8s/authentication/keygen.yml | 6 +++--- k8s/authentication/migrations.yml | 11 +++++++---- k8s/authentication/secrets.yml | 11 ++++++++++- k8s/authentication/service.yml | 11 +++++++---- k8s/flights/database.yml | 5 ++++- k8s/flights/migrations.yml | 18 ++++++++++++++++-- k8s/flights/secrets.yml | 9 +++++++++ 12 files changed, 95 insertions(+), 22 deletions(-) create mode 100644 k8s/aircraft/secrets.yml create mode 100644 k8s/flights/secrets.yml diff --git a/k8s/aircraft/database.yml b/k8s/aircraft/database.yml index 554d63c..ce88b68 100644 --- a/k8s/aircraft/database.yml +++ b/k8s/aircraft/database.yml @@ -37,7 +37,10 @@ spec: - name: POSTGRES_USER value: postgres - name: POSTGRES_PASSWORD - value: postgres + valueFrom: + secretKeyRef: + name: aircraft-database-password + key: password readinessProbe: exec: command: [ "pg_isready","-U","postgres","-d","aircraft" ] diff --git a/k8s/aircraft/migrations.yml b/k8s/aircraft/migrations.yml index 6a0f1d1..5cd6175 100644 --- a/k8s/aircraft/migrations.yml +++ b/k8s/aircraft/migrations.yml @@ -43,12 +43,26 @@ spec: echo "Running Liquibase migrations..." cd /repo/services/aircraft/src/main/resources/db liquibase \ - --url=jdbc:postgresql://aircraft-database:5432/aircraft \ - --username=postgres \ - --password=postgres \ - --changelog-file=changelog/db.changelog-master.xml \ + --url="jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}" \ + --username="${DATABASE_USER}" \ + --password="${DATABASE_PASSWORD}" \ + --changelog-file="changelog/db.changelog-master.xml" \ update echo "Liquibase migrations completed successfully." + env: + - name: DATABASE_HOST + value: aircraft-database + - name: DATABASE_PORT + value: "5432" + - name: DATABASE_NAME + value: aircraft + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: aircraft-database-password + key: password volumeMounts: - name: repo-volume mountPath: /repo diff --git a/k8s/aircraft/secrets.yml b/k8s/aircraft/secrets.yml new file mode 100644 index 0000000..7e0fa88 --- /dev/null +++ b/k8s/aircraft/secrets.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: aircraft-database-password + namespace: aviation +type: Opaque +data: + password: cG9zdGdyZXM= +--- \ No newline at end of file diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml index 5f73f0d..83ad170 100644 --- a/k8s/aircraft/service.yml +++ b/k8s/aircraft/service.yml @@ -51,7 +51,10 @@ spec: - name: DATABASE_USERNAME value: "postgres" - name: DATABASE_PASSWORD - value: "postgres" + valueFrom: + secretKeyRef: + name: aircraft-database-password + key: password - name: CACHE_URL value: "redis://aircraft-cache:6379" - name: LIQUIBASE_ENABLED diff --git a/k8s/authentication/database.yml b/k8s/authentication/database.yml index 948a922..762e3dd 100644 --- a/k8s/authentication/database.yml +++ b/k8s/authentication/database.yml @@ -37,7 +37,10 @@ spec: - name: POSTGRES_USER value: postgres - name: POSTGRES_PASSWORD - value: postgres + valueFrom: + secretKeyRef: + name: authentication-database-password + key: password readinessProbe: exec: command: [ "pg_isready","-U","postgres","-d","authentication" ] diff --git a/k8s/authentication/keygen.yml b/k8s/authentication/keygen.yml index b7bc030..069f56e 100644 --- a/k8s/authentication/keygen.yml +++ b/k8s/authentication/keygen.yml @@ -30,10 +30,10 @@ spec: - name: KEYS_DIR value: "/keys" - name: KEY_PASSWORD - valueFrom: { + valueFrom: secretKeyRef: - key: authentication-key-password - } + name: authentication-key-password + key: password volumeMounts: - name: keys-volume mountPath: /keys diff --git a/k8s/authentication/migrations.yml b/k8s/authentication/migrations.yml index b558aef..b353976 100644 --- a/k8s/authentication/migrations.yml +++ b/k8s/authentication/migrations.yml @@ -43,16 +43,19 @@ spec: - name: KEYS_DIR value: /keys - name: KEY_PASSWORD - valueFrom: { + valueFrom: secretKeyRef: - key: authentication-key-password - } + name: authentication-key-password + key: password - name: DATABASE_NAME value: authentication - name: DATABASE_USER value: postgres - name: DATABASE_PASSWORD - value: postgres + valueFrom: + secretKeyRef: + name: authentication-database-password + key: password - name: DATABASE_HOST value: authentication-database - name: DATABASE_PORT diff --git a/k8s/authentication/secrets.yml b/k8s/authentication/secrets.yml index 496df6a..6eac4b7 100644 --- a/k8s/authentication/secrets.yml +++ b/k8s/authentication/secrets.yml @@ -5,5 +5,14 @@ metadata: namespace: aviation type: Opaque data: - password: "password" + password: cGFzc3dvcmQ= +--- +apiVersion: v1 +kind: Secret +metadata: + name: authentication-database-password + namespace: aviation +type: Opaque +data: + password: cG9zdGdyZXM= --- \ No newline at end of file diff --git a/k8s/authentication/service.yml b/k8s/authentication/service.yml index 85a55ea..b055c93 100644 --- a/k8s/authentication/service.yml +++ b/k8s/authentication/service.yml @@ -73,7 +73,10 @@ spec: - name: DATABASE_USER value: postgres - name: DATABASE_PASSWORD - value: postgres + valueFrom: + secretKeyRef: + name: authentication-database-password + key: password - name: DATABASE_HOST value: authentication-database - name: DATABASE_PORT @@ -111,10 +114,10 @@ spec: - name: KEYS_DIR value: /keys - name: KEY_PASSWORD - valueFrom: { + valueFrom: secretKeyRef: - key: authentication-key-password - } + name: authentication-key-password + key: password volumeMounts: - name: keys-volume mountPath: /keys diff --git a/k8s/flights/database.yml b/k8s/flights/database.yml index df244a8..e243945 100644 --- a/k8s/flights/database.yml +++ b/k8s/flights/database.yml @@ -37,7 +37,10 @@ spec: - name: POSTGRES_USER value: postgres - name: POSTGRES_PASSWORD - value: postgres + valueFrom: + secretKeyRef: + name: flights-database-password + key: password readinessProbe: exec: command: [ "pg_isready","-U","postgres","-d","flights" ] diff --git a/k8s/flights/migrations.yml b/k8s/flights/migrations.yml index 4c2951d..d830c9b 100644 --- a/k8s/flights/migrations.yml +++ b/k8s/flights/migrations.yml @@ -33,5 +33,19 @@ spec: git clone https://github.com/edinstance/distributed-aviation-system.git /repo echo "Running migrations..." migrate -path /repo/services/flights/migrations \ - -database "postgres://postgres:postgres@flights-database:5432/flights?sslmode=disable" up - echo "Migrations completed successfully." \ No newline at end of file + -database "postgres://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?sslmode=disable" up + echo "Migrations completed successfully." + env: + - name: DATABASE_HOST + value: flights-database + - name: DATABASE_PORT + value: "5432" + - name: DATABASE_NAME + value: flights + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: flights-database-password + key: password \ No newline at end of file diff --git a/k8s/flights/secrets.yml b/k8s/flights/secrets.yml new file mode 100644 index 0000000..b4a2357 --- /dev/null +++ b/k8s/flights/secrets.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: flights-database-password + namespace: aviation +type: Opaque +data: + password: cG9zdGdyZXM= +--- \ No newline at end of file From 54b85e40ffc546d4c48bbd7d8eacbc70c8be7f74 Mon Sep 17 00:00:00 2001 From: edinstance Date: Wed, 22 Oct 2025 02:17:21 +0100 Subject: [PATCH 10/25] fix: updated router --- docker-compose.yml | 4 ++-- router.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 49fa54c..47cfb2b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: - graphql-router: + router-service: image: ghcr.io/apollographql/router:v2.6.2 - container_name: graphql-router + container_name: router-service volumes: - ./supergraph.graphql:/dist/supergraph.graphql - ./router.yml:/dist/router.yml diff --git a/router.yml b/router.yml index b5f1963..a0212a1 100644 --- a/router.yml +++ b/router.yml @@ -33,7 +33,7 @@ telemetry: service_name: "graphql-router" otlp: enabled: true - endpoint: http://otel-collector:4317 + endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://otel-collector:4317} protocol: grpc metrics: common: @@ -41,7 +41,7 @@ telemetry: service_name: "graphql-router" otlp: enabled: true - endpoint: http://otel-collector:4317 + endpoint: ${OTEL_METRICS_EXPORTER_ENDPOINT:http://otel-collector:4317} protocol: grpc logging: stdout: From 2b992da1516dbbb6d7325b5bb7d77f8fddd1bba7 Mon Sep 17 00:00:00 2001 From: edinstance Date: Wed, 22 Oct 2025 02:17:39 +0100 Subject: [PATCH 11/25] feat: updated gateway to include a healthcheck --- services/gateway/src/handling/health_handler.rs | 6 ++++++ services/gateway/src/handling/mod.rs | 4 +++- services/gateway/src/main.rs | 5 +++-- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 services/gateway/src/handling/health_handler.rs diff --git a/services/gateway/src/handling/health_handler.rs b/services/gateway/src/handling/health_handler.rs new file mode 100644 index 0000000..f0d4670 --- /dev/null +++ b/services/gateway/src/handling/health_handler.rs @@ -0,0 +1,6 @@ +use axum::Json; +use serde_json::json; + +pub async fn health_handler() -> impl axum::response::IntoResponse { + Json(json!({ "status": "UP" })) +} \ No newline at end of file diff --git a/services/gateway/src/handling/mod.rs b/services/gateway/src/handling/mod.rs index ce22eec..2908ab3 100644 --- a/services/gateway/src/handling/mod.rs +++ b/services/gateway/src/handling/mod.rs @@ -1,3 +1,5 @@ mod route_handler; +mod health_handler; -pub use route_handler::route_handler; \ No newline at end of file +pub use route_handler::route_handler; +pub use health_handler::health_handler; \ No newline at end of file diff --git a/services/gateway/src/main.rs b/services/gateway/src/main.rs index 287bb54..34a9ace 100644 --- a/services/gateway/src/main.rs +++ b/services/gateway/src/main.rs @@ -5,7 +5,7 @@ mod requests; mod verify; use crate::config::Config; -use crate::handling::route_handler; +use crate::handling::{route_handler, health_handler}; use crate::observability::{ObservabilityConfig, init_observability, shutdown_observability}; use crate::verify::JwksCache; use axum::{Router, routing::any}; @@ -38,12 +38,13 @@ async fn main() { let client = Arc::new( Client::builder() - .timeout(std::time::Duration::from_secs(30)) + .timeout(Duration::from_secs(30)) .build() .expect("Failed to create HTTP client"), ); let app = Router::new() + .route("/health", any(health_handler)) .route( "/", any({ From 0ec3a75de8602f5e90448e73eb564d8da8ef05d3 Mon Sep 17 00:00:00 2001 From: edinstance Date: Wed, 22 Oct 2025 02:18:07 +0100 Subject: [PATCH 12/25] feat: created gateway and router k8 manifests --- k8s/02-ingress.yml | 37 ++++++++++++++++- k8s/gateway/service.yml | 64 ++++++++++++++++++++++++++++++ k8s/router/service.yml | 88 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 k8s/gateway/service.yml create mode 100644 k8s/router/service.yml diff --git a/k8s/02-ingress.yml b/k8s/02-ingress.yml index 7a1d276..d45f69c 100644 --- a/k8s/02-ingress.yml +++ b/k8s/02-ingress.yml @@ -11,6 +11,20 @@ spec: - host: api.aviation.local http: paths: + - path: /router/(.*) + pathType: ImplementationSpecific + backend: + service: + name: router-service + port: + number: 4000 + - path: /router + pathType: Prefix + backend: + service: + name: router-service + port: + number: 4000 - path: /flights/(.*) pathType: ImplementationSpecific backend: @@ -52,4 +66,25 @@ spec: service: name: authentication-service port: - number: 8000 \ No newline at end of file + number: 8000 + - path: /gateway/(.*) + pathType: ImplementationSpecific + backend: + service: + name: gateway-service + port: + number: 4001 + - path: /gateway + pathType: Prefix + backend: + service: + name: gateway-service + port: + number: 4001 + - path: /(.*) + pathType: ImplementationSpecific + backend: + service: + name: gateway-service + port: + number: 4001 \ No newline at end of file diff --git a/k8s/gateway/service.yml b/k8s/gateway/service.yml new file mode 100644 index 0000000..b710783 --- /dev/null +++ b/k8s/gateway/service.yml @@ -0,0 +1,64 @@ +apiVersion: v1 +kind: Service +metadata: + name: gateway-service + namespace: aviation +spec: + type: ClusterIP + ports: + - port: 4001 + targetPort: 4001 + protocol: TCP + selector: + app: gateway-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: gateway-service + template: + metadata: + labels: + app: gateway-service + spec: + containers: + - name: gateway-service + image: ghcr.io/edinstance/distributed-aviation-system-services/gateway:latest + ports: + - containerPort: 4001 + env: + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "4001" + - name: ROUTER_URL + value: http://router-service:4000 + - name: JWKS_URL + value: http://authentication-service:8000/.well-known/jwks.json + - name: LOG_LEVEL + value: "info" + - name: JSON_LOGS + value: "true" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://host.docker.internal:4317 + - name: OTEL_SERVICE_NAME + value: aviation-gateway + readinessProbe: + httpGet: + path: /health + port: 4001 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file diff --git a/k8s/router/service.yml b/k8s/router/service.yml new file mode 100644 index 0000000..5f2ba10 --- /dev/null +++ b/k8s/router/service.yml @@ -0,0 +1,88 @@ +apiVersion: v1 +kind: Service +metadata: + name: router-service + namespace: aviation +spec: + type: ClusterIP + selector: + app: router-service + ports: + - port: 4000 + targetPort: 4000 + name: http + protocol: TCP + - port: 8088 + targetPort: 8088 + name: health + protocol: TCP + - port: 8089 + targetPort: 8089 + name: metrics + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: router-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: router-service + template: + metadata: + labels: + app: router-service + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning router configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying supergraph and config files..." + mkdir -p /config + cp /repo/supergraph.graphql /config/supergraph.graphql + cp /repo/router.yml /config/router.yml + echo "Config ready." + volumeMounts: + - name: router-config + mountPath: /config + containers: + - name: apollo-router + image: ghcr.io/apollographql/router:v2.6.2 + args: + - "--supergraph" + - /etc/apollo/supergraph.graphql + - "--config" + - /etc/apollo/router.yml + - "--hot-reload" + ports: + - containerPort: 4000 + - containerPort: 8088 + - containerPort: 8089 + readinessProbe: + httpGet: + path: /health + port: 8088 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: router-config + mountPath: /etc/apollo + readOnly: true + volumes: + - name: router-config + emptyDir: {} \ No newline at end of file From 2eb88b5127ab8b4f3fb17827267e212c6ff2fa89 Mon Sep 17 00:00:00 2001 From: edinstance Date: Wed, 22 Oct 2025 02:23:16 +0100 Subject: [PATCH 13/25] feat: created monitoring namespace and moved ingress namespace to namespaces file --- k8s/00-namespace.yml | 16 +++++++++++++++- k8s/01-ingress-controller.yml | 8 -------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/k8s/00-namespace.yml b/k8s/00-namespace.yml index 4dcca1a..7fc7721 100644 --- a/k8s/00-namespace.yml +++ b/k8s/00-namespace.yml @@ -1,4 +1,18 @@ apiVersion: v1 kind: Namespace metadata: - name: aviation \ No newline at end of file + name: aviation +--- +apiVersion: v1 +kind: Namespace +metadata: + name: monitoring +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + name: ingress-nginx +--- \ No newline at end of file diff --git a/k8s/01-ingress-controller.yml b/k8s/01-ingress-controller.yml index a667894..cc731e3 100644 --- a/k8s/01-ingress-controller.yml +++ b/k8s/01-ingress-controller.yml @@ -1,12 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - labels: - app.kubernetes.io/instance: ingress-nginx - app.kubernetes.io/name: ingress-nginx - name: ingress-nginx ---- -apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: From 959035a11cd17bc813cd4df256bcf23f5774260e Mon Sep 17 00:00:00 2001 From: edinstance Date: Wed, 22 Oct 2025 20:47:17 +0100 Subject: [PATCH 14/25] feat: created otel collector service and updated services to send metrics to it --- k8s/aircraft/service.yml | 2 +- k8s/authentication/service.yml | 2 +- k8s/flights/service.yml | 4 +- k8s/gateway/service.yml | 4 +- k8s/monitoring/otel.yml | 81 ++++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 k8s/monitoring/otel.yml diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml index 83ad170..7f20102 100644 --- a/k8s/aircraft/service.yml +++ b/k8s/aircraft/service.yml @@ -62,7 +62,7 @@ spec: - name: OTEL_SERVICE_NAME value: "aircraft-service" - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: "http://host.docker.internal:4317" + value: "http://otel-collector.monitoring:4317" - name: OTEL_EXPORTER_OTLP_PROTOCOL value: "grpc" - name: OTEL_TRACES_EXPORTER diff --git a/k8s/authentication/service.yml b/k8s/authentication/service.yml index b055c93..9f3d024 100644 --- a/k8s/authentication/service.yml +++ b/k8s/authentication/service.yml @@ -96,7 +96,7 @@ spec: - name: OTEL_SERVICE_NAME value: authentication-service - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: http://otel-collector:4317 + value: http://otel-collector.monitoring:4317 - name: OTEL_EXPORTER_OTLP_PROTOCOL value: grpc - name: OTEL_TRACES_EXPORTER diff --git a/k8s/flights/service.yml b/k8s/flights/service.yml index f70d595..955910b 100644 --- a/k8s/flights/service.yml +++ b/k8s/flights/service.yml @@ -49,9 +49,9 @@ spec: - name: PORT value: "8081" - name: AIRCRAFT_SERVICE_GRPC_URL - value: host.docker.internal:9090 + value: aircraft-service:9090 - name: OTLP_GRPC_URL - value: host.docker.internal:4317 + value: otel-collector.monitoring:4317 - name: KAFKA_BROKER_URL value: host.docker.internal:9092 - name: KAFKA_SCHEMA_REGISTRY_URL diff --git a/k8s/gateway/service.yml b/k8s/gateway/service.yml index b710783..0423e34 100644 --- a/k8s/gateway/service.yml +++ b/k8s/gateway/service.yml @@ -46,9 +46,9 @@ spec: - name: JSON_LOGS value: "true" - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: http://host.docker.internal:4317 + value: http://otel-collector.monitoring:4317 - name: OTEL_SERVICE_NAME - value: aviation-gateway + value: gateway-service readinessProbe: httpGet: path: /health diff --git a/k8s/monitoring/otel.yml b/k8s/monitoring/otel.yml new file mode 100644 index 0000000..ec5d652 --- /dev/null +++ b/k8s/monitoring/otel.yml @@ -0,0 +1,81 @@ +apiVersion: v1 +kind: Service +metadata: + name: otel-collector + namespace: monitoring +spec: + type: ClusterIP + selector: + app: otel-collector + ports: + - port: 4317 + targetPort: 4317 + name: otlp-grpc + protocol: TCP + - port: 4318 + targetPort: 4318 + name: otlp-http + protocol: TCP + - port: 9464 + targetPort: 9464 + name: prometheus-metrics + protocol: TCP + - port: 8888 + targetPort: 8888 + name: service-metrics + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: otel-collector + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: otel-collector + template: + metadata: + labels: + app: otel-collector + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning router configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying otel config files..." + mkdir -p /config + cp /repo/monitoring/otel/otel.yml /config/config.yaml + echo "Config ready." + volumeMounts: + - name: otel-collector-config + mountPath: /config + containers: + - name: otel-collector + image: otel/opentelemetry-collector:0.136.0 + args: ["--config=/etc/otel/config.yaml"] + ports: + - containerPort: 4317 + - containerPort: 4318 + - containerPort: 8888 + - containerPort: 9464 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: otel-collector-config + mountPath: /etc/otel + readOnly: true + volumes: + - name: otel-collector-config + emptyDir: { } \ No newline at end of file From 10d7b9927ee66933fcd7aaad44fe2bbc1c70ff20 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 27 Oct 2025 21:55:46 +0000 Subject: [PATCH 15/25] feat: created prometheus manifest --- k8s/monitoring/otel.yml | 2 +- k8s/monitoring/promethus.yml | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 k8s/monitoring/promethus.yml diff --git a/k8s/monitoring/otel.yml b/k8s/monitoring/otel.yml index ec5d652..cebc8e3 100644 --- a/k8s/monitoring/otel.yml +++ b/k8s/monitoring/otel.yml @@ -47,7 +47,7 @@ spec: - sh - -c - | - echo "Cloning router configuration..." + echo "Cloning configuration..." git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo echo "Copying otel config files..." mkdir -p /config diff --git a/k8s/monitoring/promethus.yml b/k8s/monitoring/promethus.yml new file mode 100644 index 0000000..5ce465f --- /dev/null +++ b/k8s/monitoring/promethus.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: monitoring +spec: + type: ClusterIP + selector: + app: prometheus + ports: + - port: 9090 + targetPort: 9090 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying prometheus config files..." + mkdir -p /config + cp /repo/monitoring/prometheus/prometheus.yml /config/config.yaml + echo "Config ready." + volumeMounts: + - name: prometheus-config + mountPath: /config + containers: + - name: prometheus + image: prom/prometheus:v3.6.0 + args: ["--config.file=/etc/prometheus/config.yaml"] + ports: + - containerPort: 9090 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: prometheus-config + mountPath: /etc/prometheus + readOnly: true + volumes: + - name: prometheus-config + emptyDir: { } \ No newline at end of file From 1135d01376ac0eb856c5c4c6c2ec202622b1392c Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 27 Oct 2025 22:00:05 +0000 Subject: [PATCH 16/25] feat: created jaeger manifest --- k8s/monitoring/jaeger.yml | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 k8s/monitoring/jaeger.yml diff --git a/k8s/monitoring/jaeger.yml b/k8s/monitoring/jaeger.yml new file mode 100644 index 0000000..918bbe2 --- /dev/null +++ b/k8s/monitoring/jaeger.yml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: Service +metadata: + name: jaeger + namespace: monitoring +spec: + type: ClusterIP + selector: + app: jaeger + ports: + - port: 16686 + targetPort: 16686 + name: jaeger-ui + protocol: TCP + - port: 14268 + targetPort: 14268 + name: jaeger-http + protocol: TCP + - port: 14250 + targetPort: 14250 + name: jaeger-grpc + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jaeger + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: jaeger + template: + metadata: + labels: + app: jaeger + spec: + containers: + - name: jaeger + image: jaegertracing/all-in-one:1.65.0 + ports: + - containerPort: 16686 + - containerPort: 14268 + - containerPort: 14250 + env: + - name: COLLECTOR_OTLP_ENABLED + value: "true" + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi From 637f8903735e692a323d7d8f5e8ceba1e3cc1e17 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 27 Oct 2025 22:24:41 +0000 Subject: [PATCH 17/25] feat: created mimir manifest --- k8s/monitoring/mimir.yml | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 k8s/monitoring/mimir.yml diff --git a/k8s/monitoring/mimir.yml b/k8s/monitoring/mimir.yml new file mode 100644 index 0000000..d486c70 --- /dev/null +++ b/k8s/monitoring/mimir.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: mimir + namespace: monitoring +spec: + type: ClusterIP + selector: + app: mimir + ports: + - port: 9009 + targetPort: 9009 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mimir + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: mimir + template: + metadata: + labels: + app: mimir + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying mimir config files..." + mkdir -p /config + cp /repo/monitoring/mimir/config/mimir.yml /config/config.yaml + echo "Config ready." + volumeMounts: + - name: mimir-config + mountPath: /config + containers: + - name: mimir + image: grafana/mimir:2.17.1 + args: ["-config.file=/etc/mimir/config.yaml"] + ports: + - containerPort: 9009 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: mimir-config + mountPath: /etc/mimir + readOnly: true + volumes: + - name: mimir-config + emptyDir: { } \ No newline at end of file From 2eadb3f530f2df800ca2e604d0052213eec8376d Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 27 Oct 2025 22:26:10 +0000 Subject: [PATCH 18/25] feat: created loki manifest --- k8s/monitoring/loki.yml | 41 +++++++++++++++++++++++++++++++++++ monitoring/docker-compose.yml | 1 - 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 k8s/monitoring/loki.yml diff --git a/k8s/monitoring/loki.yml b/k8s/monitoring/loki.yml new file mode 100644 index 0000000..69bec9f --- /dev/null +++ b/k8s/monitoring/loki.yml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: Service +metadata: + name: loki + namespace: monitoring +spec: + type: ClusterIP + selector: + app: loki + ports: + - port: 3100 + targetPort: 3100 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: loki + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: loki + template: + metadata: + labels: + app: loki + spec: + containers: + - name: loki + image: grafana/loki:3.3.0 + ports: + - containerPort: 3100 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi diff --git a/monitoring/docker-compose.yml b/monitoring/docker-compose.yml index d2fabbf..98b8d99 100644 --- a/monitoring/docker-compose.yml +++ b/monitoring/docker-compose.yml @@ -75,7 +75,6 @@ services: restart: unless-stopped ports: - "3100:3100" - command: -config.file=/etc/loki/local-config.yaml volumes: - loki_data:/loki networks: From c5ff5f2ad1269fff447f277b4aa67036417651ff Mon Sep 17 00:00:00 2001 From: edinstance Date: Thu, 30 Oct 2025 15:07:46 +0000 Subject: [PATCH 19/25] feat: created grafana manifest --- k8s/monitoring/grafana.yml | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 k8s/monitoring/grafana.yml diff --git a/k8s/monitoring/grafana.yml b/k8s/monitoring/grafana.yml new file mode 100644 index 0000000..05474b2 --- /dev/null +++ b/k8s/monitoring/grafana.yml @@ -0,0 +1,73 @@ +apiVersion: v1 +kind: Service +metadata: + name: grafana + namespace: monitoring +spec: + type: ClusterIP + selector: + app: grafana + ports: + - port: 3000 + targetPort: 3000 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grafana + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: grafana + template: + metadata: + labels: + app: grafana + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying grafana config files..." + mkdir -p /config + cp -r /repo/monitoring/grafana/provisioning/* /config/ + echo "Config ready." + volumeMounts: + - name: grafana-config + mountPath: /config + containers: + - name: grafana + image: grafana/grafana:12.2.0 + env: + - name: GF_SECURITY_ADMIN_USER + value: admin + - name: GF_SECURITY_ADMIN_PASSWORD + value: admin + - name: GF_USERS_ALLOW_SIGN_UP + value: "false" + - name: GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS + value: "grafana-exploretraces-app,grafana-metricsdrilldown-app,grafana-lokiexplore-app" + ports: + - containerPort: 3000 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: grafana-config + mountPath: /etc/grafana/provisioning + readOnly: true + volumes: + - name: grafana-config + emptyDir: { } \ No newline at end of file From 7820c0d77a096f5d09b5699d3e218ba48fda54db Mon Sep 17 00:00:00 2001 From: edinstance Date: Thu, 30 Oct 2025 15:08:13 +0000 Subject: [PATCH 20/25] fix: fixed gateway routing issues --- services/gateway/src/main.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/services/gateway/src/main.rs b/services/gateway/src/main.rs index 34a9ace..cd6d35e 100644 --- a/services/gateway/src/main.rs +++ b/services/gateway/src/main.rs @@ -45,28 +45,14 @@ async fn main() { let app = Router::new() .route("/health", any(health_handler)) - .route( - "/", - any({ - let router_url = router_url.clone(); - let client = client.clone(); - let jwks_cache = jwks_cache.clone(); - move |req| { - route_handler(req, router_url.clone(), client.clone(), jwks_cache.clone()) - } - }), - ) - .route( - "/{*wildcard}", - any({ - let router_url = router_url.clone(); - let client = client.clone(); - let jwks_cache = jwks_cache.clone(); - move |req| { - route_handler(req, router_url.clone(), client.clone(), jwks_cache.clone()) - } - }), - ); + .fallback({ + let router_url = router_url.clone(); + let client = client.clone(); + let jwks_cache = jwks_cache.clone(); + move |req| { + route_handler(req, router_url.clone(), client.clone(), jwks_cache.clone()) + } + }); let addr = SocketAddr::from(([0, 0, 0, 0], config.port)); info!(address = %addr, "Aviation gateway service started"); From c6c29607429cc550983d1c39afe46dfb70d12d1b Mon Sep 17 00:00:00 2001 From: edinstance Date: Fri, 31 Oct 2025 16:08:32 +0000 Subject: [PATCH 21/25] feat: created messaging namespace with kafka and schema registry --- k8s/00-namespace.yml | 5 ++ k8s/messaging/kafka.yml | 118 ++++++++++++++++++++++++++++++ k8s/messaging/schema-loader.yml | 53 ++++++++++++++ k8s/messaging/schema-registry.yml | 58 +++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 k8s/messaging/kafka.yml create mode 100644 k8s/messaging/schema-loader.yml create mode 100644 k8s/messaging/schema-registry.yml diff --git a/k8s/00-namespace.yml b/k8s/00-namespace.yml index 7fc7721..d4d6e6a 100644 --- a/k8s/00-namespace.yml +++ b/k8s/00-namespace.yml @@ -10,6 +10,11 @@ metadata: --- apiVersion: v1 kind: Namespace +metadata: + name: messaging +--- +apiVersion: v1 +kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx diff --git a/k8s/messaging/kafka.yml b/k8s/messaging/kafka.yml new file mode 100644 index 0000000..5bc445d --- /dev/null +++ b/k8s/messaging/kafka.yml @@ -0,0 +1,118 @@ +apiVersion: v1 +kind: Service +metadata: + name: kafka + namespace: messaging +spec: + clusterIP: None + selector: + app: kafka + ports: + - name: internal + port: 9092 + protocol: TCP + - name: external + port: 19092 + protocol: TCP + - name: controller + port: 9093 + protocol: TCP +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: kafka + namespace: messaging +spec: + serviceName: kafka + replicas: 3 + selector: + matchLabels: + app: kafka + template: + metadata: + labels: + app: kafka + spec: + containers: + - name: kafka + image: apache/kafka:4.0.0 + ports: + - containerPort: 9092 + - containerPort: 19092 + - containerPort: 9093 + env: + # Make HOSTNAME available to Kafka (Kubernetes will expand this) + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + + # Cluster settings + - name: CLUSTER_ID + value: "7sWhx1QdSqGGl3a57SSZXA" + - name: KAFKA_PROCESS_ROLES + value: "broker,controller" + + # Controller quorum definition – all 3 brokers are voters + - name: KAFKA_CONTROLLER_QUORUM_VOTERS + value: "0@kafka-0.kafka.messaging.svc.cluster.local:9093,1@kafka-1.kafka.messaging.svc.cluster.local:9093,2@kafka-2.kafka.messaging.svc.cluster.local:9093" + + # Define listeners + - name: KAFKA_LISTENERS + value: "INTERNAL://0.0.0.0:9092,EXTERNAL://0.0.0.0:19092,CONTROLLER://0.0.0.0:9093" + + # Advertised listeners (now correctly expands HOSTNAME) + - name: KAFKA_ADVERTISED_LISTENERS + value: "INTERNAL://$(HOSTNAME).kafka.messaging.svc.cluster.local:9092,EXTERNAL://$(HOSTNAME).kafka.messaging.svc.cluster.local:19092" + + # Listener protocol mappings + - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP + value: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT" + + - name: KAFKA_INTER_BROKER_LISTENER_NAME + value: "INTERNAL" + - name: KAFKA_CONTROLLER_LISTENER_NAMES + value: "CONTROLLER" + + # Replication settings + - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR + value: "3" + - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR + value: "3" + - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR + value: "2" + - name: KAFKA_MIN_INSYNC_REPLICAS + value: "2" + + # Node ID for KRaft mode + - name: KAFKA_NODE_ID + valueFrom: + fieldRef: + fieldPath: metadata.labels['apps.kubernetes.io/pod-index'] + + # Log directories + - name: KAFKA_LOG_DIRS + value: /var/lib/kafka/data + + volumeMounts: + - name: kafka-data + mountPath: /var/lib/kafka + + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1 + memory: 1Gi + volumeClaimTemplates: + - metadata: + name: kafka-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path \ No newline at end of file diff --git a/k8s/messaging/schema-loader.yml b/k8s/messaging/schema-loader.yml new file mode 100644 index 0000000..91ad84a --- /dev/null +++ b/k8s/messaging/schema-loader.yml @@ -0,0 +1,53 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: schema-loader + namespace: messaging +spec: + template: + metadata: + labels: + app: schema-loader + spec: + restartPolicy: OnFailure + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning repository..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying schema files and script..." + mkdir -p /config /schemas + cp /repo/kafka/script.sh /config/ + cp -r /repo/kafka/schemas/* /schemas/ + echo "Config and schemas ready." + volumeMounts: + - name: config-volume + mountPath: /config + - name: schemas-volume + mountPath: /schemas + containers: + - name: schema-loader + image: alpine:3.20 + command: ["/bin/sh", "-c"] + args: ["apk add --no-cache curl jq && /config/script.sh"] + volumeMounts: + - name: config-volume + mountPath: /config + - name: schemas-volume + mountPath: /schemas + resources: + requests: + cpu: 100m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi + volumes: + - name: config-volume + emptyDir: {} + - name: schemas-volume + emptyDir: {} \ No newline at end of file diff --git a/k8s/messaging/schema-registry.yml b/k8s/messaging/schema-registry.yml new file mode 100644 index 0000000..fe20998 --- /dev/null +++ b/k8s/messaging/schema-registry.yml @@ -0,0 +1,58 @@ +apiVersion: v1 +kind: Service +metadata: + name: schema-registry + namespace: messaging +spec: + ports: + - name: http + port: 8081 + protocol: TCP + selector: + app: schema-registry +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: schema-registry + namespace: messaging +spec: + replicas: 1 + selector: + matchLabels: + app: schema-registry + template: + metadata: + labels: + app: schema-registry + spec: + enableServiceLinks: false # Required for Kafka to work + containers: + - name: schema-registry + image: confluentinc/cp-schema-registry:8.1.0 + ports: + - containerPort: 8081 + env: + - name: SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS + value: "kafka.messaging.svc.cluster.local:9092" + - name: SCHEMA_REGISTRY_LISTENERS + value: "http://0.0.0.0:8081" + - name: SCHEMA_REGISTRY_HOST_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SCHEMA_REGISTRY_LOG4J_ROOT_LOGLEVEL + value: "INFO" + - name: SCHEMA_REGISTRY_KAFKASTORE_TOPIC_REPLICATION_FACTOR + value: "1" + - name: SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL + value: "PLAINTEXT" + - name: SCHEMA_REGISTRY_SCHEMA_COMPATIBILITY_LEVEL + value: "BACKWARD" + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file From 744cc48e8eda17dfecf43d8f7cc2b842aacef35c Mon Sep 17 00:00:00 2001 From: edinstance Date: Sat, 1 Nov 2025 15:46:49 +0000 Subject: [PATCH 22/25] feat: created search service in k8s --- k8s/00-namespace.yml | 5 ++ k8s/search/dashboards.yml | 67 ++++++++++++++++++++++++++ k8s/search/init-job.yml | 63 +++++++++++++++++++++++++ k8s/search/opensearch.yml | 98 +++++++++++++++++++++++++++++++++++++++ k8s/search/service.yml | 78 +++++++++++++++++++++++++++++++ 5 files changed, 311 insertions(+) create mode 100644 k8s/search/dashboards.yml create mode 100644 k8s/search/init-job.yml create mode 100644 k8s/search/opensearch.yml create mode 100644 k8s/search/service.yml diff --git a/k8s/00-namespace.yml b/k8s/00-namespace.yml index d4d6e6a..90c696b 100644 --- a/k8s/00-namespace.yml +++ b/k8s/00-namespace.yml @@ -20,4 +20,9 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx +--- +apiVersion: v1 +kind: Namespace +metadata: + name: search --- \ No newline at end of file diff --git a/k8s/search/dashboards.yml b/k8s/search/dashboards.yml new file mode 100644 index 0000000..c0203bf --- /dev/null +++ b/k8s/search/dashboards.yml @@ -0,0 +1,67 @@ +apiVersion: v1 +kind: Service +metadata: + name: opensearch-dashboards + namespace: search +spec: + selector: + app: opensearch-dashboards + ports: + - name: http + port: 5601 + targetPort: 5601 + protocol: TCP + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: opensearch-dashboards + namespace: search +spec: + replicas: 1 + selector: + matchLabels: + app: opensearch-dashboards + template: + metadata: + labels: + app: opensearch-dashboards + spec: + containers: + - name: opensearch-dashboards + image: opensearchproject/opensearch-dashboards:2.11.1 + ports: + - containerPort: 5601 + name: http + env: + - name: OPENSEARCH_HOSTS + value: '["http://opensearch.search.svc.cluster.local:9200"]' + - name: OPENSEARCH_SSL_VERIFICATIONMODE + value: "none" + - name: OPENSEARCH_SECURITY_ENABLED + value: "false" + - name: DISABLE_SECURITY_DASHBOARDS_PLUGIN + value: "true" + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 500m + memory: 1Gi + readinessProbe: + httpGet: + path: /api/status + port: 5601 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /api/status + port: 5601 + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 +--- \ No newline at end of file diff --git a/k8s/search/init-job.yml b/k8s/search/init-job.yml new file mode 100644 index 0000000..8f68ba4 --- /dev/null +++ b/k8s/search/init-job.yml @@ -0,0 +1,63 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: opensearch-init + namespace: search +spec: + template: + metadata: + labels: + app: opensearch-init + spec: + restartPolicy: OnFailure + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning repository..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying init files and script..." + mkdir -p /config /init/indexes /init/visualizations /init/searches /init/dashboards + cp /repo/services/search/init/setup-dashboard.sh /config/ + cp -r /repo/services/search/init/indexes/* /init/indexes/ + cp -r /repo/services/search/init/visualizations/* /init/visualizations/ + cp -r /repo/services/search/init/searches/* /init/searches/ + cp -r /repo/services/search/init/dashboards/* /init/dashboards/ + chmod +x /config/setup-dashboard.sh + echo "Init files ready." + volumeMounts: + - name: config-volume + mountPath: /config + - name: init-volume + mountPath: /init + containers: + - name: opensearch-init + image: alpine:3.20 + command: ["/bin/sh", "-c"] + args: + - | + apk add --no-cache curl jq bash + # Update URLs for Kubernetes services + sed -i 's|opensearch-node-1:9200|opensearch.search.svc.cluster.local:9200|g' /config/setup-dashboard.sh + sed -i 's|opensearch-dashboards:5601|opensearch-dashboards.search.svc.cluster.local:5601|g' /config/setup-dashboard.sh + /config/setup-dashboard.sh + volumeMounts: + - name: config-volume + mountPath: /config + - name: init-volume + mountPath: /init + resources: + requests: + cpu: 100m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi + volumes: + - name: config-volume + emptyDir: {} + - name: init-volume + emptyDir: {} \ No newline at end of file diff --git a/k8s/search/opensearch.yml b/k8s/search/opensearch.yml new file mode 100644 index 0000000..1d90b2e --- /dev/null +++ b/k8s/search/opensearch.yml @@ -0,0 +1,98 @@ +apiVersion: v1 +kind: Service +metadata: + name: opensearch + namespace: search +spec: + clusterIP: None + selector: + app: opensearch + ports: + - name: http + port: 9200 + protocol: TCP + - name: transport + port: 9300 + protocol: TCP +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: opensearch + namespace: search +spec: + serviceName: opensearch + replicas: 2 + selector: + matchLabels: + app: opensearch + template: + metadata: + labels: + app: opensearch + spec: + containers: + - name: opensearch + image: opensearchproject/opensearch:2.11.1 + ports: + - containerPort: 9200 + name: http + - containerPort: 9300 + name: transport + env: + - name: OPENSEARCH_JAVA_OPTS + value: "-Xms512m -Xmx512m" + - name: bootstrap.memory_lock + value: "true" + - name: discovery.seed_hosts + value: "opensearch-0.opensearch.search.svc.cluster.local,opensearch-1.opensearch.search.svc.cluster.local" + - name: cluster.initial_cluster_manager_nodes + value: "opensearch-0" + - name: cluster.name + value: "aviation-search-cluster" + - name: node.name + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: network.host + value: "0.0.0.0" + - name: DISABLE_SECURITY_PLUGIN + value: "true" + - name: DISABLE_INSTALL_DEMO_CONFIG + value: "true" + volumeMounts: + - name: opensearch-data + mountPath: /usr/share/opensearch/data + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + cpu: 1 + memory: 2Gi + readinessProbe: + httpGet: + path: /_cluster/health + port: 9200 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /_cluster/health + port: 9200 + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 + securityContext: + fsGroup: 1000 + volumeClaimTemplates: + - metadata: + name: opensearch-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: local-path \ No newline at end of file diff --git a/k8s/search/service.yml b/k8s/search/service.yml new file mode 100644 index 0000000..f940362 --- /dev/null +++ b/k8s/search/service.yml @@ -0,0 +1,78 @@ +apiVersion: v1 +kind: Service +metadata: + name: search-service + namespace: search +spec: + type: ClusterIP + ports: + - port: 8082 + targetPort: 8082 + protocol: TCP + selector: + app: search-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: search-service + namespace: search +spec: + replicas: 1 + selector: + matchLabels: + app: search-service + template: + metadata: + labels: + app: search-service + spec: + containers: + - name: search-service + image: ghcr.io/edinstance/distributed-aviation-system-services/search:latest + ports: + - containerPort: 8082 + env: + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "8082" + - name: OPENSEARCH_HOST + value: "opensearch.search.svc.cluster.local" + - name: OPENSEARCH_PORT + value: "9200" + - name: OPENSEARCH_SCHEME + value: "http" + - name: KAFKA_BOOTSTRAP_SERVERS + value: "kafka.messaging.svc.cluster.local:9092" + - name: SCHEMA_REGISTRY_URL + value: "http://schema-registry.messaging:8081" + - name: OTEL_SERVICE_NAME + value: "search-service" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://otel-collector.monitoring:4317" + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: "grpc" + - name: OTEL_TRACES_EXPORTER + value: "otlp" + - name: OTEL_METRICS_EXPORTER + value: "otlp" + - name: OTEL_LOGS_EXPORTER + value: "otlp" + - name: OTEL_METRIC_EXPORT_INTERVAL + value: "5000" + - name: OTEL_BSP_SCHEDULE_DELAY + value: "5000" + readinessProbe: + httpGet: + path: /details/health + port: 8082 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file From 9aca94fa593573a6ea9f149eab5103f3557e0fe6 Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 3 Nov 2025 21:08:28 +0000 Subject: [PATCH 23/25] refactor!: refactored k8s to use more namespaces and added some fixes --- k8s/00-namespace.yml | 15 ++++ k8s/02-cross-namespace-services.yml | 65 ++++++++++++++++++ k8s/{02-ingress.yml => 03-ingress.yml} | 16 ++++- k8s/aircraft/cache.yml | 4 +- k8s/aircraft/database.yml | 4 +- k8s/aircraft/migrations.yml | 4 +- k8s/aircraft/secrets.yml | 2 +- k8s/aircraft/service.yml | 16 +++-- k8s/authentication/database.yml | 4 +- k8s/authentication/keygen.yml | 4 +- k8s/authentication/migrations.yml | 4 +- k8s/authentication/secrets.yml | 4 +- k8s/authentication/service.yml | 8 +-- k8s/cross-namespace-services-aviation.yml | 32 +++++++++ k8s/flights/cache.yml | 4 +- k8s/flights/database.yml | 4 +- k8s/flights/migrations.yml | 4 +- k8s/flights/secrets.yml | 2 +- k8s/flights/service.yml | 14 ++-- k8s/messaging/schema-loader.yml | 1 + k8s/router/router-config-job.yml | 53 +++++++++++++++ k8s/router/service.yml | 35 ++++------ k8s/router/supergraph-job.yml | 83 +++++++++++++++++++++++ load-tests/src/config.ts | 10 +-- load-tests/src/helpers/auth_headers.ts | 29 ++++++++ load-tests/src/tests/shells/aircraft.ts | 18 ++--- load-tests/src/tests/shells/flights.ts | 18 ++--- supergraph.yml | 6 +- 28 files changed, 375 insertions(+), 88 deletions(-) create mode 100644 k8s/02-cross-namespace-services.yml rename k8s/{02-ingress.yml => 03-ingress.yml} (85%) create mode 100644 k8s/cross-namespace-services-aviation.yml create mode 100644 k8s/router/router-config-job.yml create mode 100644 k8s/router/supergraph-job.yml create mode 100644 load-tests/src/helpers/auth_headers.ts diff --git a/k8s/00-namespace.yml b/k8s/00-namespace.yml index 90c696b..9b5457b 100644 --- a/k8s/00-namespace.yml +++ b/k8s/00-namespace.yml @@ -5,6 +5,21 @@ metadata: --- apiVersion: v1 kind: Namespace +metadata: + name: authentication +--- +apiVersion: v1 +kind: Namespace +metadata: + name: flights +--- +apiVersion: v1 +kind: Namespace +metadata: + name: aircraft +--- +apiVersion: v1 +kind: Namespace metadata: name: monitoring --- diff --git a/k8s/02-cross-namespace-services.yml b/k8s/02-cross-namespace-services.yml new file mode 100644 index 0000000..c9cd795 --- /dev/null +++ b/k8s/02-cross-namespace-services.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: flights-service.flights.svc.cluster.local + ports: + - port: 8081 +--- +apiVersion: v1 +kind: Service +metadata: + name: aircraft-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: aircraft-service.aircraft.svc.cluster.local + ports: + - port: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: authentication-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: authentication-service.authentication.svc.cluster.local + ports: + - port: 8000 +--- +apiVersion: v1 +kind: Service +metadata: + name: search-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: search-service.search.svc.cluster.local + ports: + - port: 8082 +--- +apiVersion: v1 +kind: Service +metadata: + name: router-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: router-service.aviation.svc.cluster.local + ports: + - port: 4000 +--- +apiVersion: v1 +kind: Service +metadata: + name: gateway-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: gateway-service.aviation.svc.cluster.local + ports: + - port: 4001 \ No newline at end of file diff --git a/k8s/02-ingress.yml b/k8s/03-ingress.yml similarity index 85% rename from k8s/02-ingress.yml rename to k8s/03-ingress.yml index d45f69c..07bd35e 100644 --- a/k8s/02-ingress.yml +++ b/k8s/03-ingress.yml @@ -2,7 +2,7 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: aviation-ingress - namespace: aviation + namespace: ingress-nginx annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: @@ -81,6 +81,20 @@ spec: name: gateway-service port: number: 4001 + - path: /search/(.*) + pathType: ImplementationSpecific + backend: + service: + name: search-service + port: + number: 8082 + - path: /search + pathType: Prefix + backend: + service: + name: search-service + port: + number: 8082 - path: /(.*) pathType: ImplementationSpecific backend: diff --git a/k8s/aircraft/cache.yml b/k8s/aircraft/cache.yml index c37a03f..f460b4d 100644 --- a/k8s/aircraft/cache.yml +++ b/k8s/aircraft/cache.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: aircraft-cache - namespace: aviation + namespace: aircraft spec: ports: - port: 6379 @@ -13,7 +13,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: aircraft-cache - namespace: aviation + namespace: aircraft spec: replicas: 1 selector: diff --git a/k8s/aircraft/database.yml b/k8s/aircraft/database.yml index ce88b68..1412b06 100644 --- a/k8s/aircraft/database.yml +++ b/k8s/aircraft/database.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: aircraft-database - namespace: aviation + namespace: aircraft spec: clusterIP: None ports: @@ -14,7 +14,7 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: aircraft-database - namespace: aviation + namespace: aircraft spec: serviceName: aircraft-database replicas: 1 diff --git a/k8s/aircraft/migrations.yml b/k8s/aircraft/migrations.yml index 5cd6175..766c9a2 100644 --- a/k8s/aircraft/migrations.yml +++ b/k8s/aircraft/migrations.yml @@ -2,7 +2,7 @@ apiVersion: batch/v1 kind: Job metadata: name: aircraft-migrations - namespace: aviation + namespace: aircraft spec: backoffLimit: 0 template: @@ -16,7 +16,7 @@ spec: - -c - | echo "Waiting for Postgres to become available..." - until nc -z aircraft-database.aviation.svc.cluster.local 5432; do + until nc -z aircraft-database.aircraft.svc.cluster.local 5432; do echo "Still waiting for DB..."; sleep 2; done echo "Database is ready!" diff --git a/k8s/aircraft/secrets.yml b/k8s/aircraft/secrets.yml index 7e0fa88..4f90b25 100644 --- a/k8s/aircraft/secrets.yml +++ b/k8s/aircraft/secrets.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Secret metadata: name: aircraft-database-password - namespace: aviation + namespace: aircraft type: Opaque data: password: cG9zdGdyZXM= diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml index 7f20102..06dd693 100644 --- a/k8s/aircraft/service.yml +++ b/k8s/aircraft/service.yml @@ -2,13 +2,18 @@ apiVersion: v1 kind: Service metadata: name: aircraft-service - namespace: aviation + namespace: aircraft spec: type: ClusterIP ports: - port: 8080 targetPort: 8080 protocol: TCP + name: http + - port: 9090 + targetPort: 9090 + protocol: TCP + name: grpc selector: app: aircraft-service --- @@ -16,7 +21,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: aircraft-service - namespace: aviation + namespace: aircraft spec: replicas: 1 selector: @@ -30,15 +35,18 @@ spec: initContainers: - name: wait-for-db image: busybox - command: [ "sh", "-c", "until nc -z aircraft-database.aviation.svc.cluster.local 5432; do sleep 2; done;" ] + command: [ "sh", "-c", "until nc -z aircraft-database.aircraft.svc.cluster.local 5432; do sleep 2; done;" ] - name: wait-for-cache image: busybox - command: [ "sh", "-c", "until nc -z aircraft-cache.aviation.svc.cluster.local 6379; do sleep 2; done;" ] + command: [ "sh", "-c", "until nc -z aircraft-cache.aircraft.svc.cluster.local 6379; do sleep 2; done;" ] containers: - name: aircraft-service image: ghcr.io/edinstance/distributed-aviation-system-services/aircraft:latest ports: - containerPort: 8080 + name: http + - containerPort: 9090 + name: grpc env: - name: ENVIRONMENT value: "prod" diff --git a/k8s/authentication/database.yml b/k8s/authentication/database.yml index 762e3dd..a61843c 100644 --- a/k8s/authentication/database.yml +++ b/k8s/authentication/database.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: authentication-database - namespace: aviation + namespace: authentication spec: clusterIP: None ports: @@ -14,7 +14,7 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: authentication-database - namespace: aviation + namespace: authentication spec: serviceName: authentication-database replicas: 1 diff --git a/k8s/authentication/keygen.yml b/k8s/authentication/keygen.yml index 069f56e..d0e78ff 100644 --- a/k8s/authentication/keygen.yml +++ b/k8s/authentication/keygen.yml @@ -2,7 +2,7 @@ apiVersion: batch/v1 kind: Job metadata: name: authentication-keygen - namespace: aviation + namespace: authentication spec: backoffLimit: 0 template: @@ -53,7 +53,7 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: authentication-keys-pvc - namespace: aviation + namespace: authentication spec: accessModes: - ReadWriteOnce diff --git a/k8s/authentication/migrations.yml b/k8s/authentication/migrations.yml index b353976..a16490e 100644 --- a/k8s/authentication/migrations.yml +++ b/k8s/authentication/migrations.yml @@ -2,7 +2,7 @@ apiVersion: batch/v1 kind: Job metadata: name: authentication-migrations - namespace: aviation + namespace: authentication spec: backoffLimit: 0 template: @@ -16,7 +16,7 @@ spec: - -c - | echo "Waiting for PostgreSQL to become available..." - until nc -z authentication-database.aviation.svc.cluster.local 5432; do + until nc -z authentication-database.authentication.svc.cluster.local 5432; do echo "Still waiting for DB..."; sleep 2; done echo "Database is ready!" diff --git a/k8s/authentication/secrets.yml b/k8s/authentication/secrets.yml index 6eac4b7..f35a535 100644 --- a/k8s/authentication/secrets.yml +++ b/k8s/authentication/secrets.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Secret metadata: name: authentication-key-password - namespace: aviation + namespace: authentication type: Opaque data: password: cGFzc3dvcmQ= @@ -11,7 +11,7 @@ apiVersion: v1 kind: Secret metadata: name: authentication-database-password - namespace: aviation + namespace: authentication type: Opaque data: password: cG9zdGdyZXM= diff --git a/k8s/authentication/service.yml b/k8s/authentication/service.yml index 9f3d024..432f9c4 100644 --- a/k8s/authentication/service.yml +++ b/k8s/authentication/service.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: authentication-service - namespace: aviation + namespace: authentication spec: type: ClusterIP ports: @@ -16,7 +16,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: authentication-service - namespace: aviation + namespace: authentication spec: replicas: 1 selector: @@ -30,7 +30,7 @@ spec: initContainers: - name: wait-for-db image: busybox:1.36 - command: [ "sh", "-c", "until nc -z authentication-database.aviation.svc.cluster.local 5432; do sleep 2; done;" ] + command: [ "sh", "-c", "until nc -z authentication-database.authentication.svc.cluster.local 5432; do sleep 2; done;" ] - name: wait-for-keygen image: busybox:1.36 command: @@ -67,7 +67,7 @@ spec: - name: DEBUG value: "False" - name: ALLOWED_HOSTS - value: localhost,127.0.0.1,authentication-service.aviation.svc.cluster.local,*.aviation.svc.cluster.local,api.aviation.local + value: localhost,127.0.0.1,authentication-service.authentication.svc.cluster.local,authentication-service.aviation.svc.cluster.local,*.authentication.svc.cluster.local,api.authentication.local,api.aviation.local - name: DATABASE_NAME value: authentication - name: DATABASE_USER diff --git a/k8s/cross-namespace-services-aviation.yml b/k8s/cross-namespace-services-aviation.yml new file mode 100644 index 0000000..4aed627 --- /dev/null +++ b/k8s/cross-namespace-services-aviation.yml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-service + namespace: aviation +spec: + type: ExternalName + externalName: flights-service.flights.svc.cluster.local + ports: + - port: 8081 +--- +apiVersion: v1 +kind: Service +metadata: + name: aircraft-service + namespace: aviation +spec: + type: ExternalName + externalName: aircraft-service.aircraft.svc.cluster.local + ports: + - port: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: search-service + namespace: aviation +spec: + type: ExternalName + externalName: search-service.search.svc.cluster.local + ports: + - port: 8082 \ No newline at end of file diff --git a/k8s/flights/cache.yml b/k8s/flights/cache.yml index 5eb46f9..7037fbb 100644 --- a/k8s/flights/cache.yml +++ b/k8s/flights/cache.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: flights-cache - namespace: aviation + namespace: flights spec: ports: - port: 6379 @@ -13,7 +13,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: flights-cache - namespace: aviation + namespace: flights spec: replicas: 1 selector: diff --git a/k8s/flights/database.yml b/k8s/flights/database.yml index e243945..777f129 100644 --- a/k8s/flights/database.yml +++ b/k8s/flights/database.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: flights-database - namespace: aviation + namespace: flights spec: clusterIP: None ports: @@ -14,7 +14,7 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: flights-database - namespace: aviation + namespace: flights spec: serviceName: flights-database replicas: 1 diff --git a/k8s/flights/migrations.yml b/k8s/flights/migrations.yml index d830c9b..5727570 100644 --- a/k8s/flights/migrations.yml +++ b/k8s/flights/migrations.yml @@ -2,7 +2,7 @@ apiVersion: batch/v1 kind: Job metadata: name: flights-migrations - namespace: aviation + namespace: flights spec: backoffLimit: 0 template: @@ -16,7 +16,7 @@ spec: - -c - | echo "Waiting for Postgres to become available..." - until nc -z flights-database.aviation.svc.cluster.local 5432; do + until nc -z flights-database.flights.svc.cluster.local 5432; do echo "Still waiting for DB..."; sleep 2; done echo "Database is ready!" diff --git a/k8s/flights/secrets.yml b/k8s/flights/secrets.yml index b4a2357..17a622b 100644 --- a/k8s/flights/secrets.yml +++ b/k8s/flights/secrets.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Secret metadata: name: flights-database-password - namespace: aviation + namespace: flights type: Opaque data: password: cG9zdGdyZXM= diff --git a/k8s/flights/service.yml b/k8s/flights/service.yml index 955910b..3587b5b 100644 --- a/k8s/flights/service.yml +++ b/k8s/flights/service.yml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: flights-service - namespace: aviation + namespace: flights spec: type: ClusterIP ports: @@ -16,7 +16,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: flights-service - namespace: aviation + namespace: flights spec: replicas: 1 selector: @@ -30,10 +30,10 @@ spec: initContainers: - name: wait-for-db image: busybox - command: [ "sh", "-c", "until nc -z flights-database.aviation.svc.cluster.local 5432; do sleep 2; done;" ] + command: [ "sh", "-c", "until nc -z flights-database.flights.svc.cluster.local 5432; do sleep 2; done;" ] - name: wait-for-cache image: busybox - command: [ "sh", "-c", "until nc -z flights-cache.aviation.svc.cluster.local 6379; do sleep 2; done;" ] + command: [ "sh", "-c", "until nc -z flights-cache.flights.svc.cluster.local 6379; do sleep 2; done;" ] containers: - name: flights-service image: ghcr.io/edinstance/distributed-aviation-system-services/flights:latest @@ -49,13 +49,13 @@ spec: - name: PORT value: "8081" - name: AIRCRAFT_SERVICE_GRPC_URL - value: aircraft-service:9090 + value: aircraft-service.aircraft:9090 - name: OTLP_GRPC_URL value: otel-collector.monitoring:4317 - name: KAFKA_BROKER_URL - value: host.docker.internal:9092 + value: kafka.messaging.svc.cluster.local:9092 - name: KAFKA_SCHEMA_REGISTRY_URL - value: http://host.docker.internal:8081 + value: http://schema-registry.messaging.svc.cluster.local:8081 - name: KAFKA_FLIGHTS_TOPIC value: flights readinessProbe: diff --git a/k8s/messaging/schema-loader.yml b/k8s/messaging/schema-loader.yml index 91ad84a..e9a4226 100644 --- a/k8s/messaging/schema-loader.yml +++ b/k8s/messaging/schema-loader.yml @@ -23,6 +23,7 @@ spec: mkdir -p /config /schemas cp /repo/kafka/script.sh /config/ cp -r /repo/kafka/schemas/* /schemas/ + chmod +x /config/script.sh echo "Config and schemas ready." volumeMounts: - name: config-volume diff --git a/k8s/router/router-config-job.yml b/k8s/router/router-config-job.yml new file mode 100644 index 0000000..f40cd6c --- /dev/null +++ b/k8s/router/router-config-job.yml @@ -0,0 +1,53 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: router-config-fetch + namespace: aviation +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + containers: + - name: config-fetch + image: alpine:3.19 + workingDir: /app + command: + - sh + - -c + - | + set -e + echo "Installing dependencies..." + apk add --no-cache git >/dev/null + echo "Cloning repository..." + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying router configuration..." + cp /repo/router.yml /config/router.yml + echo "Router configuration fetched successfully." + ls -la /config/ + volumeMounts: + - name: router-config-volume + mountPath: /config + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 256Mi + volumes: + - name: router-config-volume + persistentVolumeClaim: + claimName: router-config-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: router-config-pvc + namespace: aviation +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi \ No newline at end of file diff --git a/k8s/router/service.yml b/k8s/router/service.yml index 5f2ba10..0f29bc3 100644 --- a/k8s/router/service.yml +++ b/k8s/router/service.yml @@ -36,23 +36,6 @@ spec: labels: app: router-service spec: - initContainers: - - name: fetch-config - image: alpine/git:2.49.1 - command: - - sh - - -c - - | - echo "Cloning router configuration..." - git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo - echo "Copying supergraph and config files..." - mkdir -p /config - cp /repo/supergraph.graphql /config/supergraph.graphql - cp /repo/router.yml /config/router.yml - echo "Config ready." - volumeMounts: - - name: router-config - mountPath: /config containers: - name: apollo-router image: ghcr.io/apollographql/router:v2.6.2 @@ -60,12 +43,17 @@ spec: - "--supergraph" - /etc/apollo/supergraph.graphql - "--config" - - /etc/apollo/router.yml + - /etc/router/router.yml - "--hot-reload" ports: - containerPort: 4000 - containerPort: 8088 - containerPort: 8089 + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://otel-collector.monitoring.svc.cluster.local:4317 + - name: OTEL_METRICS_EXPORTER_ENDPOINT + value: http://otel-collector.monitoring.svc.cluster.local:4317 readinessProbe: httpGet: path: /health @@ -80,9 +68,16 @@ spec: cpu: 500m memory: 512Mi volumeMounts: - - name: router-config + - name: shared-schema mountPath: /etc/apollo readOnly: true + - name: router-config + mountPath: /etc/router + readOnly: true volumes: + - name: shared-schema + persistentVolumeClaim: + claimName: supergraph-schema-pvc - name: router-config - emptyDir: {} \ No newline at end of file + persistentVolumeClaim: + claimName: router-config-pvc \ No newline at end of file diff --git a/k8s/router/supergraph-job.yml b/k8s/router/supergraph-job.yml new file mode 100644 index 0000000..5e1f4ca --- /dev/null +++ b/k8s/router/supergraph-job.yml @@ -0,0 +1,83 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: supergraph-config + namespace: aviation +data: + supergraph.yml: | + federation_version: =2.3.2 + subgraphs: + flights: + routing_url: http://flights-service.flights.svc.cluster.local:8081/graphql + schema: + subgraph_url: http://flights-service.flights.svc.cluster.local:8081/graphql + aircraft: + routing_url: http://aircraft-service.aircraft.svc.cluster.local:8080/graphql + schema: + subgraph_url: http://aircraft-service.aircraft.svc.cluster.local:8080/graphql + search: + routing_url: http://search-service.search.svc.cluster.local:8082/graphql + schema: + subgraph_url: http://search-service.search.svc.cluster.local:8082/graphql +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: supergraph-composer + namespace: aviation +spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: rover + image: ubuntu:22.04 + command: + - bash + - -c + - | + echo "Installing Rover..." + apt-get update && apt-get install -y curl + curl -sSL https://rover.apollo.dev/nix/latest | sh + export PATH="/root/.rover/bin:$PATH" + + echo "Composing supergraph schema..." + rover supergraph compose \ + --config /config/supergraph.yml \ + --output /shared/supergraph.graphql \ + --elv2-license accept + + echo "Supergraph composed successfully!" + ls -la /shared/ + volumeMounts: + - name: supergraph-config + mountPath: /config + readOnly: true + - name: shared-schema + mountPath: /shared + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + volumes: + - name: supergraph-config + configMap: + name: supergraph-config + - name: shared-schema + persistentVolumeClaim: + claimName: supergraph-schema-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: supergraph-schema-pvc + namespace: aviation +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/load-tests/src/config.ts b/load-tests/src/config.ts index dc3023a..9d11741 100644 --- a/load-tests/src/config.ts +++ b/load-tests/src/config.ts @@ -1,7 +1,7 @@ export const CONFIG = { - flightServiceUrl: __ENV.FLIGHT_URL || "http://localhost:8081/graphql", - aircraftServiceUrl: __ENV.AIRCRAFT_URL || "http://localhost:8080/graphql", - routerUrl: __ENV.ROUTER_URL || "http://localhost:4000", - gatewayUrl: __ENV.GATEWAY_URL || "http://localhost:4001", - authServiceUrl: __ENV.AUTHENTICATION_URL || "http://localhost:8000", + flightServiceUrl: __ENV.FLIGHT_URL || "http://api.aviation.local/flights/graphql", + aircraftServiceUrl: __ENV.AIRCRAFT_URL || "http://api.aviation.local/aircraft/graphql", + routerUrl: __ENV.ROUTER_URL || "http://api.aviation.local/router", + gatewayUrl: __ENV.GATEWAY_URL || "http://api.aviation.local/gateway", + authServiceUrl: __ENV.AUTHENTICATION_URL || "http://api.aviation.local/auth", }; diff --git a/load-tests/src/helpers/auth_headers.ts b/load-tests/src/helpers/auth_headers.ts new file mode 100644 index 0000000..d9a14c0 --- /dev/null +++ b/load-tests/src/helpers/auth_headers.ts @@ -0,0 +1,29 @@ +import { AuthContext } from "../types/auth_context"; + +/** + * Builds authentication headers for GraphQL requests + * @param accessToken - JWT token (for gateway requests) + * @param authContext - Auth context (for direct router/service requests) + * @param useDirectHeaders - Whether to include direct headers (x-user-sub, x-org-id, x-org-name) + */ +export function buildAuthHeaders( + accessToken?: string, + authContext?: AuthContext, + useDirectHeaders: boolean = true +): Record { + const headers: Record = {}; + + // Add JWT token for gateway requests + if (accessToken) { + headers["Authorization"] = `Bearer ${accessToken}`; + } + + // Add direct headers for router/service requests (when JWT isn't being processed by gateway) + if (useDirectHeaders && authContext) { + headers["x-org-id"] = authContext.organization.id; + headers["x-user-sub"] = authContext.admin.id; + headers["x-org-name"] = authContext.organization.name; + } + + return headers; +} \ No newline at end of file diff --git a/load-tests/src/tests/shells/aircraft.ts b/load-tests/src/tests/shells/aircraft.ts index de8074a..192a797 100644 --- a/load-tests/src/tests/shells/aircraft.ts +++ b/load-tests/src/tests/shells/aircraft.ts @@ -11,17 +11,21 @@ import { import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.4.0/index.js"; import { check } from "k6"; import { AuthContext } from "src/types/auth_context"; +import { buildAuthHeaders } from "../../helpers/auth_headers"; export function runAircraftScenario( url: string, accessToken?: string, authContext?: AuthContext, ) { + // Determine if we should use direct headers (for router) vs JWT (for gateway) + const useDirectHeaders = !url.includes("/gateway"); + graphql( url, GetAircraftDocument, { id: uuidv4() }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); const createAircraftRes = graphql< @@ -40,15 +44,7 @@ export function runAircraftScenario( yearOfManufacture: 2020, }, }, - { - ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}), - ...(authContext - ? { - "x-org-id": authContext.organization.id, - "x-user-sub": authContext.admin.id, - } - : {}), - }, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); check(createAircraftRes, { @@ -62,7 +58,7 @@ export function runAircraftScenario( url, GetAircraftDocument, { id: aircraftId }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); } diff --git a/load-tests/src/tests/shells/flights.ts b/load-tests/src/tests/shells/flights.ts index 7b530a3..3b3a389 100644 --- a/load-tests/src/tests/shells/flights.ts +++ b/load-tests/src/tests/shells/flights.ts @@ -10,6 +10,7 @@ import { import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.4.0/index.js"; import { check } from "k6"; import { AuthContext } from "src/types/auth_context"; +import { buildAuthHeaders } from "../../helpers/auth_headers"; function randomFlightNumber(): string { const airlines = ["BA", "UA", "LH", "AF"]; @@ -23,11 +24,14 @@ export function runFlightScenario( accessToken?: string, authContext?: AuthContext, ) { + // Determine if we should use direct headers (for router) vs JWT (for gateway) + const useDirectHeaders = !url.includes("/gateway"); + graphql( url, GetFlightByIdDocument, { id: uuidv4() }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); const createRes = graphql< @@ -44,15 +48,7 @@ export function runFlightScenario( departureTime: new Date().toISOString(), arrivalTime: new Date(Date.now() + 3600 * 1000).toISOString(), }, - { - ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}), - ...(authContext - ? { - "x-org-id": authContext.organization.id, - "x-user-sub": authContext.admin.id, - } - : {}), - }, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); check(createRes, { @@ -66,7 +62,7 @@ export function runFlightScenario( url, GetFlightByIdDocument, { id: flightId }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); } diff --git a/supergraph.yml b/supergraph.yml index 8cd1187..c0bd031 100644 --- a/supergraph.yml +++ b/supergraph.yml @@ -1,14 +1,14 @@ federation_version: =2.3.2 subgraphs: flights: - routing_url: http://flights-service:8081/graphql + routing_url: ${FLIGHTS_SERVICE_URL:-http://flights-service:8081/graphql} schema: file: ./services/flights/internal/graphql/schema.graphqls aircraft: - routing_url: http://aircraft-service:8080/graphql + routing_url: ${AIRCRAFT_SERVICE_URL:-http://aircraft-service:8080/graphql} schema: file: ./services/aircraft/src/main/resources/schema/schema.graphqls search: - routing_url: http://search-service:8082/graphql + routing_url: ${SEARCH_SERVICE_URL:-http://search-service:8082/graphql} schema: file: ./services/search/src/main/resources/schema/schema.graphqls \ No newline at end of file From 1c8de266ea5ec744080dfa1b64ef86af16322a1e Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 3 Nov 2025 21:33:19 +0000 Subject: [PATCH 24/25] fix: removed * allowed hosts --- services/authentication/authentication/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/authentication/authentication/settings.py b/services/authentication/authentication/settings.py index 4cf65a1..f105559 100644 --- a/services/authentication/authentication/settings.py +++ b/services/authentication/authentication/settings.py @@ -31,7 +31,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = config('DEBUG', default=True, cast=bool) -ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost,127.0.0.1,*', cast=lambda v: [s.strip() for s in v.split(',')]) +ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost,127.0.0.1', cast=lambda v: [s.strip() for s in v.split(',')]) # Application definition SHARED_APPS = [ From 64d5e856a66a873c1a80438648d6cc3f786b3d0a Mon Sep 17 00:00:00 2001 From: edinstance Date: Mon, 3 Nov 2025 21:39:36 +0000 Subject: [PATCH 25/25] fix: updated schema registry url --- k8s/search/service.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/search/service.yml b/k8s/search/service.yml index f940362..339d354 100644 --- a/k8s/search/service.yml +++ b/k8s/search/service.yml @@ -46,7 +46,7 @@ spec: - name: KAFKA_BOOTSTRAP_SERVERS value: "kafka.messaging.svc.cluster.local:9092" - name: SCHEMA_REGISTRY_URL - value: "http://schema-registry.messaging:8081" + value: "http://schema-registry.messaging.svc.cluster.local:8081" - name: OTEL_SERVICE_NAME value: "search-service" - name: OTEL_EXPORTER_OTLP_ENDPOINT