Skip to content

Instantly share code, notes, and snippets.

@antitree
Last active August 26, 2020 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antitree/ae0e065482b4941fb8e433f7054d2cf4 to your computer and use it in GitHub Desktop.
Save antitree/ae0e065482b4941fb8e433f7054d2cf4 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Ephemeral container deployer
# Author: @antitree
# This patches over a pod to add an ephemeral container, mounts share volumes,
# enters the namespace and some other shit.
function description() {
echo -e "\nDescription: This plugin speeds up the process of patching a Pod with an
ephemeral container. It will automatically mount the PID namespace, secrets, and other volumes
to help with debugging or reviewing the main container. \n\n
$(usage)
"
#exit 0
}
function usage() {
echo -e "\teph -p PODNAME [-s] [-o] [-i IMAGE/NAME] [-n NAMESPACE]
-p PODMAN name of pod [required]
-s automount storage from pod
-o output JSON to terminal instead of directly deploying
-i IMAGE/NAME image to deploye (antitree/brick)
-n NAMESPACE namespace (default)"
}
function find_secrets() {
echo $(kubectl get pod $DEBUG_PODNAME -o=jsonpath='{range .spec..volumes[*].secret}{.secretName}{"\n"}{end}')
}
function _kube_list_pods() {
# dump a menu of all the available pods
IFS=';' read -ra pods <<< "$(kubectl get pods -n $DEBUG_NAMESPACE -o go-template='{{range .items}}{{.metadata.name}}:{{.metadata.namespace}}:{{.status.phase}}{{"\n"}}{{end}}' | sort -k 2 -k 1 -t: | tr '\n' ';')"
local count=1
lines=$(for i in ${pods[@]}; do
IFS=":" read -ra TOKS <<< "${i}"
printf " $count) ${TOKS[0]}\t${TOKS[1]}\t${TOKS[2]}\n"
((count=count+1))
done | column -t)
count=$(echo "$lines" | wc -l)
echo "$lines" >&2
local sel=0
while [[ $sel -lt 1 || $sel -gt $count ]]; do
read -p "Select a Pod: " sel >&2
done
echo "${pods[(sel-1)]}"
}
while getopts "hon:i:p:s" arg; do
case $arg in
n) # Add Namespace
export DEBUG_NAMESPACE="${OPTARG}"
;;
s) # Add Storage
export DEBUG_STORAGE="true"
;;
p) # Add podname account
export DEBUG_PODNAME="${OPTARG}"
;;
i) # Choose an image
export DEBUG_IMAGE="${OPTARG}"
;;
h) # Show help
description
exit 1
;;
o) # Output to terminal
TERMINAL="true"
;;
:) # Show help
description
exit 1
;;
esac
done
shift $((OPTIND-1))
if [[ -z ${DEBUG_NAMESPACE} ]]; then
DEBUG_NAMESPACE="default"
fi
# Validate the podname
if [[ -z ${DEBUG_PODNAME} ]]; then
echo "Missing podname"
SEL=$(_kube_list_pods)
IFS=":" read -ra DEBUG_PODNAME <<< "${SEL}"
#description
#exit 2
fi
# Look for storage mounts
if [[ -n ${DEBUG_STORAGE} ]]; then
POD_STORAGE=$(kubectl get pod $DEBUG_PODNAME -o=json | jq ".spec.containers[].volumeMounts")
if [[ $? -gt 0 ]];then
POD_STORAGE="[{}]"
fi
else
POD_STORAGE="[{}]"
fi
function attach() {
# Instructions to attach
echo
echo
echo "Ephemeral container appears to be created. Attach to it like so:"
echo -e "\tkubectl exec -it $DEBUG_PODNAME -c ${DEBUG_NAME:=debugger} -- /bin/bash"
}
function yaml() {
# Template YAML for ephemeral container
echo -e '
{
"apiVersion": "v1",
"kind": "EphemeralContainers",
"metadata": {
"name": "${DEBUG_PODNAME}"
},
"ephemeralContainers": [{
"command": [
"bash"
],
"image": "${DEBUG_IMAGE:=antitree/brick}",
"imagePullPolicy": "IfNotPresent",
"name": "${DEBUG_NAME:=debugger}",
"stdin": true,
"tty": true,
"terminationMessagePolicy": "File",
"targetContainerName": "${DEBUG_PODNAME}",
"volumeMounts":
${POD_STORAGE},
"env": [{
"name": "MY_POD_SERVICE_ACCOUNT",
"valueFrom":{
"fieldRef": {
"fieldPath": "spec.serviceAccountName"
}
}
}]
}]
}
_EOT_'
}
# Output to terminal or directly to kubernetes
if [[ -z ${TERMINAL} ]] ; then
eval "cat <<-_EOT_ $(yaml)" | kubectl replace --raw "/api/v1/namespaces/${DEBUG_NAMESPACE}/pods/${DEBUG_PODNAME}/ephemeralcontainers" -f - && attach
else
eval "cat <<-_EOT_ $(yaml)"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment