Command snippets

118 tagged one-liners — search by task, not tool name.

Reviewed: ·Tested on: Kubernetes 1.29, Terraform 1.8, Ubuntu 22.04

⚠️ Snippets marked destructive can cause outages — run in staging first.

ECR login + docker push

aws · docker · ci

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com
docker tag myapp:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:latest

Merge EKS into kubeconfig

aws · k8s

aws eks update-kubeconfig --name my-cluster --region us-east-1
kubectl config current-context
kubectl get nodes

Assume IAM role (CLI session)

aws

aws sts assume-role --role-arn arn:aws:iam::123456789012:role/DeployRole --role-session-name deploy
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
aws sts get-caller-identity

Verify AWS identity

aws · debug

aws sts get-caller-identity
aws configure list

Debug DNS/network in pod

k8s · debug

kubectl run netshoot --rm -it --image=nicolaka/netshoot --restart=Never -n <ns> -- /bin/bash
# inside: nslookup kubernetes.default, curl -v svc:port

Port-forward service locally

k8s · debug

kubectl port-forward svc/<service> 8080:80 -n <namespace>
curl -I http://localhost:8080

Helm dry-run debug

k8s

helm upgrade --install myrelease ./chart -n apps -f values.yaml --dry-run --debug
helm template myrelease ./chart -f values.yaml | kubectl apply --dry-run=client -f -

Helm rollback failed release

k8s · debug

helm history myrelease -n apps
helm rollback myrelease <revision> -n apps
helm status myrelease -n apps
⚠️ DestructiveConfirm no other apply is running. Run in staging first — wrong unlock can corrupt state.

Terraform force-unlock

terraform · debug

terraform force-unlock <LOCK_ID>
# LOCK_ID from error message — confirm no other apply running first

Terraform import existing resource

terraform

terraform import aws_instance.web i-0abc123def456
terraform state show aws_instance.web

Terraform plan to file

terraform · ci

terraform init
terraform plan -out=tfplan
terraform apply tfplan

Nginx proxy_pass + timeout fix for 502

nginx · debug

location / {
  proxy_pass http://backend:8080;
  proxy_connect_timeout 60s;
  proxy_send_timeout 60s;
  proxy_read_timeout 60s;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
}
sudo nginx -t && sudo systemctl reload nginx

Tail nginx error log

nginx · debug

sudo tail -f /var/log/nginx/error.log
sudo nginx -t
⚠️ DestructiveRemoves unused images and volumes cluster-wide. Run in staging first — can break cached builds.

Docker cleanup disk space

docker · debug

docker system df
docker system prune -a --volumes
# careful: removes unused images

Follow container logs

docker · debug

docker logs -f <container>
docker inspect <container> --format='{{.State.ExitCode}}'

Logs from crashed pod

k8s · debug

kubectl logs <pod> -n <ns> --previous
kubectl describe pod <pod> -n <ns>
kubectl get events -n <ns> --sort-by='.lastTimestamp'

Diagnose ImagePullBackOff

k8s · debug

kubectl describe pod <pod> -n <ns> | grep -A5 Events
kubectl get secret -n <ns>
# ensure imagePullSecrets if private registry

Rollback deployment

k8s

kubectl rollout history deploy/<name> -n <ns>
kubectl rollout undo deploy/<name> -n <ns>
kubectl rollout status deploy/<name> -n <ns>
⚠️ DestructiveEvicts all pods from the node. Run in staging first — causes workload disruption in prod.

Safely drain node

k8s

kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
kubectl uncordon <node>

Pod CPU/memory usage

k8s · debug

kubectl top nodes
kubectl top pods -A --sort-by=memory

Unseal Vault

debug

vault status
vault operator unseal
# repeat until Sealed: false

GHA OIDC to AWS (workflow snippet)

ci · aws

permissions:
  id-token: write
  contents: read
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123:role/GithubActionsRole
      aws-region: us-east-1

GHA build and push image

ci · docker

- uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
  with:
    push: true
    tags: ghcr.io/org/app:${{ github.sha }}

GHA kubectl apply

ci · k8s

- uses: azure/setup-kubectl@v4
- run: kubectl apply -f k8s/
  env:
    KUBECONFIG: ${{ secrets.KUBECONFIG_B64 }}  # base64-encoded

Bitbucket Pipelines Docker service

ci · docker

definitions:
  services:
    docker:
      memory: 2048
pipelines:
  default:
    - step:
        services:
          - docker
        script:
          - docker build -t myapp .
          - docker push myapp

