Console Login

GitOps Architecture: Stop Using 'kubectl apply' in Production

The Era of "ClickOps" is Over: A Blueprint for GitOps in 2022

If you are still SSHing into your production servers to run docker-compose up, or worse, manually firing kubectl apply -f . from your laptop, you are operating on borrowed time. I have seen infrastructure crumble because a senior engineer's laptop drive died, taking the only copy of the production config with it. In the high-stakes environment of Norwegian enterprise hostingβ€”where Datatilsynet (The Norwegian Data Protection Authority) watches closely and downtime costs thousands of kroner per minuteβ€”immutability isn't a luxury. It's the baseline.

GitOps isn't just a buzzword; it's the operational model that separates professionals from hobbyists. It creates a single source of truth (Git) for your entire infrastructure. In this guide, we will dismantle the fragile push-based pipelines of the past and architect a robust, pull-based GitOps workflow suitable for deployment on CoolVDS high-performance KVM instances.

The Architecture: Pull vs. Push

Traditional CI/CD pipelines "push" changes to the cluster. This is a security nightmare. It requires your CI runner (often hosted externally, like GitHub Actions or GitLab.com) to have root-level access (cluster-admin) to your Kubernetes cluster. If your CI provider is compromised, your infrastructure is gone.

The GitOps Solution (Pull Model):

  • Git Repository: Holds the desired state (YAML manifests).
  • Container Registry: Holds the immutable artifacts (Docker images).
  • The Controller (ArgoCD): Lives inside your cluster (on your CoolVDS node). It polls the Git repo and applies changes from the inside out. No external credentials enter the cluster.
Pro Tip: Network latency kills reconciliation loops. If your GitOps controller is running in Oslo but your Git repo is hosted in US-East, you will see lag in state synchronization. Hosting your self-managed GitLab instance on a CoolVDS server in the same datacenter as your K8s cluster reduces fetch latency to sub-millisecond levels.

Step 1: The Directory Structure

A disorganized repo leads to drift. I advocate for a Kustomize-based approach, separating base configurations from overlays (environments). This minimizes code duplication.

/gitops-repo
β”œβ”€β”€ /base
β”‚   β”œβ”€β”€ deployment.yaml
β”‚   β”œβ”€β”€ service.yaml
β”‚   └── kustomization.yaml
β”œβ”€β”€ /overlays
β”‚   β”œβ”€β”€ /dev
β”‚   β”‚   β”œβ”€β”€ kustomization.yaml
β”‚   β”‚   └── replica_patch.yaml
β”‚   └── /prod
β”‚       β”œβ”€β”€ kustomization.yaml
β”‚       └── resource_limits.yaml

Step 2: Installing ArgoCD on CoolVDS

We choose CoolVDS for the control plane because etcd and GitOps controllers are I/O hungry. Shared hosting platforms often throttle IOPS, causing ArgoCD to timeout during heavy sync operations. The dedicated NVMe storage on CoolVDS handles high concurrency read/write operations without sweating.

Deploy ArgoCD to your cluster:

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.0/manifests/install.yaml

Once installed, you define an Application. This tells the controller: "Make the cluster look like this Git repo."

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nordic-payment-gateway
  namespace: argocd
spec:
  project: default
  source:
    repoURL: 'git@gitlab.coolvds-internal:devops/payments.git'
    targetRevision: HEAD
    path: overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: payments-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

The selfHeal: true flag is the magic. If someone manually changes a service port via kubectl, ArgoCD detects the drift and immediately reverts it to the state defined in Git. This ensures strict compliance and prevents "config creep."

Step 3: Managing Secrets (The Hard Part)

You cannot commit raw secrets to Git. In 2022, the standard for this is Bitnami Sealed Secrets. It uses asymmetric cryptography. You encrypt the secret on your laptop using a public key; only the controller inside the cluster (which holds the private key) can decrypt it.

Workflow:

  1. Install the controller on your cluster.
  2. Use kubeseal to encrypt your .env file.
# Create a raw secret (dry run)
kubectl create secret generic db-creds --from-literal=password=SuperSecureNorwegianPwd! --dry-run=client -o yaml > secret.yaml

# Seal it
kubeseal --format=yaml --cert=pub-cert.pem < secret.yaml > sealed-secret.yaml

You can safely commit sealed-secret.yaml to a public GitHub repo. Even if it leaks, it is useless without the private key stored securely on your CoolVDS volume.

Step 4: CI Integration

Your CI pipeline (GitLab CI or Jenkins) should no longer deploy. Its job is solely to test code, build images, and update the Kubernetes manifest repo.

Here is a snippet for a GitLab CI job that updates the image tag in the GitOps repo:

deploy_manifest:
  stage: deploy
  image: alpine:3.15
  before_script:
    - apk add --no-cache git
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
  script:
    - git clone git@gitlab.com:company/infra-repo.git
    - cd infra-repo/overlays/prod
    - sed -i "s/newTag: .*/newTag: $CI_COMMIT_SHORT_SHA/" kustomization.yaml
    - git config user.email "ci-bot@coolvds.com"
    - git config user.name "CI Bot"
    - git commit -am "Update image to $CI_COMMIT_SHORT_SHA"
    - git push origin main

Why Infrastructure Matters for GitOps

GitOps increases the load on your control plane. You have controllers constantly diffing state, pulling git repos, and managing secrets. I've seen standard cloud VPS instances choke on this workload, leading to CrashLoopBackOff on the ArgoCD repo-server.

The CoolVDS Advantage:

Feature Generic VPS CoolVDS KVM
Storage Shared SSD (Variable Latency) Dedicated NVMe (Consistent IOPS)
CPU Steal High (Noisy Neighbors) Near Zero (Dedicated Resources)
Data Sovereignty Often routed via US/EU-West Local Storage (Oslo/Norway compliant)

Compliance & The "Schrems II" Reality

For Norwegian companies, storing customer data outside the EEA is becoming a legal minefield. By hosting your Kubernetes cluster and your GitOps data on CoolVDS, you ensure data residency within Norway. This simplifies GDPR compliance significantly compared to using managed K8s services from US hyperscalers, where data transfers are often opaque.

Conclusion

Moving to GitOps requires a shift in mindset, but the payoff is stability. When your infrastructure is code, disaster recovery becomes as simple as git clone and kubectl apply. However, this automation requires a robust foundation. A flaky underlying server will break even the most perfect pipeline.

Don't let I/O wait times bottleneck your deployment frequency. Build your GitOps platform on infrastructure that respects your engineering standards.

Ready to harden your pipeline? Deploy a high-performance NVMe KVM instance on CoolVDS today and see the difference dedicated resources make.