Skip to content

Quick Reference Guide

Fast lookup for common operations.

Cluster Access

# List contexts
kubectl config get-contexts

# Switch context
kubectl config use-context k3s-prod      # Production cluster
kubectl config use-context k3d-local     # Local dev cluster

# Get current context
kubectl config current-context

# Test access
kubectl get nodes

Node Management

# List nodes
kubectl get nodes -o wide

# Get node status
kubectl top nodes
kubectl describe node <node-name>

# Drain node (graceful shutdown)
kubectl drain <node-name> --ignore-daemonsets

# Uncordon node (make available for scheduling)
kubectl uncordon <node-name>

# Taint node (prevent scheduling)
kubectl taint node <node-name> key=value:NoSchedule

# Label node
kubectl label nodes <node-name> workload-type=storage

Pod Management

# List pods
kubectl get pods -A                          # All namespaces
kubectl get pods -n apps                     # Specific namespace
kubectl get pods -l app=moodle              # By label

# Pod details
kubectl describe pod <pod-name> -n <namespace>

# Logs
kubectl logs <pod-name> -n <namespace>
kubectl logs -f deployment/<name> -n <ns>   # Follow
kubectl logs --previous <pod-name> -n <ns>  # Previous crash
# If you get "timed out" or "502 Bad Gateway": see docs/KUBECTL-LOGS-502.md (fix kubelet cert with --node-ip on each node)

# Execute command in pod
kubectl exec -it <pod-name> -n <ns> -- /bin/sh
kubectl exec <pod-name> -n <ns> -- command

# Port forward
kubectl port-forward pod/<name> 8080:8080 -n <ns>
kubectl port-forward svc/<name> 8080:8080 -n <ns>

# Copy files
kubectl cp <pod>:/path/to/file ./local/path -n <ns>
kubectl cp ./local/file <pod>:/path/to/file -n <ns>

Deployment Management

# List deployments
kubectl get deployments -n apps

# Deploy YAML
kubectl apply -f deployment.yaml
kustomize build apps/base/moodle | kubectl apply -f -

# Scale deployment
kubectl scale deployment/<name> --replicas=3 -n <ns>

# Rolling restart
kubectl rollout restart deployment/<name> -n <ns>

# Check rollout status
kubectl rollout status deployment/<name> -n <ns>

# Rollback to previous version
kubectl rollout undo deployment/<name> -n <ns>

# View rollout history
kubectl rollout history deployment/<name> -n <ns>

# Update image
kubectl set image deployment/<name> <container>=image:newtag -n <ns>

# Prune old ReplicaSets (after revisionHistoryLimit is set in manifests)
# List ReplicaSets with 0 desired replicas
kubectl get rs -A | grep '\s0\s'
# Optional: patch deployment to force controller to prune (or rely on next Flux reconcile)
kubectl patch deployment <name> -n <ns> -p '{"spec":{"revisionHistoryLimit":3}}'

Cluster cleanup (ReplicaSets / memory)

  • ReplicaSets: All base deployments use revisionHistoryLimit: 3, so only the last 3 revisions are kept (e.g. Stirling-PDF, Bento). After Flux reconciles, old ReplicaSets are pruned automatically.
  • Homarr RAM: Homarr (Next.js) uses ~1GB by default (Node.js heap). The deployment sets a 512Mi memory limit; if the pod is OOMKilled, raise the limit or set NODE_OPTIONS=--max-old-space-size=384 to cap the V8 heap.

Storage Management

# List PersistentVolumes
kubectl get pv
kubectl describe pv <pv-name>

# List PersistentVolumeClaims
kubectl get pvc -A
kubectl get pvc -n apps

# PVC details
kubectl describe pvc <pvc-name> -n <ns>

# Storage classes
kubectl get storageclass
kubectl describe storageclass longhorn

# Check disk usage
kubectl exec -it <pod> -- df -h /mnt/data

Service Management

# List services
kubectl get svc -n <ns>

# Service details
kubectl describe svc <service-name> -n <ns>

# Get service endpoints
kubectl get endpoints -n <ns>

# Port forward to service
kubectl port-forward svc/<name> 8080:8080 -n <ns>

Ingress Management

# List ingresses
kubectl get ingress -A

# Ingress details
kubectl describe ingress <ingress-name> -n <ns>

# Check ingress status
kubectl get ingress -o wide -n <ns>

Namespace Management

# List namespaces
kubectl get namespaces

# Create namespace
kubectl create namespace myapp

# Delete namespace (WARNING: deletes all resources in it!)
kubectl delete namespace myapp

# Set default namespace
kubectl config set-context --current --namespace=apps

Secret Management

# List secrets
kubectl get secrets -n <ns>

# Create secret
kubectl create secret generic <name> \
  --from-literal=key=value \
  -n <ns>

# View secret (base64 encoded)
kubectl get secret <name> -o yaml -n <ns>

