Last active
October 25, 2024 17:46
-
-
Save aradnom/3f38232df750239580aa1391505df62b to your computer and use it in GitHub Desktop.
Shell functions and aliases for common things I do with kubectl (Kubernetes, K8s)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################### | |
# Kubernetes Shortcuts ######################################################## | |
############################################################################### | |
# Shell functions and aliases for common things I do with kubectl (Kubernetes, | |
# K8s) | |
# | |
# A lot of the below makes the following assumptions: | |
# - That you have separate staging and production clusters or a similar | |
# arrangement | |
# - That deployments are labeled with a git commit sha from whatever project | |
# they pertain to | |
# - That deployment configs are specified as Secrets with a naming convention | |
# of <deployment name>-config | |
# - That metrics-server is installed in your clusters | |
# Typing all 7 letters is for suckers | |
alias k='kubectl' | |
# Port forward to cluster Grafana service | |
alias kgrafana='kubectl port-forward svc/prometheus-grafana 4000:80 -n monitoring' | |
# Port forward internal Redis cluster | |
# This forwards to 6380 on the local machine just in case redis is already | |
# running locally on 6379 | |
# Connect to redis after tunnel is established with `redis-cli -p 6380 -a <pass>` | |
alias kredis='kubectl port-forward svc/redis-master 6380:6379' | |
# Which cluster we talking to right now? | |
alias kcontext='kubectl config current-context' | |
# Flip to staging/production clusters | |
alias kstaging='kubectl config use-context do-nyc3-deskpass-staging' | |
alias kproduction='kubectl config use-context do-nyc3-deskpass-production' | |
alias ksandbox='kubectl config use-context do-nyc3-deskpass-sandbox' | |
# Get live updates on pods/nodes every 2 seconds | |
alias kwatchpods='watch -n2 kubectl top pods' | |
alias kwatchnodes='watch -n2 kubectl top nodes' | |
# Dumpster any current failed pods sitting around | |
alias kclearevicted="kubectl delete pods --field-selector 'status.phase==Failed'" | |
# Dumpster any current completed pods sitting around | |
alias kclearcompleted="kubectl delete pods --field-selector 'status.phase==Succeeded'" | |
# List pods | |
alias kpo="kubectl get pods" | |
# List pods along with which node each pod is assigned to | |
alias kponodes="kubectl get pods -o=custom-columns=NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName" | |
# Forward specified K8s service port to local machine. | |
# | |
# $1: K8s service to forward | |
# $2: Source port in cluster to forward (from port) | |
# $3: Destination local port on your machine (to port) | |
function kportforward { | |
kubectl port-forward svc/$1 $3:$2; | |
} | |
# Set Secret value in specified Secret, generally for the purpose of setting | |
# ENV vars. Existing config var will be run over. Assumes secret names follow | |
# the convention <deployment name>-config. | |
# | |
# $1: Name of Secret to update, without the '-config' bit | |
# $2: Name of var in Secret to set/update | |
# $3: New value to set. Make sure to pass value with single quotes if it | |
# contains nonalphanumeric values | |
function ksetvar { | |
kubectl patch secret $1-config --type='json' \ | |
-p="$(printf '[{"op": "replace", "path": "/data/'$2'", "value": "%s"}]' \ | |
$(printf "$3" | base64 | perl -pe chomp))"; | |
} | |
# Opposite of the above, retrieve a specific env var from specific Secret. Also | |
# assumes secret names follow the convention <deployment name>-config. | |
# | |
# $1: Name of Secret to pull field from | |
# $2: Name of field to retrieve | |
function kgetvar { | |
kubectl get secret $1-config --template={{.data.$2}} | base64 -D && echo; | |
} | |
# Retrieve log history for all commits between staging app and production app | |
# Convenient way to tell at a glance what's different between the two | |
# Run from the folder containing the git history for whatever deployment you're | |
# using this with. | |
# | |
# $1: Name of deployment to pull commit history for (needs to be the same | |
# between both clusters) | |
function kgitdiff { | |
kubectl config use-context do-nyc3-deskpass-production > /dev/null | |
PROD_IMAGE=$(kubectl get deployment $1 -o jsonpath='{.spec.template.spec.containers[].image}') | |
PROD_COMMIT=$(printf "$PROD_IMAGE" | grep -oE '(\d|[a-z]){40}') | |
kubectl config use-context do-nyc3-deskpass-staging > /dev/null | |
STAGING_IMAGE=$(kubectl get deployment $1 -o jsonpath='{.spec.template.spec.containers[].image}') | |
STAGING_COMMIT=$(printf "$STAGING_IMAGE" | grep -oE '(\d|[a-z]){40}') | |
PROD_COMMIT=${PROD_COMMIT/-staging/} | |
git log --pretty=oneline $PROD_COMMIT..$STAGING_COMMIT | grep -v 'Merge branch' | |
} | |
# Quickly spit out current image for staging/production so you can tell if | |
# they're different (assumes you're using unique image names for your | |
# deployments). | |
# | |
# $1: Name of deployment to compare images with | |
function kimagecompare { | |
kubectl config use-context do-nyc3-deskpass-production; | |
printf 'Production: ' && kgetimage $1; | |
kubectl config use-context do-nyc3-deskpass-staging; | |
printf 'Staging: ' && kgetimage $1; | |
} | |
# Retrieve current image for specified deployment. | |
# | |
# $1: Name of deployment to pull image for | |
function kgetimage { | |
kubectl get deployment $1 -o jsonpath='{.spec.template.spec.containers[].image}' && echo; | |
} | |
# Build and deploy Docker image from the current directory. Will: | |
# - Retrieve the current head commit sha to label the new image with | |
# - Build new Docker image (runs a separate script for this) | |
# - Tag and push the new image up to Docker Hub | |
# - Update deployment in K8s with new image tag and label the deployment with it | |
# - Wait for the new deployment to succeed | |
# | |
# $1: Local image name | |
# $2: Image name on Docker hub | |
# $3: Deployment name in cluster | |
function kbuild { | |
DOCKER_IMAGE_NAME=$1 | |
DOCKER_HUB_NAME=$2 | |
DEPLOYMENT_NAME=$3 | |
# Get SHA from latest commit | |
CURRENT_COMMIT=$(git log --pretty=format:'%H' -n 1) | |
# CURRENT_COMMIT=testing | |
# Build updated image | |
./deploy/docker/build.sh; | |
# Tag and push to Docker Hub | |
docker tag $DOCKER_IMAGE_NAME deskpass/$DOCKER_HUB_NAME:$CURRENT_COMMIT; | |
docker push deskpass/$DOCKER_HUB_NAME:$CURRENT_COMMIT; | |
# Deploy updated image to the cluster | |
kubectl set image deployment/$DEPLOYMENT_NAME $DEPLOYMENT_NAME=deskpass/$DOCKER_HUB_NAME:$CURRENT_COMMIT; | |
kubectl label deployment $DEPLOYMENT_NAME "app.kubernetes.io/version=$CURRENT_COMMIT" --overwrite; | |
kubectl rollout status deploy/$DEPLOYMENT_NAME; | |
} | |
# Deploy existing Docker Hub tag to specified deployment in K8s. Will update | |
# the deployment with the specified image tag, label the deployment with the | |
# tag and wait for the rollout to succeed. | |
# | |
# $1: Image name on Docker Hub | |
# $2: Tag name (usually the commit SHA) | |
# $3: Deployment name in cluster | |
function kdeploy { | |
DOCKER_IMAGE_NAME=$1 | |
DOCKER_IMAGE_TAG=$2 | |
DEPLOYMENT_NAME=$3 | |
kubectl set image deployment/$DEPLOYMENT_NAME $DEPLOYMENT_NAME=deskpass/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG; | |
kubectl label deployment $DEPLOYMENT_NAME "app.kubernetes.io/version=$DOCKER_IMAGE_TAG" --overwrite; | |
kubectl rollout status deploy/$DEPLOYMENT_NAME; | |
} | |
# Same story as the above but for a single pod. | |
# | |
# $1: Image name on Docker Hub | |
# $2: Tag name (usually the commit SHA) | |
# $3: Pod name in cluster | |
function kdeploypod { | |
DOCKER_IMAGE_NAME=$1 | |
DOCKER_IMAGE_TAG=$2 | |
POD_NAME=$3 | |
kubectl set image pod/$POD_NAME $POD_NAME=deskpass/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG; | |
kubectl label pod $POD_NAME "app.kubernetes.io/version=$DOCKER_IMAGE_TAG" --overwrite; | |
} | |
# Monitor a specific deployment's resources. Requires metrics-server to be | |
# installed on the cluster. | |
# | |
# $1: Name of deployment to monitor | |
function kwatchdeploy { | |
watch -n 2 "kubectl top po | grep $1"; | |
} | |
# Monitor resources for a specific pod. Requires metrics-server to be | |
# installed on the cluster. | |
# | |
# $1: Name of pod to monitor | |
function kwatchpod { | |
watch -n2 kubectl top pod $1; | |
} | |
# Remote connect to shell in running pod in the cluster. | |
# | |
# $1: ID of pod to connect to | |
function kshell { | |
kubectl exec --stdin --tty $1 -- /bin/sh; | |
} | |
# Remote connect to bash in running pod in the cluster. | |
# | |
# $1: ID of pod to connect to | |
function kbash { | |
kubectl exec --stdin --tty $1 -- /bin/bash; | |
} | |
# Apply manifest to cluster from specified filename. | |
# | |
# $1: Path to file to apply | |
function kapply { | |
kubectl apply -f $1; | |
} | |
# Manually scale specified deployment to specified number of pods. | |
# | |
# $1: Name of deployment to scale | |
# $2: Number of pods to scale deployment to | |
function kscale { | |
kubectl scale deployment $1 --replicas=$2; | |
} | |
# Restart specified deployment. | |
# | |
# $1: Name of deployment to restart | |
function krestart { | |
kubectl rollout restart deployment $1; | |
} | |
# List all pods currently running on a specific node. | |
# | |
# $1: ID of node to list pods for | |
function knodepods { | |
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=$1; | |
} | |
# Edit Secret for specified app. Assumes standard naming format of | |
# <app name>-config. | |
# | |
# $1: Name of secret to edit | |
function kconfig { | |
kubectl edit secret $1-config; | |
} | |
# Dump config values to file for specified app | |
# | |
# $1: Name of app to dump config values for | |
function kdumpconfig { | |
kubectl get secret $1-config -o json | gojq '.data' > ~/Downloads/$1-config-values.json | |
# Format JSON object as lines with separator | |
# printf 'JSON stuff' | gojq -r 'to_entries[] | "\(.key) | \(.value)"' | |
} | |
# Set resource request limits on specified deployment. Assumes deployment and | |
# container have the same name. | |
# | |
# $1: Name of deployment to set limits for | |
# $2: CPU limit to set, see https://bit.ly/k8s-resource-limits | |
# $3: Memory limit to set, see https://bit.ly/k8s-resource-limits | |
function ksetresources { | |
kubectl set resources deployment $1 --requests=cpu=$2,memory=$3; | |
# Made a manual patch version of this before I knew about the set command. | |
# Keeping this around in case it ever seems like something more flexible | |
# than the vanilla set command is needed | |
# kubectl patch deploy $1 --patch '{ "spec": { "template": { "spec": { | |
# "containers": [{ "name": "'$1'", "resources": { | |
# "requests": { "cpu": "'$2'", "memory": "'$3'" | |
# } } }] | |
# } } } }'; | |
} | |
# Retrieve current resource limit/request settings for specified deployment. | |
# | |
# $1: Name of deployment to retrieve resource limits for | |
function kgetresources { | |
kubectl get deploy $1 \ | |
--output=jsonpath='{.spec.template.spec.containers[].resources}' && \ | |
echo; | |
} | |
# Force deletion of a specific pod. Can be useful if a pod gets stuck in | |
# UnknownStatus for whatever reason. | |
# | |
# $1: ID of pod to delete. | |
function kdeletepod { | |
kubectl delete pod $1 --grace-period=0 --force; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment