Retour aux articles

Building an End-to-End DevOps Path: Rust CI, Kubernetes GitOps, and Observability

A technical retrospective on designing Kiddoo's DevOps delivery path: Rust testing, containers, Kubernetes, GitOps, AWS infrastructure, and monitoring.

Level Sony
Rust DevOps CI/CD GitOps Kubernetes Argo CD Prometheus Grafana Terraform AWS
Building an End-to-End DevOps Path: Rust CI, Kubernetes GitOps, and Observability
Table des matières

Context. Kiddoo is an academic project completed in 2026 as part of a supervised professional simulation. It is a REST API for childcare-service matching. This article documents the architecture and practices implemented; it does not present the platform as a commercial production service.

The problem: delivering without manual runbooks

The starting point was a multi-service Rust API. The challenge was not just to start it: a change had to be verified, packaged, promoted across environments, and checked after deployment.

I therefore treated delivery as one coherent path rather than a series of commands:

  • a change must be tested in a clean environment;
  • the deployed artifact must be identifiable through a versioned image;
  • every environment must explicitly declare its expected version;
  • Kubernetes must converge on that state without manual intervention;
  • the team must be able to tell quickly whether a service is available, slow, or failing.

This approach limits workstation drift, improves traceability, and prepares a clean rollback when a version does not behave as expected.

Application architecture and responsibilities

The application repository is a Rust workspace. It contains a database library and three services:

  • api-gateway, the request entry point;
  • identity-proxy, responsible for authentication-related exchanges;
  • orchestrator, intended to coordinate selected business processes.

PostgreSQL handles persistence. This separation makes services easier to test and containerize, while requiring explicit network contracts and configuration management.

Kiddoo platform architecture

Overview of the Kiddoo architecture and its deployment components.

Containers do not embed credentials or environment-specific settings. Ports, internal URLs, and non-sensitive values are injected at startup; secrets use a separate mechanism. This avoids rebuilding images per environment and reduces the chance of leaking credentials through Git or logs.

First gate: CI in a disposable environment

GitHub Actions provides a clean Linux context for every run. The workflow starts a postgres:17-alpine service, waits for it through pg_isready, and passes the correct connection URL to the tests.

Checks cover the whole workspace:

cargo test --workspace --verbose
cargo fmt --check
cargo clippy -- -D warnings
cargo build --release

Testing the workspace instead of a single binary matters: a persistence-library change can affect several services. Integration tests were also prepared for key routes, including /health, /login, and /me.

Pre-commit hooks complement CI on the developer machine. They catch formatting issues, selected syntax errors, and accidental sensitive files earlier. They do not replace CI; they simply shorten the feedback loop before a push.

Containerizing without reproducing local-machine issues

Each application service has its own Dockerfile. Docker Compose starts the required components locally with an internal network and shared configuration. The gateway is the exposed entry point; the identity proxy and PostgreSQL stay on the application network.

One important detail is that localhost inside a container means that container itself. Inter-service calls therefore use Compose service names such as identity-proxy, rather than fixed IP addresses or localhost.

Data remains separate from the application container lifecycle. Replacing an image with a newer version should not lose database data. This principle also prepares the move from PostgreSQL during tests to RDS PostgreSQL in AWS.

GitOps: making Git the deployment source of truth

The delivery path separates the application from its deployment declaration:

  1. GitHub Actions validates the code and produces an identified image.
  2. The image is published to GitHub Container Registry.
  3. The expected image tag is updated in the target environment configuration.
  4. Argo CD detects the Git change and synchronizes Kubernetes.

Kustomize prevents copying every manifest: a shared base holds common configuration while overlays adjust development, staging, and production settings. This gives each environment a clear role: integrate quickly, qualify in production-like conditions, then promote a stable version.

Commit → CI → GHCR:version image
                    │
                    â–¼
          environment Kustomize overlay
                    │
                    â–¼
            Git repository (desired state)
                    │
                    â–¼
           Argo CD → Kubernetes cluster

GitOps deployment flow for Kiddoo

GitOps deployment flow: a Git change is synchronized by Argo CD with the Kubernetes cluster.

The main benefit is auditability: the requested version and its history are visible in Git. During a regression, returning to a known declaration is more explicit and controllable than directly changing the cluster.

The AWS foundation: Infrastructure as Code and defence in depth

The project also includes AWS infrastructure built with Terraform. Its modular organization separates networking, the EC2 server, RDS PostgreSQL, and dev, staging, and prod environments. An S3 backend stores Terraform state remotely so it is not tied to one local file.

After provisioning, Ansible configures the system. AWS Systems Manager can initiate this work without relying on exposed SSH during initial setup. The security controls include:

  • VPC and subnets separating components;
  • security groups allowing only required flows;
  • private RDS access limited to the application security group;
  • encrypted EBS volumes and RDS storage;
  • Secrets Manager and Ansible Vault to keep secrets out of the repository;
  • Cloudflare Tunnel to expose a service without directly opening its application port;
  • SSH hardening after provisioning, with a firewall and restricted access.

The purpose is not to claim one component secures everything, but to reduce the attack surface at several layers: identity, network, data, secrets, and administration.

Observing the system after deployment

A successful deployment is more than created resources. Services must actually answer requests and their resources must remain healthy over time.

Kubernetes readiness and liveness probes determine whether a pod can receive traffic or needs restarting. Prometheus then collects metrics exposed by services and the platform, while Grafana makes them readable through dashboards.

The selected indicators answer practical operating questions:

  • is the service available?
  • are error rate or response time increasing?
  • are CPU and memory close to saturation?
  • is a pod restarting repeatedly?
  • do authentication failures reveal an anomaly?

Alert rules are planned for these situations. They do not replace human analysis, but they shorten the time from a symptom to its investigation through metrics and logs.

Key takeaways

The value of this work lies in the links between its parts. Tests are useful because they block a faulty image; an image matters because it is versioned; GitOps matters because the requested state is readable; monitoring matters because it verifies the actual effect of a deployment.

The project gave me practical experience of the trade-offs in an end-to-end DevOps path: keeping environments aligned without mixing them, automating without losing control, isolating secrets, and designing for operations from the start.

View the Kiddoo project page.

Commentaires

Assistant portfolio

Pose une question sur Sony

Mémoire locale active: l'assistant adapte ses suggestions à cette visite.