Skip to content

DevOps Flow

This document explains the complete flow of your code from your local machine to running in production on our Kubernetes cluster. Understanding this distinction between local and remote execution is crucial for working effectively with CI/CD pipelines.

Key Concepts: Local vs Remote

Local (Your Laptop)

  • You write and test code here
  • You use git to commit and push changes
  • Running mvn or Docker locally tests on your machine only
  • Changes here don't affect the game running on the server

Remote (Our Servers)

  • GitLab server stores your code
  • GitLab Runners build your code automatically
  • Container images are stored in the registry
  • Kubernetes cluster runs the actual game

Important: When you push code to GitLab, it doesn't run on your laptop anymore. The CI/CD pipeline runs on our runners, and the final application runs in our Kubernetes cluster.


Complete CI/CD Flow

%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#0066cc','lineColor':'#0066cc','secondaryColor':'#fff4e6','tertiaryColor':'#f0f0f0','fontSize':'14px'}}}%%
graph TB
    subgraph Local["🏠 LOCAL ENVIRONMENT"]
        direction TB
        Dev["👨‍💻 You (Developer)<br/>Write Java code<br/>Test locally"]
        LocalGit["📁 Local Git Repository<br/>.git folder"]

        Dev -->|"1. git commit"| LocalGit
    end

    subgraph Remote["🌐 REMOTE ENVIRONMENT"]
        direction TB

        GitLab["🦊 GitLab Server<br/>Stores your code<br/>Manages CI/CD"]

        subgraph Runner["⚙️ GitLab Runner"]
            direction TB
            Build["📦 Build Job<br/>mvn package<br/>Jib builds image"]
            Test["✅ Test Job<br/>mvn test"]
            Deploy["🚀 Deploy Job<br/>kubectl apply"]
        end

        Registry["📦 Container Registry<br/>Stores Docker images<br/>gitlab.stud.atlantis.ugent.be:5050"]

        subgraph K8s["☸️ Kubernetes Cluster"]
            direction TB
            Pods["🎮 Your Running Pods<br/>Actual game instances"]
        end
    end

    %% Flow connections
    LocalGit ==>|"2. git push"| GitLab
    GitLab -->|"3. Triggers pipeline"| Runner
    Build -->|"4. Pushes image"| Registry
    Build -.->|"on success"| Test
    Test -.->|"on success"| Deploy
    Deploy -->|"5. kubectl apply<br/>(updates deployment)"| K8s
    K8s -->|"6. Pulls new image"| Registry

    %% Styling
    classDef localStyle fill:#e8f4f8,stroke:#0066cc,stroke-width:3px
    classDef remoteStyle fill:#fff4e6,stroke:#ff9900,stroke-width:2px
    classDef runnerStyle fill:#f0f0f0,stroke:#666,stroke-width:2px
    classDef k8sStyle fill:#e6f3ff,stroke:#0066cc,stroke-width:2px

    class Local localStyle
    class Remote,GitLab,Registry remoteStyle
    class Runner,Build,Test,Deploy runnerStyle
    class K8s,Pods k8sStyle

Understanding Each Step

  1. Local Development (git push)

    • You write code on your laptop in your IDE
    • You commit changes with git commit
    • You push to GitLab with git push
    • Nothing runs yet! Code is just uploaded to GitLab
  2. Pipeline Trigger

    • GitLab detects the push
    • Automatically starts your .gitlab-ci.yml pipeline
    • Assigns jobs to available GitLab Runners
  3. Build Phase (in Runner container)

    • Runner creates a fresh Docker container with JDK
    • Downloads your code from GitLab
    • Downloads Maven dependencies
    • Runs mvn package to compile your Java code
    • Uses Jib to build a Docker image
    • Pushes the image to the Container Registry
    • This is NOT on your laptop! It's on our runner servers
  4. Test Phase (in Runner container)

    • New container is created
    • Runs your unit and integration tests
    • If tests fail, pipeline stops here
  5. Deploy Phase (in Runner container)

    • Runner executes kubectl apply commands
    • Sends deployment instructions to Kubernetes cluster
    • Still not on your laptop! Runner talks to Kubernetes
  6. Kubernetes Deployment

    • Kubernetes receives the deployment update
    • Pulls the new Docker image from the Registry
    • Stops old pods, starts new pods with your updated code
    • Your code is now running in the game!

Kubernetes Cluster Architecture

Our Kubernetes cluster consists of 3 control plane nodes and 3 worker nodes. Here's how it's organized:

%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e6f3ff','primaryTextColor':'#000','primaryBorderColor':'#0066cc','lineColor':'#666','fontSize':'14px'}}}%%
graph TB
    subgraph Cluster["☸️ IDLab Kubernetes Cluster"]
        direction TB

        ControlPlane["🎛️ Control Plane<br/>(3 nodes for high availability)<br/><br/>• API Server<br/>• Scheduler<br/>• Controller Manager"]

        subgraph Workers["👷 Worker Nodes (3 nodes)"]
            direction LR

            Worker1["Worker Node 1<br/><br/>🎮 Team pods<br/>(your applications)<br/><br/>🎮 Backend"]
            Worker2["Worker Node 2<br/><br/>🎮 Team pods<br/>(your applications)<br/><br/>🎮 Frontend"]
            Worker3["Worker Node 3<br/><br/>🎮 Team pods<br/>(your applications)<br/><br/>🎮 Monitoring"]
        end
    end

    kubectl["💻 kubectl<br/>(from CI/CD)"]
    Registry2["📦 Container Registry"]

    kubectl -->|"kubectl apply"| ControlPlane
    ControlPlane -->|"schedules pods on"| Workers

    Worker1 -.->|"pulls images"| Registry2
    Worker2 -.->|"pulls images"| Registry2
    Worker3 -.->|"pulls images"| Registry2

    classDef controlStyle fill:#fff4e6,stroke:#ff9900,stroke-width:3px
    classDef workerStyle fill:#e6f3ff,stroke:#0066cc,stroke-width:2px

    class ControlPlane controlStyle
    class Workers,Worker1,Worker2,Worker3 workerStyle

Cluster Components Explained

Control Plane (3 nodes for high availability)

  • API Server: Receives commands from kubectl in your CI/CD pipeline
  • Scheduler: Decides which worker node should run each pod
  • Controller Manager: Ensures desired state matches actual state (e.g., if a pod crashes, it restarts it)
  • 3 nodes provide redundancy - if one fails, the others keep working

Worker Nodes (3 nodes for running applications)

  • Each worker node can run multiple pods
  • Each pod contains one or more Docker containers
  • Your logic-service runs as a pod on one of these workers
  • Kubernetes automatically distributes pods across workers depending on availability and load

Key Point: When you run kubectl apply in your CI/CD pipeline:

  1. Command goes to the Control Plane
  2. Control Plane schedules your pod on a worker node
  3. Worker node pulls your Docker image from the registry
  4. Your application starts running in a pod

Common Misconceptions

"When I push to GitLab, my code runs on GitLab"

Reality: GitLab stores your code. The CI/CD pipeline runs on GitLab Runners (separate machines), and your final application runs in the Kubernetes cluster.

"If it works on my laptop, it will work in Kubernetes"

Reality: Your laptop and Kubernetes are different environments. Always test using the CI/CD pipeline. Environment variables, networking, and resource limits differ.

"The Docker image is built on my machine"

Reality: When using CI/CD, the image is built by the GitLab Runner in a container on our servers, not on your laptop.

"kubectl commands in my CI/CD affect my local machine"

Reality: kubectl in CI/CD connects to the remote Kubernetes cluster using the KUBECONFIG credentials. It never touches your laptop.


Quick Reference: Where Does What Run?

Activity Where It Happens Tool/Command
Writing code Your laptop IDE (IntelliJ, VSCode)
Running code locally Your laptop mvn quarkus:dev
Storing code GitLab Server git push
Building in CI/CD GitLab Runner .gitlab-ci.yml
Storing images Container Registry Jib/Docker
Running the game Kubernetes Cluster kubectl apply
Viewing logs Kubernetes Cluster kubectl logs

What Happens When You Change Code?

%%{init: {'theme':'base'}}%%
sequenceDiagram
    actor Dev as 👨‍💻 You
    participant Laptop as 🏠 Your Laptop
    participant GitLab as 🦊 GitLab
    participant Runner as ⚙️ Runner
    participant Registry as 📦 Registry
    participant K8s as ☸️ Kubernetes

    Dev->>Laptop: 1. Edit Java file
    Dev->>Laptop: 2. git commit
    Dev->>GitLab: 3. git push

    Note over GitLab: Code stored on GitLab server

    GitLab->>Runner: 4. Start pipeline

    Note over Runner: Fresh container created

    Runner->>Runner: 5. mvn package (build)
    Runner->>Registry: 6. Push Docker image
    Runner->>K8s: 7. kubectl apply

    Note over K8s: Old pod terminated

    K8s->>Registry: 8. Pull new image
    K8s->>K8s: 9. Start new pod

    Note over K8s: Your updated code is now running!

    Dev->>K8s: 10. kubectl logs (check if it works)

Remember: Steps 4-9 happen entirely on remote servers. Your laptop is only involved in steps 1-3 and 10!