DEV Community

Titouan Despierres
Titouan Despierres

Posted on

Building Resilience: Progressive Rollouts for Java AI Microservices with Argo CD and GitHub Actions

Building Resilience: Progressive Rollouts for Java AI Microservices with Argo CD and GitHub Actions

In 2026, the landscape of Java development has shifted. We are no longer just building REST APIs; we are deploying high-performance AI inference engines and RAG (Retrieval-Augmented Generation) services. With the release of JDK 26 and Kubernetes 1.33, the focus has moved from simple deployment to complex, resilient orchestration.

This guide explores a battle-tested pattern for deploying Java 26 AI services using a GitOps approach with Argo CD, GitHub Actions, and Kustomize, focusing on progressive rollouts and observability.


1. The Java 26 Edge: Native Memory and AI

With JDK 26, the Foreign Function & Memory API (JEP 472) and Vector API have matured. For AI workloads using libraries like LangChain4j or Spring AI that interface with local LLMs (via llama.cpp) or vector databases, managing off-heap memory is critical.

Key Change: We can now interface with C++ or CUDA kernels with near-zero overhead.
Impact: Java is no longer "too slow" or "too heavy" for the data plane of AI services.

JVM Strategy for 2026

When running on Kubernetes, your JVM needs to be aware of the cgroup limits. In Java 26, -XX:MaxRAMPercentage=75.0 is still your friend, but you must also account for off-heap memory used by native AI libraries.


2. CI: The Automated Pipeline (GitHub Actions)

Our CI pipeline doesn't just build a JAR; it produces a hardened OCI image and updates the GitOps repository.

.github/workflows/ci.yml

name: CI/CD Pipeline
on:
  push:
    branches: [ main ]
jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 26
        uses: actions/setup-java@v4
        with:
          java-version: '26'
          distribution: 'temurin'

      - name: Build with Maven
        run: ./mvnw clean package

      - name: Docker Build & Push
        run: |
          docker build -t ghcr.io/my-org/ai-service:${{ github.sha }} .
          echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker push ghcr.io/my-org/ai-service:${{ github.sha }}

  update-gitops:
    needs: build-and-push
    runs-on: ubuntu-latest
    steps:
      - name: Checkout GitOps Repo
        uses: actions/checkout@v4
        with:
          repository: my-org/gitops-infra
          token: ${{ secrets.GITOPS_PAT }}

      - name: Update Kustomize Image
        run: |
          cd overlays/production
          kustomize edit set image ai-service=ghcr.io/my-org/ai-service:${{ github.sha }}

      - name: Commit and Push
        run: |
          git config user.name "CI Bot"
          git config user.email "ci@my-org.com"
          git add .
          git commit -m "deploy: update ai-service to ${{ github.sha }}"
          git push
Enter fullscreen mode Exit fullscreen mode

3. CD: Progressive Rollouts with Argo CD & Rollouts

Standard Kubernetes Deployment (RollingUpdate) is often insufficient for AI workloads where a bad model weight update can cause silent failures or high latency. We use Argo Rollouts for Canary deployments.

Argo Rollout Manifest (rollout.yaml)

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: ai-service
spec:
  replicas: 5
  selector:
    matchLabels:
      app: ai-service
  template:
    metadata:
      labels:
        app: ai-service
    spec:
      containers:
      - name: ai-service
        image: ghcr.io/my-org/ai-service:v1
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: "2"
            memory: "4Gi"
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: { duration: 5m }
      - setWeight: 50
      - pause: { duration: 10m }
      - analysis:
          templates:
          - templateName: success-rate
Enter fullscreen mode Exit fullscreen mode

4. Kubernetes 1.33: Sidecar Containers for Observability

In Kubernetes 1.33, the SidecarContainers feature is the production standard. We use it to run an OTel (OpenTelemetry) collector alongside our Java application to capture high-resolution AI metrics (token throughput, prompt latency).

K8s Manifest excerpt

spec:
  containers:
  - name: ai-service
    image: ai-service:latest
  initContainers:
  - name: otel-collector
    image: otel/opentelemetry-collector:latest
    restartPolicy: Always # Kubernetes 1.29+ Native Sidecar
Enter fullscreen mode Exit fullscreen mode

5. Security and Compliance in the Pipeline

With GitLab CI, we can leverage the native Secret Detection and Dependency Scanning for our Java dependencies.

.gitlab-ci.yml (Security focused)

include:
  - template: Jobs/Dependency-Scanning.gitlab-ci.yml
  - template: Jobs/Secret-Detection.gitlab-ci.yml

build:
  image: eclipse-temurin:26-jdk
  script:
    - ./gradlew build
  artifacts:
    paths:
      - build/libs/*.jar
Enter fullscreen mode Exit fullscreen mode

Summary & Strategy for Adoption

  1. Phase 1: Migrate your base image to JDK 26 to benefit from the latest GC optimizations (ZGC refinements).
  2. Phase 2: Implement GitOps with Argo CD to decouple deployment from CI.
  3. Phase 3: Use Argo Rollouts for any service handling LLM inference to ensure stability during updates.

By combining the performance of Java 26 with the reliability of GitOps, we create a platform capable of scaling AI workloads in production with confidence.

Tags: #java #kubernetes #devops #ai

Top comments (0)