MHRubel
HomeAboutProjectsSkillsExperienceBlogContact
MHRubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Software EngineeringTechnologyJune 18, 20263 min read

Ephemeral Environments with vcluster and GitHub Actions Guide

Master ephemeral environments for pull requests using vcluster and GitHub Actions. Learn how to spin up isolated Kubernetes namespaces for faster testing.

kubernetesvclusterdevopsgithub-actionscloud-nativeci-cdautomationLinuxServer

If you’ve ever spent hours debugging a "works on my machine" issue that failed in staging, you know the pain of shared dev environments. They are bottlenecks. Someone deletes a configmap, or a migration goes sideways, and suddenly nobody can work.

I started using ephemeral environments to solve this. By spinning up a fresh, isolated Kubernetes cluster for every pull request preview, we eliminate contention. But spinning up a full EKS or GKE cluster for every PR is expensive and slow. That’s where vcluster changes the game.

Why vcluster for PR Previews?

Standard namespaces are fine, but they don't provide true isolation. If you need custom CRDs, different API versions, or cluster-wide permissions, a namespace won't cut it.

vcluster creates a virtual cluster inside your existing Kubernetes cluster. It’s lightweight, fast, and uses a fraction of the resources of a "real" cluster. Since it runs as a pod, you can spin one up in seconds.

The Architecture

We’ll use GitHub Actions to trigger the creation of a vcluster whenever a PR is opened.

  1. Trigger: PR opened or synchronized.
  2. Setup: Install vcluster CLI and helm in the runner.
  3. Deploy: Create the virtual cluster.
  4. Sync: Deploy the application manifests into the virtual cluster.
  5. Teardown: Delete the vcluster when the PR is closed.

Implementation Guide

First, make sure you have the vcluster CLI installed in your runner. I prefer using the official setup action.

YAML
# .github/workflows/ephemeral.yml
name: PR Ephemeral Environment

on:
  pull_request:
    types: [opened, synchronize, closed]

jobs:
  vcluster-lifecycle:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install vcluster
        run: curl -L -o vcluster "https://github.com/loft-sh/vcluster/releases/latest/download/vcluster-linux-amd64" && sudo install -c -m 0755 vcluster /usr/local/bin

      - name: Create vcluster
        if: github.event.action != 'closed'
        run: |
          vcluster create pr-${{ github.event.number }} --namespace pr-${{ github.event.number }}
          vcluster connect pr-${{ github.event.number }} --kubeconfig=./kubeconfig.yaml

      - name: Deploy App
        if: github.event.action != 'closed'
        run: |
          export KUBECONFIG=./kubeconfig.yaml
          kubectl apply -f k8s/deployment.yaml

      - name: Cleanup
        if: github.event.action == 'closed'
        run: vcluster delete pr-${{ github.event.number }}

Key Considerations for Cloud-Native Development

When you move to this model, you'll hit a few hurdles. Here is how I handle them:

1. Ingress and DNS

How do you access the app? I use ingress-nginx with a wildcard domain. Each vcluster gets a unique subdomain: pr-123.dev.example.com. You’ll need to configure your Ingress controller to route requests based on the host header.

2. Resource Quotas

Don't let a stray PR consume your entire node pool. Always set resource limits on the namespace where the vcluster runs.

YAML
apiVersion: v1
kind: ResourceQuota
metadata:
  name: vcluster-quota
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi

3. Persistent Storage

If your app needs a database, don't spin up a managed RDS instance for every PR. It’s too expensive. Use a lightweight operator like Postgres Operator inside the vcluster or use a shared, pre-provisioned dev database instance.

The "Hard-Won" Lessons

I’ve seen teams try to implement this and fail because they forgot about clean-up. GitHub Actions are great, but if a workflow fails, the cleanup step might not run.

Pro-tip: Use a Kubernetes "Janitor" or a TTL controller. I use the loft CLI or a simple cron job that deletes any namespace prefixed with pr- that hasn't been updated in 24 hours. Never rely solely on the GitHub Actions lifecycle for infrastructure cleanup.

Final Thoughts

Integrating vcluster into your CI/CD pipeline is the single most effective way to improve developer velocity. It gives your team the freedom to break things without affecting their peers. It’s not just about cool tech; it's about removing the fear of deployment.

Start small. Try it on one microservice. Once you see the feedback loop tighten, you won't ever want to go back to shared staging environments.

Back to Blog

Similar Posts

Software EngineeringJune 19, 20263 min read

Implementing Ephemeral Environments with vcluster and Loft

Master ephemeral environments with vcluster and Loft to scale your devops workflow. Learn how to implement Kubernetes multi-tenancy for faster, isolated testing.

Read more
Software EngineeringJune 18, 20266 min read

Implement Chaos Engineering in Kubernetes: Tools, Practices & Real‑World Examples

Chaos engineering, Kubernetes resilience, LitmusChaos, fault injection, DevOps testing – learn practical steps, tool choices, and production‑ready examples to make your clusters fault‑tolerant.

Read more
TechnologyJune 19, 20263 min read

Kubernetes Security: Signing and Verifying Images with Cosign and Kyverno

Master Kubernetes security by implementing image signing and verification. Learn to use Sigstore Cosign and Kyverno to ensure supply chain security and provenance.

Read more