About skaffold-orbstack
A skill for developers using Skaffold with an OrbStack local Kubernetes cluster, explaining how to access services without port forwarding. It covers LoadBalancer, Ingress, cluster DNS, migration steps, and troubleshooting.
Key features
- 01Configure Skaffold for OrbStack clusters
- 02Access services through LoadBalancer
- 03Use wildcard DNS and Ingress
- 04Migrate away from port forwarding
- 05Troubleshoot services and DNS
Use cases
- 01Reach local cluster services from macOS
- 02Set up local service addresses with Ingress
- 03Move a Skaffold project off port forwarding
- 04Connect local tools to a cluster database
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill skaffold-orbstackAfter installing, type/skaffold-orbstackin Claude Code to confirm it loaded.
Details
From the project READMESkaffold with OrbStack - Port-Forward-Free Development
When to Use This Skill
| Use this skill when... | Use a sibling Skaffold/container skill instead when... |
|---|---|
| Wiring Skaffold against the OrbStack local Kubernetes cluster | Defining file-sync rules for the inner dev loop (skaffold-filesync) |
Reaching services via *.k8s.orb.local, LoadBalancer, or Ingress without port-forward | Adding pre-deploy test or post-deploy verify stages (skaffold-testing) |
Migrating an existing project off kubectl port-forward onto OrbStack networking | Hardening or shrinking the container image itself (container-development) |
Overview
OrbStack provides superior local Kubernetes networking compared to other tools (minikube, kind, Docker Desktop). Services are accessible directly from macOS without port-forward.
Key OrbStack Advantages
| Feature | OrbStack | minikube/kind |
|---|---|---|
| LoadBalancer auto-provision | ✅ Yes | ❌ Needs MetalLB |
Wildcard DNS (*.k8s.orb.local) | ✅ Yes | ❌ No |
| cluster.local from host | ✅ Yes | ❌ No |
| Pod IP direct access | ✅ Yes | ❌ No |
| Auto HTTPS certificates | ✅ Yes | ❌ No |
Service Access Methods
Method 1: LoadBalancer Services (Simplest)
Change service type from ClusterIP to LoadBalancer:
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
type: LoadBalancer # OrbStack auto-provisions external IP
ports:
- port: 80
targetPort: 8080
selector:
app: my-app
Access: curl http://my-app.default.svc.cluster.local from macOS
Method 2: Ingress with Wildcard DNS (Recommended)
One-time setup - Install Ingress controller:
# Ingress-NGINX (recommended)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml
# OR Traefik
helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik
Create Ingress for your service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
spec:
ingressClassName: nginx
rules:
- host: my-app.k8s.orb.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
Access: http://my-app.k8s.orb.local (auto-resolves)
Method 3: Direct Service DNS (cluster.local)
OrbStack exposes cluster DNS to macOS:
# Access any service directly
curl http://my-app.default.svc.cluster.local:8080
# Full DNS pattern
curl http://<service>.<namespace>.svc.cluster.local:<port>
Skaffold Configuration for OrbStack
Minimal skaffold.yaml (No Port-Forward Needed)
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: my-app
build:
local:
push: false
useBuildkit: true
artifacts:
- image: my-app
docker:
dockerfile: Dockerfile
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/*.yaml
statusCheck: true
statusCheckDeadlineSeconds: 180
# Port-forward REMOVED - use LoadBalancer/Ingress instead
Profile: Local with Ingress
profiles:
- name: local-ingress
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/base/*.yaml
- k8s/ingress/*.yaml # Ingress resources
Profile: Services-Only (Frontend Local Dev)
profiles:
- name: services-only
build:
artifacts: [] # Don't build frontend
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/namespace.yaml
- k8s/database/*.yaml
- k8s/api/*.yaml
Access backend at http://api.k8s.orb.local while running npm run dev locally.
Kubernetes Manifest Templates
LoadBalancer Service Template
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .name }}
labels:
app: {{ .name }}
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: {{ .containerPort | default 8080 }}
selector:
app: {{ .name }}
Ingress Template
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .name }}
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: {{ .name }}.k8s.orb.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .name }}
port:
number: 80
Migration: Port-Forward to LoadBalancer
Before (Traditional)
# skaffold.yaml with port-forward
portForward:
- resourceType: service
resourceName: api
port: 8080
localPort: 8080
address: 127.0.0.1
- resourceType: service
resourceName: frontend
port: 3000
localPort: 3000
address: 127.0.0.1
skaffold dev # Services at localhost:8080, localhost:3000
After (OrbStack Native)
# k8s/services.yaml - Change service types
apiVersion: v1
kind: Service
metadata:
name: api
spec:
type: LoadBalancer # Changed from ClusterIP
ports:
- port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: LoadBalancer # Changed from ClusterIP
ports:
- port: 3000
# skaffold.yaml - Remove portForward section entirely
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/*.yaml
# No portForward needed!
skaffold dev # Services at api.default.svc.cluster.local:8080
# frontend.default.svc.cluster.local:3000
Common Patterns
Database Access
# k8s/postgresql.yaml
apiVersion: v1
kind: Service
metadata:
name: postgresql
spec:
type: LoadBalancer # Access from local tools (DBeaver, pgAdmin)
ports:
- port: 5432
Connection string: postgres://user:[email protected]:5432/db
Multi-Service Application
# k8s/ingress.yaml - Single Ingress for all services
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: nginx
rules:
- host: api.k8s.orb.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 8080
- host: web.k8s.orb.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 3000
- host: admin.k8s.orb.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-panel
port:
number: 8000
Security Considerations
Default: Localhost Only
OrbStack restricts services to localhost by default - safe on untrusted networks.
Expose to LAN (Use with Caution)
Settings → Kubernetes → "Expose services to local network devices"
Only enable when:
- Testing from mobile devices on same network
- Sharing local environment with team
- On trusted network
Troubleshooting
Service Not Accessible
- Check service type:
kubectl get svc - Verify LoadBalancer has EXTERNAL-IP (not
<pending>) - Test DNS:
nslookup my-app.default.svc.cluster.local
Ingress Not Working
- Verify Ingress controller is running:
kubectl -n ingress-nginx get pods - Check Ingress controller has LoadBalancer IP:
kubectl -n ingress-nginx get svc - Verify Ingress resource:
kubectl describe ingress my-app
DNS Resolution Issues
# Test cluster DNS from macOS
nslookup my-service.default.svc.cluster.local
# If short names fail, use full domain
# ❌ my-service.default.svc
# ✅ my-service.default.svc.cluster.local
Pod IP Direct Access (Debugging)
# Get pod IP
kubectl get pods -o wide
# Connect directly (OrbStack routes pod network to macOS)
curl http://10.42.0.15:8080
Agentic Optimizations
| Context | Command |
|---|---|
| Start dev (no port-forward) | skaffold dev --kube-context=orbstack |
| Check service IPs | kubectl get svc -o wide |
| Verify Ingress | kubectl get ingress |
| Test DNS resolution | nslookup my-app.default.svc.cluster.local |
| Check Ingress controller | kubectl -n ingress-nginx get pods |
| Get pod IPs | kubectl get pods -o wide |
| Run specific profile | skaffold dev -p services-only --kube-context=orbstack |
| Describe Ingress | kubectl describe ingress my-app |
Quick Setup Checklist
- Install Ingress controller (one-time)
- Change service types to LoadBalancer
- Create Ingress resources for pretty URLs
- Remove
portForwardfrom skaffold.yaml - Set
kubeContext: orbstackin deploy config - Update local .env/config to use
.k8s.orb.localURLs
Commands Reference
# Start development (no --port-forward needed)
skaffold dev --kube-context=orbstack
# Run specific profile
skaffold dev -p services-only --kube-context=orbstack
# Check service accessibility
kubectl get svc -o wide
# Verify Ingress
kubectl get ingress