Revert last commit (safe)

git

git revert HEAD
git push origin main

Restore stashed work

git

git stash list
git stash pop

Renew Let's Encrypt cert

nginx

sudo certbot renew --dry-run
sudo certbot renew
sudo systemctl reload nginx

Follow systemd service logs

debug

sudo journalctl -u <service> -f --since "1 hour ago"
sudo systemctl status <service>

Find what's using disk

debug

df -h
du -sh /* 2>/dev/null | sort -hr | head -20
sudo journalctl --vacuum-time=7d

Check ingress TLS cert expiry

k8s · nginx · debug

kubectl get certificate -A
kubectl describe certificate <name> -n <ns>
echo | openssl s_client -connect app.example.com:443 2>/dev/null | openssl x509 -noout -dates

Debug ingress backend

k8s · debug

kubectl describe ingress <name> -n <ns>
kubectl get endpoints -n <ns>
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=50

Compose up with rebuild

docker

docker compose up -d --build
docker compose ps
docker compose logs -f <service>

Load local image into minikube

docker · k8s

docker build -t myapp:local .
minikube image load myapp:local
# set imagePullPolicy: IfNotPresent in deployment

Switch kube context

k8s

kubectl config get-contexts
kubectl config use-context <context>
kubectl cluster-info

List terraform state resources

terraform · debug

terraform state list
terraform state show aws_instance.web
terraform refresh

Fix CI docker push 401

ci · docker · debug

# Verify registry login in CI before push
docker login registry.example.com -u $CI_USER -p $CI_TOKEN
# K8s: create docker-registry secret
kubectl create secret docker-registry regcred --docker-server=... --docker-username=... --docker-password=... -n <ns>

Shell into running pod

k8s · debug

kubectl exec -it <pod> -n <ns> -- /bin/sh
# or -c <container> if multi-container
⚠️ DestructiveDeletes Failed pods cluster-wide. Verify they are evicted junk, not debugging evidence.

Clean evicted pods

k8s · debug

kubectl get pods -A | grep Evicted
kubectl delete pods -A --field-selector=status.phase=Failed

Tail CloudWatch logs

aws · debug

aws logs tail /aws/lambda/my-function --follow --since 1h
aws logs describe-log-groups --log-group-name-prefix /ecs/

HAProxy backend status

debug

echo "show stat" | socat stdio /var/run/haproxy/admin.sock
curl -I http://backend:port

Test Redis connectivity

debug

redis-cli -h <host> -p 6379 ping
redis-cli -h <host> INFO server

Test PostgreSQL connection

debug

psql -h <host> -U <user> -d <db> -c "SELECT 1"
pg_isready -h <host> -p 5432

Check HTTP response headers

debug · nginx

curl -I https://app.example.com
curl -v http://localhost:8080/health 2>&1 | head -30

Node NotReady / pressure

k8s · debug

kubectl describe node <node>
kubectl get events -A --field-selector involvedObject.kind=Node
# check DiskPressure, MemoryPressure, PIDPressure

Switch terraform workspace

terraform

terraform workspace list
terraform workspace select prod
terraform plan

Fix GitLab runner tag mismatch

ci · debug

# .gitlab-ci.yml tags must match runner
# Settings → CI/CD → Runners → note tags
# tags: [docker, aws]
⚠️ DestructiveDelete only after snapshot. Run in staging account first.

Find unattached EBS volumes

aws · finops

aws ec2 describe-volumes --filters Name=status,Values=available --query 'Volumes[*].[VolumeId,Size,CreateTime]' --output table
# delete after snapshot:
# aws ec2 delete-volume --volume-id vol-xxx
⚠️ DestructiveDeregister only AMIs not referenced by launch templates. Run in staging first.

List old AMIs you own

aws · finops

aws ec2 describe-images --owners self --query 'Images | sort_by(@, &CreationDate)[*].[ImageId,Name,CreationDate]' --output table
# deregister unused:
# aws ec2 deregister-image --image-id ami-xxx

Find load balancers with no targets

aws · finops

for lb in $(aws elbv2 describe-load-balancers --query 'LoadBalancers[*].LoadBalancerArn' --output text); do
  echo "$lb"
  aws elbv2 describe-target-health --target-group-arn $(aws elbv2 describe-target-groups --load-balancer-arn $lb --query 'TargetGroups[0].TargetGroupArn' --output text)
done

Audit pods missing resource requests

k8s · finops

kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[].resources.requests == null) | "\(.metadata.namespace)/\(.metadata.name)"'

Compare requests vs actual usage

k8s · finops · debug

kubectl top pods -A --sort-by=cpu
# vs kubectl get pods -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,CPU:.spec.containers[*].resources.requests.cpu

Trivy scan image before deploy

docker · finops · ci

trivy image --severity HIGH,CRITICAL myapp:tag
trivy image --exit-code 1 --severity CRITICAL myapp:tag

Check Docker image size

docker · finops

docker images myapp --format "{{.Repository}}:{{.Tag}} {{.Size}}"
docker history myapp:latest --no-trunc | head -20

S3 buckets by size (top)

aws · finops

# requires s3 ls + cloudwatch or aws s3api list-objects-v2
aws s3 ls
# enable S3 Storage Lens or Cost Explorer for detail

List long-running EC2 instances

aws · finops

aws ec2 describe-instances --filters Name=instance-state-name,Values=running --query 'Reservations[*].Instances[*].[InstanceId,InstanceType,LaunchTime,Tags[?Key==`Name`].Value|[0]]' --output table

CloudWatch CPU avg (right-sizing hint)

aws · finops

aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization --dimensions Name=InstanceId,Value=i-xxx --start-time $(date -u -v-7d +%Y-%m-%dT%H:%M:%S) --end-time $(date -u +%Y-%m-%dT%H:%M:%S) --period 86400 --statistics Average

PromQL: HTTP 5xx error rate

observe · k8s

# 5xx rate / total rate
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))

# by ingress
sum by (ingress) (rate(nginx_ingress_controller_requests{status=~"5.."}[5m]))

PromQL: pod restart rate

observe · k8s

sum by (namespace, pod) (increase(kube_pod_container_status_restarts_total[1h])) > 3

# top restarters
 topk(10, sum by (pod, namespace) (kube_pod_container_status_restarts_total))

PromQL: P99 latency

observe

histogram_quantile(0.99,
  sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
)

# ingress latency
histogram_quantile(0.99, sum by (le) (rate(nginx_ingress_controller_request_duration_seconds_bucket[5m])))

PromQL: node disk usage %

observe · k8s

100 - (
  avg by (instance) (node_filesystem_avail_bytes{mountpoint="/"}) /
  avg by (instance) (node_filesystem_size_bytes{mountpoint="/"}) * 100
)

PromQL: cert expiry days left

observe · k8s

(certmanager_certificate_expiration_timestamp_seconds - time()) / 86400 < 14

# alert when < 7 days
(certmanager_certificate_expiration_timestamp_seconds - time()) / 86400

LogQL: error lines last 15m

observe

{namespace="apps"} |= "error" or |= "ERROR" or |= "panic"
| json
| line_format "{{.pod}} {{.message}}"

# rate of error log lines
sum(rate({namespace="apps"} |= "error" [5m])) by (pod)

CloudWatch Insights: 5xx / errors

observe · aws

fields @timestamp, @message
| filter @message like /(?i)(error|5\d\d|exception)/
| sort @timestamp desc
| limit 100

# EKS container logs
fields @timestamp, kubernetes.pod_name, @message
| filter @message like /ERROR/
| stats count() by kubernetes.pod_name

GKE kubeconfig merge

gcp · k8s

gcloud container clusters get-credentials my-cluster --region us-central1 --project my-project
kubectl config current-context
kubectl get nodes

GCP Artifact Registry docker push

gcp · docker · ci

gcloud auth configure-docker us-central1-docker.pkg.dev
docker tag myapp:latest us-central1-docker.pkg.dev/my-project/my-repo/myapp:tag
docker push us-central1-docker.pkg.dev/my-project/my-repo/myapp:tag

GKE Workload Identity (KSA → GSA)

gcp · k8s · ci

# Bind K8s SA to GCP SA
gcloud iam service-accounts add-iam-policy-binding GSA@PROJECT.iam.gserviceaccount.com \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:PROJECT.svc.id.goog[NAMESPACE/KSA]"

# Deployment annotation:
# iam.gke.io/gcp-service-account: GSA@PROJECT.iam.gserviceaccount.com

AKS kubeconfig merge

azure · k8s

az aks get-credentials --resource-group my-rg --name my-aks
kubectl config current-context
kubectl get nodes

Azure ACR docker login + push

azure · docker · ci

az acr login --name myregistry
docker tag myapp:latest myregistry.azurecr.io/myapp:tag
docker push myregistry.azurecr.io/myapp:tag

Azure federated creds for GitHub OIDC

azure · ci

az ad app federated-credential create \
  --id $APP_ID \
  --parameters '{
    "name": "github-main",
    "issuer": "https://token.actions.githubusercontent.com",
    "subject": "repo:org/repo:ref:refs/heads/main",
    "audiences": ["api://AzureADTokenExchange"]
  }'
# then azure/login@v2 with client-id, tenant-id, subscription-id

PostgreSQL logical backup (pg_dump)

backup

pg_dump -h <host> -U <user> -d <db> -Fc -f backup-$(date +%F).dump
# custom format (-Fc) supports parallel restore
aws s3 cp backup-$(date +%F).dump s3://my-backups/postgres/
⚠️ DestructiveOverwrites target database. Restore to empty DB or staging first.

PostgreSQL restore from pg_dump

backup

createdb -h <host> -U <user> restore_test
pg_restore -h <host> -U <user> -d restore_test -c backup-2026-06-21.dump
psql -h <host> -U <user> -d restore_test -c "SELECT count(*) FROM users;"

MySQL mysqldump backup

backup

mysqldump -h <host> -u <user> -p --single-transaction --routines <db> > backup-$(date +%F).sql
gzip backup-$(date +%F).sql
aws s3 cp backup-$(date +%F).sql.gz s3://my-backups/mysql/
⚠️ DestructiveDrops and recreates data in target DB. Use staging first.

MySQL restore from dump

backup

gunzip -c backup-2026-06-21.sql.gz | mysql -h <host> -u <user> -p <db>
mysql -h <host> -u <user> -p -e "SELECT COUNT(*) FROM users;" <db>

MongoDB mongodump archive

backup

mongodump --uri="mongodb://user:pass@host:27017/app" --archive=backup-$(date +%F).gz --gzip
aws s3 cp backup-$(date +%F).gz s3://my-backups/mongo/
⚠️ DestructiveRestores into existing collections. Test on empty DB first.

MongoDB restore from archive

backup

mongorestore --uri="mongodb://host:27017" --archive=backup-2026-06-21.gz --gzip --drop
mongosh --eval "db.users.countDocuments()"

Redis RDB snapshot (BGSAVE)

backup · redis

redis-cli -h <host> BGSAVE
redis-cli -h <host> LASTSAVE
# copy /var/lib/redis/dump.rdb to backup storage
scp redis-host:/var/lib/redis/dump.rdb ./backup-$(date +%F).rdb
⚠️ DestructiveStop Redis, replace dump.rdb, restart — data loss if wrong file.

Redis restore RDB file

backup · redis

sudo systemctl stop redis
sudo cp backup-2026-06-21.rdb /var/lib/redis/dump.rdb
sudo chown redis:redis /var/lib/redis/dump.rdb
sudo systemctl start redis
redis-cli ping

Velero backup namespace

backup · k8s · aws

velero backup create apps-$(date +%F) --include-namespaces apps --wait
velero backup describe apps-$(date +%F)
velero backup logs apps-$(date +%F)
⚠️ DestructiveRestores resources into cluster — use --namespace-mappings to staging NS first.

Velero restore from backup

backup · k8s

velero restore create restore-$(date +%F) --from-backup apps-2026-06-21 --wait
velero restore describe restore-$(date +%F)
kubectl get all -n apps

etcd snapshot (control plane)

backup · k8s

ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%F).db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key
etcdctl snapshot status /backup/etcd-$(date +%F).db
⚠️ DestructiveCluster-wide disaster recovery only — follow vendor runbook; wrong step bricks cluster.

etcd restore snapshot

backup · k8s

# STOP API server + etcd on all nodes first — follow your K8s distro docs
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-2026-06-21.db \
  --data-dir=/var/lib/etcd-restore
# then reconfigure etcd to use restored data dir

Terraform state backup (pull local copy)

backup · terraform

terraform state pull > terraform.tfstate.backup-$(date +%F).json
# remote backend: enable S3 versioning on state bucket
aws s3api list-object-versions --bucket my-tf-state --prefix prod/terraform.tfstate
⚠️ DestructiveWrong state version can destroy infra on next apply. Coordinate with team.

Restore Terraform state from S3 version

backup · terraform · aws

aws s3api list-object-versions --bucket my-tf-state --prefix prod/terraform.tfstate
aws s3api get-object --bucket my-tf-state --key prod/terraform.tfstate --version-id <VERSION_ID> terraform.tfstate
terraform state push terraform.tfstate  # only if intentional

AWS RDS manual snapshot

backup · aws

aws rds create-db-snapshot --db-instance-identifier mydb --db-snapshot-identifier mydb-pre-upgrade-$(date +%F)
aws rds wait db-snapshot-available --db-snapshot-identifier mydb-pre-upgrade-$(date +%F)
aws rds describe-db-snapshots --db-instance-identifier mydb

AWS RDS restore snapshot to new instance

backup · aws

aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier mydb-restore-test \
  --db-snapshot-identifier mydb-pre-upgrade-2026-06-21
# verify app against restore-test endpoint before cutover

Sync directory to S3 (config backup)

backup · aws

aws s3 sync /etc/nginx s3://my-backups/nginx/$(hostname)/ --exclude "*.tmp"
aws s3 sync s3://my-backups/nginx/$(hostname)/ ./restore-test/ --dryrun
⚠️ DestructiveOverwrites local files. Dry-run first; restore to temp dir.

Restore files from S3 sync

backup · aws

aws s3 sync s3://my-backups/nginx/myhost/ /tmp/nginx-restore/ --dryrun
aws s3 sync s3://my-backups/nginx/myhost/ /tmp/nginx-restore/
diff -r /etc/nginx /tmp/nginx-restore/

DNS lookup debug (dig + nslookup)

debug · nginx

dig app.example.com +short
dig app.example.com ANY
nslookup app.example.com
# compare to ingress LB: kubectl get ingress -n apps

Test TCP port open (nc / curl)

debug

nc -zv backend.example.com 443
curl -v telnet://backend:8080
ss -tlnp | grep 8080

Restart service safely (systemd)

debug

sudo systemctl status <service>
sudo systemctl restart <service>
sudo journalctl -u <service> -n 50 --no-pager
sudo systemctl is-active <service>

Check TLS cert expiry from CLI

debug · nginx · backup

echo | openssl s_client -connect app.example.com:443 -servername app.example.com 2>/dev/null | openssl x509 -noout -dates -subject
# days left:
echo | openssl s_client -connect app.example.com:443 2>/dev/null | openssl x509 -noout -checkend 604800

Cron backup script template

backup

#!/bin/bash
# /usr/local/bin/backup.sh — install via cron: 0 2 * * * /usr/local/bin/backup.sh
set -euo pipefail
BACKUP_DIR=/var/backups
DATE=$(date +%F)
pg_dump -U app appdb | gzip > "$BACKUP_DIR/appdb-$DATE.sql.gz"
find "$BACKUP_DIR" -name 'appdb-*.sql.gz' -mtime +14 -delete
aws s3 cp "$BACKUP_DIR/appdb-$DATE.sql.gz" s3://my-backups/cron/

PostgreSQL rotate app user password

k8s · backup

# 1. Create parallel user
CREATE USER app_v2 WITH PASSWORD 'new-secret';
GRANT ALL ON DATABASE appdb TO app_v2;
GRANT ALL ON ALL TABLES IN SCHEMA public TO app_v2;
# 2. Update K8s secret + rollout restart
kubectl create secret generic db-creds --from-literal=password=new-secret -n apps --dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deploy/myapp -n apps

Update K8s secret + rolling restart

k8s · ci

kubectl create secret generic app-secrets \
  --from-literal=API_KEY=new-key \
  -n apps --dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deploy/myapp -n apps
kubectl rollout status deploy/myapp -n apps

Verify IRSA role from pod

aws · k8s

kubectl exec -it deploy/myapp -n apps -- env | grep AWS
kubectl exec -it deploy/myapp -n apps -- aws sts get-caller-identity
# expect role ARN matching ServiceAccount annotation

Restart all pods using ServiceAccount

k8s

# after SA annotation change
kubectl rollout restart deploy -n apps
kubectl get pods -n apps -o jsonpath='{range .items[*]}{.metadata.name}{" SA="}{.spec.serviceAccountName}{"\n"}{end}'

Vault KV — write new secret version

debug

vault kv put secret/apps/myapp db_password=new-secret api_key=new-key
vault kv get secret/apps/myapp
# External Secrets Operator syncs within refreshInterval

cert-manager HTTP-01 ClusterIssuer

k8s · nginx

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: ops@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx

cert-manager DNS-01 (Route53 wildcard)

k8s · aws

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-dns
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: ops@example.com
    privateKeySecretRef:
      name: letsencrypt-dns
    solvers:
      - dns01:
          route53:
            region: us-east-1
            hostedZoneID: Z123456
# Certificate dnsNames: [example.com, '*.example.com']

cert-manager self-signed CA Issuer

k8s

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: internal-ca
  namespace: apps
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: internal-tls
  namespace: apps
spec:
  secretName: internal-tls
  issuerRef:
    name: internal-ca
  dnsNames:
    - svc.apps.svc.cluster.local

Quick diff deploy images across contexts

k8s · debug

for ctx in staging prod; do
  echo "=== $ctx ==="
  kubectl --context=$ctx get deploy -n apps -o custom-columns=NAME:.metadata.name,IMAGE:.spec.template.spec.containers[0].image
done

Terraform workspace compare workflow

terraform

terraform workspace list
terraform workspace select staging && terraform plan -no-color > /tmp/plan-staging.txt
terraform workspace select prod && terraform plan -no-color > /tmp/plan-prod.txt
diff -u /tmp/plan-staging.txt /tmp/plan-prod.txt || true

Argo CD — app status and sync

k8s · ci · debug

argocd app list
argocd app get <app> --refresh
argocd app sync <app>
argocd app diff <app>

Argo CD — hard refresh stuck app

k8s · ci · debug

argocd app get <app> --hard-refresh
kubectl patch application <app> -n argocd --type merge -p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"HEAD"}}}'

Flux — force reconcile source/kustomization

k8s · ci · debug

flux get sources git -A
flux get kustomizations -A
flux reconcile source git <name> -n flux-system
flux reconcile kustomization <name> -n flux-system --with-source

Jenkins — kubectl deploy from pipeline

ci · k8s

pipeline {
  agent any
  stages {
    stage('Deploy') {
      steps {
        withKubeConfig([credentialsId: 'kubeconfig']) {
          sh 'kubectl apply -f k8s/'
          sh 'kubectl rollout status deploy/myapp -n apps'
        }
      }
    }
  }
}

Fix failing liveness/readiness probe

k8s · debug

# describe shows probe failures
kubectl describe pod <pod> -n <ns> | grep -A3 Liveness
# common fix — separate paths, longer initialDelaySeconds
readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 10
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  failureThreshold: 3

Debug HPA not scaling

k8s · debug

kubectl get hpa -n <ns>
kubectl describe hpa <name> -n <ns>
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/<ns>/pods" | head
# metrics-server must be running

PromQL: CPU throttling rate

observe · k8s

sum by (pod, namespace) (rate(container_cpu_cfs_throttled_seconds_total[5m]))

# top throttled
 topk(10, sum by (pod) (rate(container_cpu_cfs_throttled_seconds_total[5m])))

PromQL: pod memory vs limit

observe · k8s

sum by (pod, namespace) (container_memory_working_set_bytes)
/
sum by (pod, namespace) (kube_pod_container_resource_limits{resource="memory"}) * 100

# OOM risk > 90%

RBAC — can I perform action?

k8s · debug

kubectl auth can-i create deployments -n apps
kubectl auth can-i get secrets --as=system:serviceaccount:apps:default -n apps
kubectl describe rolebinding -n apps

Elasticsearch cluster health

observe · debug

curl -s http://localhost:9200/_cluster/health?pretty
curl -s http://localhost:9200/_cat/indices?v
curl -s http://localhost:9200/_cat/shards?v | grep UNASSIGNED

GitLab CI — deploy to K8s

ci · k8s

deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context org/cluster
    - kubectl apply -f k8s/
    - kubectl rollout status deploy/myapp -n apps
  only:
    - main

GitHub Actions — deploy to GitHub Pages

ci

name: Deploy Pages
on:
  push:
    branches: [main]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/configure-pages@v5
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./public
      - uses: actions/deploy-pages@v4

SSH ProxyJump to private host

debug · linux

ssh -J bastion@jump.example.com user@10.0.2.50
# ~/.ssh/config:
# Host private
#   ProxyJump bastion@jump.example.com
#   HostName 10.0.2.50
#   User deploy

Fail2ban — protect SSH

linux · debug

sudo apt install fail2ban
sudo tee /etc/fail2ban/jail.local <<'EOF'
[sshd]
enabled = true
port = ssh
maxretry = 5
bantime = 3600
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Chrony NTP sync check

linux · debug

chronyc tracking
chronyc sources -v
timedatectl status