Post

Building a GitOps CI/CD Pipeline with K3s, ArgoCD & Jenkins (1) — Overview & Motivation

Building a GitOps CI/CD Pipeline with K3s, ArgoCD & Jenkins (1) — Overview & Motivation

Introduction

Until recently, my deployment environment was simple. I had a VPS server with Docker installed, and Jenkins would receive a GitHub webhook, build a Docker image, and run the container locally.

1
GitHub Push → Jenkins Build → Docker build → docker run (local)

This approach works, but it has some shortcomings:

  • If a container crashes, I have to restart it manually
  • Rollbacks are tedious
  • Managing many services becomes painful
  • There’s no dashboard to see the deployment state at a glance

While thinking about these issues, I started studying Kubernetes. So I decided to build a lightweight K3s cluster and set up a GitOps-style CI/CD pipeline from scratch.


Why K3s?

The full Kubernetes distribution is heavy and complex. Especially on a single-node VPS like mine, the overhead can be a burden. K3s, on the other hand:

  • Lightweight — runs as a single binary (~60MB)
  • Low-spec friendly — works with 1GB RAM and 1 CPU
  • kubeconfig compatible — standard kubectl commands just work
  • Simple installation — one command to bootstrap the cluster
1
curl -sfL https://get.k3s.io | sh -

After deploying K3s on my server, the overall system resource usage barely increased.


Why GitOps?

GitOps is an operating model that uses Git as the single source of truth.

The difference between traditional deployment and GitOps:

AspectTraditionalGitOps
Deployment triggerJenkins deploys directlyGit repo change → auto sync
State managementManual or scriptsGit repo = desired state
RollbackRedeploy old versionGit revert → auto recovery
VisibilityCheck logsReal-time sync status in dashboard

Adopting GitOps gives you:

  1. Declarative infrastructure — K8s manifests live in Git, so you define desired state, not current state
  2. Self-healing — even if someone deletes a Pod, ArgoCD restores it to the state defined in Git
  3. Audit trail — every change is recorded as a Git commit

Overall Architecture

1
2
3
4
5
6
7
8
9
10
GitHub Push (main branch)
    ↓ (webhook)
Jenkins Pipeline
    ├─ Docker Build (Node 20 + pnpm)
    ├─ GHCR Push (ghcr.io/.../next14-r3f:COMMIT_SHA)
    └─ GitOps repo image tag update
        ↓ (3-min polling)
ArgoCD Auto-Sync
    ↓
K3s cluster deployment

Tech Stack

ToolRoleNotes
K3sLightweight KubernetesSingle node, --disable traefik
ArgoCDGitOps OperatorAuto-sync, Self-Heal
JenkinsCI pipelineGitHub Webhook, Pipeline as Code
GHCRContainer registryGitHub Container Registry
NginxReverse proxySSL + domain routing
Next.jsDeployed applicationR3F-based portfolio site

In the next post, I’ll walk through the actual setup step by step: installing K3s, configuring ArgoCD, and writing the Jenkinsfile.

This post is licensed under CC BY 4.0 by the author.