# Decode secret
kubectl get secret <name> -o jsonpath='{.data.password}' -n <ns> | base64 -d

# Delete secret
kubectl delete secret <name> -n <ns>

ConfigMap Management

# List ConfigMaps
kubectl get configmap -n <ns>

# View ConfigMap
kubectl describe configmap <name> -n <ns>

# Create ConfigMap
kubectl create configmap <name> --from-file=file.yaml -n <ns>

# Edit ConfigMap
kubectl edit configmap <name> -n <ns>

Flux Management

# Check Flux status
flux get all --all-namespaces

# Check specific resource
flux get kustomizations --all-namespaces
flux get sources git --all-namespaces

# Force reconciliation
flux reconcile kustomization <name> --with-source
flux reconcile source git <name>

# View logs
flux logs --follow
flux logs --follow deployment/<name> -n <ns>

# Get installed version
flux --version

# Uninstall Flux
flux uninstall --namespace flux-system

Helm Management (if using)

# Add Helm repo
helm repo add <repo-name> <repo-url>
helm repo update

# List charts
helm search repo <repo-name>

# Install chart
helm install <release> <repo>/<chart> -n <ns>

# Upgrade chart
helm upgrade <release> <repo>/<chart> -n <ns>

# List releases
helm list -n <ns>

# Get values
helm get values <release> -n <ns>

# Uninstall
helm uninstall <release> -n <ns>

Skooner Dashboard

# Get login token
kubectl create token skooner-sa -n monitoring --duration=24h
kubectl create token default -n monitoring --duration=24h

# Check Skooner status
kubectl get pods -n monitoring -l app=skooner
kubectl get svc -n monitoring -l app=skooner
kubectl get ingress -n monitoring -l app=skooner

# View Skooner logs
kubectl logs -f deployment/skooner -n monitoring

# Check Flux HelmRelease
flux get helmrelease skooner -n monitoring
flux get source helm skooner -n flux-system

# Force reconciliation
flux reconcile helmrelease skooner -n monitoring
flux reconcile source helm skooner -n flux-system

# Restart Skooner
kubectl rollout restart deployment/skooner -n monitoring

# Port-forward for local access
kubectl port-forward svc/skooner 8080:80 -n monitoring

# Check resource usage
kubectl top pods -n monitoring -l app=skooner

Kustomize

# Build manifest
kustomize build <path> > output.yaml

# Apply built manifest
kustomize build <path> | kubectl apply -f -

# Validate
kustomize build <path> | kubectl --dry-run=client -f - apply

# View differences
kustomize build <path> | kubectl diff -f -

Monitoring & Debugging

# Get cluster events
kubectl get events -A --sort-by='.lastTimestamp'

# Check resource usage
kubectl top nodes
kubectl top pods -n <ns>

# Get resource requests/limits
kubectl describe node <node> | grep -A 5 "Allocated resources"

# Check node conditions
kubectl describe node <node> | grep Condition -A 5

# View API server logs
kubectl logs -n kube-system -l component=kube-apiserver

# Resource quotas
kubectl describe resourcequota -n <ns>

# Network policies
kubectl get networkpolicies -n <ns>

Common Troubleshooting

# Pod won't start
kubectl describe pod <pod> -n <ns>
kubectl logs <pod> -n <ns>
kubectl logs --previous <pod> -n <ns>

# Check PVC binding
kubectl describe pvc <pvc> -n <ns>
kubectl get pv | grep <pvc-name>

# Check node resources
kubectl top nodes
kubectl top pod <pod> -n <ns>
kubectl describe nodes

# Check DNS
kubectl run -it --rm debug --image=busybox --restart=Never -- sh
nslookup kubernetes.default
nslookup myservice.apps.svc.cluster.local

# Connectivity test
kubectl run -it --rm netshoot --image=nicolaka/netshoot --restart=Never -- bash
curl http://myservice.apps.svc.cluster.local:8080

# Restart all pods in deployment
kubectl rollout restart deployment/<name> -n <ns>

# Force delete pod
kubectl delete pod <pod> -n <ns> --grace-period=0 --force

File Editing

# Edit deployment in-place
kubectl edit deployment <name> -n <ns>

# Edit service
kubectl edit svc <name> -n <ns>

# Edit ConfigMap
kubectl edit configmap <name> -n <ns>

# Patch resource
kubectl patch deployment <name> -p '{"spec":{"replicas":3}}' -n <ns>

Export & Backup

# Export all resources
kubectl get all -A -o yaml > cluster-backup.yaml

# Export namespace
kubectl get all -n apps -o yaml > namespace-apps-backup.yaml

# Export specific resource
kubectl get deployment/<name> -n <ns> -o yaml > deployment-backup.yaml

# Export to JSON
kubectl get all -n <ns> -o json > backup.json

YAML Validation

# Validate YAML syntax
kubectl apply -f file.yaml --dry-run=client

# Validate without applying
kubectl apply -k . --dry-run=client

# Show what would change
kubectl apply -k . --dry-run=client -o yaml

# Diff before apply
kustomize build . | kubectl diff -f -

Performance

# Monitor cluster activity
kubectl get events -A --watch

# Show API server latency
kubectl top nodes --use-protocol-buffers

# Check etcd size (on master node)
sudo journalctl -u k3s | grep "etcd size"

# Get resource metrics
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes

SSH to Nodes

# SSH to K3s master node
ssh root@192.168.1.100  # leia

# SSH to K3s worker node
ssh root@192.168.1.101  # luke-1

# SSH to Proxmox host
ssh root@192.168.1.10   # r2d2

# Check K3s status on node
sudo systemctl status k3s
sudo systemctl status k3s-agent

# View K3s logs on node
sudo journalctl -u k3s -f
sudo journalctl -u k3s-agent -f

# K3s commands on node
sudo k3s kubectl get nodes
sudo k3s crictl ps  # View containers

Git Workflow

# Clone repo
git clone https://github.com/yourusername/homelab-gitops

# Create feature branch
git checkout -b feature/add-myservice

# Make changes
# ... edit YAML files

# Stage changes
git add apps/base/myservice/

# Commit
git commit -m "feat: add myservice"

# Push
git push origin feature/add-myservice

# Create PR on GitHub
# Wait for CI validation
# Review and merge

# Verify deployment (Flux auto-deploys)
kubectl get pods -n apps

Environment Variables

# Set context
export KUBECONFIG=~/.kube/config:~/.kube/config-prod
kubectl config use-context k3s-prod

# Set default namespace
export KUBE_NAMESPACE=apps
kubectl get pods -n $KUBE_NAMESPACE

# GitHub credentials (for Flux)
export GITHUB_TOKEN=ghp_xxxxx
export GITHUB_USER=yourusername

Aliases (Add to ~/.bashrc or ~/.zshrc)

alias k='kubectl'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgpvc='kubectl get pvc'
alias kgd='kubectl get deployments'
alias kdesc='kubectl describe'
alias kex='kubectl exec -it'
alias klf='kubectl logs -f'
alias kaf='kubectl apply -f'
alias kdel='kubectl delete'
alias kn='kubectl config set-context --current --namespace'

# Kustomize
alias kbuild='kustomize build'
alias kbuildlocal='kustomize build clusters/local'
alias kbuildprod='kustomize build clusters/production'

# Flux
alias fstat='flux get all --all-namespaces'
alias fsync='flux reconcile kustomization flux-system --with-source'
alias flogs='flux logs --follow'

# Navigation
alias cdgit='cd ~/homelab-gitops'

Useful One-Liners

# Get all pods not in Running state
kubectl get pods -A --field-selector=status.phase!=Running

# Find pods with errors
kubectl get pods -A -o jsonpath='{range .items[?(@.status.containerStatuses[*].state.waiting)]}{.metadata.name}{"\n"}{end}'

# Get resource usage for all pods
kubectl top pods -A --sort-by=memory

# Find pending pods
kubectl get pods -A --field-selector=status.phase=Pending

# List all resources in namespace
kubectl api-resources -n apps

# Get YAML for running resource and edit
kubectl get deployment myapp -o yaml | vim - | kubectl apply -f -

# Compare cluster state with YAML
kustomize build . | kubectl diff -f -

# Get service endpoints
kubectl get svc -A -o wide

# Find pods on specific node
kubectl get pods -A --field-selector=spec.nodeName=leia

# Get PVC usage
kubectl exec -it <pod> -- du -sh /data

# Restart all pods in namespace
kubectl delete pods -n apps --all

# Tail all pod logs in namespace
kubectl logs -f -n apps -l app=moodle --all-containers=true --max-log-requests=10

Emergency Commands

# Force delete stuck pod
kubectl delete pod <pod> -n <ns> --grace-period=0 --force

# Drain and reboot node
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# (reboot node)
kubectl uncordon <node>

# Clear evicted pods
kubectl get pods -n <ns> -o json | jq '.items[] | select(.status.reason=="Evicted")' | jq '.metadata.name' | xargs kubectl delete pod -n <ns>

# Delete namespace stuck in Terminating
kubectl get namespace <ns> -o json | jq '.spec.finalizers = []' | kubectl replace --raw /api/v1/namespaces/<ns>/finalize -f -

# Force delete PVC
kubectl patch pvc <pvc> -p '{"metadata":{"finalizers":null}}' -n <ns>

# Restart Kubelet
ssh root@<node>
sudo systemctl restart k3s-agent

Tip: Bookmark this page or add it to your notes. These commands are frequently needed!

Remember: Always test in k3d first before applying to production.

Last updated: November 2025