Skip to content

Instantly share code, notes, and snippets.

@aradnom
Last active April 26, 2024 20:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aradnom/3f38232df750239580aa1391505df62b to your computer and use it in GitHub Desktop.
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)
###############################################################################
# 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 `rdcli -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"
# 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
}
# 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;
}
# 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 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment