Created
April 18, 2023 22:47
-
-
Save peixian/a26e733625baddd0be48648a69bf89a8 to your computer and use it in GitHub Desktop.
This file contains 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
#!/bin/bash | |
######################################################################################################################################### | |
# This file takes in a kubectl context, namespace, pod selector, and erlang cookie and opens a non-hidden connection to the target pod. # | |
# It assumes that your deploy uses the pod IP as an IP address and atom, in the shape of :"SERVICE@<INTERNAL_KUBE_IP>" # | |
# It modifies either `iptables` or `pfctl` depending on your system. # | |
# Sources: # | |
# - https://quan.io/2019/09/02/using-erlangs-observer-in-kubernetes-for-an-elixir-release/ # | |
# - https://gist.github.com/avocade/2fe5f6c01832154eb51f05a2fef692ce # | |
# - https://www.openbsdhandbook.com/pf/cheat_sheet/ # | |
######################################################################################################################################### | |
set -e | |
function cleanup { | |
echo " - Stopping kubectl proxy." | |
kill $! &> /dev/null | |
} | |
trap cleanup EXIT | |
while getopts "n:l:c:ec:u:" opt; do | |
case "$opt" in | |
n) K8S_NAMESPACE="--namespace=${OPTARG}" | |
;; | |
l) K8S_SELECTOR=${OPTARG} | |
;; | |
c) K8S_CONTEXT=${OPTARG} | |
;; | |
ec) ERL_COOKIE=${OPTARG} | |
;; | |
u) ERL_USER=${OPTARG} | |
esac | |
done | |
if [ ! $ERL_COOKIE ]; then | |
ERL_COOKIE="" | |
fi | |
# Required part of config | |
if [ ! $K8S_SELECTOR ]; then | |
echo "[E] You need to specify Kubernetes selector with '-l' option." | |
exit 1 | |
fi | |
echo " - Selecting pod with '-l ${K8S_SELECTOR} ${K8S_NAMESPACE:-default}' selector." | |
POD_NAME=$(kubectl get pods --context ${K8S_CONTEXT} -l ${K8S_SELECTOR} ${K8S_NAMESPACE} -o jsonpath='{.items[0].metadata.name}') | |
echo " - Resolving Erlang node port on a pod '${POD_NAME}'." | |
EPMD_OUTPUT=$(echo ${POD_NAME} | xargs -o -I my_pod kubectl --context ${K8S_CONTEXT} exec my_pod ${K8S_NAMESPACE} -i -t -- /app/erts-13.1.2/bin/epmd -names | tail -n 1) | |
echo " - Got output from epmd: " | |
echo " - ${EPMD_OUTPUT}" | |
eval 'EPMD_OUTPUT=($EPMD_OUTPUT)' | |
if [ ! $ERL_USER ]; then | |
RANDOM_SUFFIX=$(echo $RANDOM | md5sum | head -c 4) | |
ERL_USER="debug-${RANDOM_SUFFIX}" | |
fi | |
# Strip newlines from last element of output | |
OTP_PORT=${EPMD_OUTPUT[4]//[$'\t\r\n ']} | |
echo " - Connecting on port ${OTP_PORT} as user '${ERL_USER}' with cookie '${ERL_COOKIE}'." | |
# Kill epmd on local node to free 4369 port | |
killall epmd || true | |
# Replace it with remote nodes epmd and proxy remove erlang app port | |
echo "kubectl --context ${K8S_CONTEXT} port-forward ${POD_NAME} ${K8S_NAMESPACE} 4369 ${OTP_PORT}" | |
kubectl --context ${K8S_CONTEXT} port-forward $POD_NAME $K8S_NAMESPACE 4369 $OTP_PORT & | |
sleep 1 | |
echo "kubectl --context ${K8S_CONTEXT} get pod ${POD_NAME} -n ${K8S_NAMESPACE} --template '{{.status.podIP}}'" | |
POD_IP=$(kubectl --context ${K8S_CONTEXT} get pod ${POD_NAME} ${K8S_NAMESPACE} --template '{{.status.podIP}}') | |
POD_DEPLOYMENT=$(kubectl --context ${K8S_CONTEXT} get pod ${POD_NAME} ${K8S_NAMESPACE} --template '{{.spec.subdomain}}') | |
ERLANG_NODE="${POD_DEPLOYMENT}@${POD_IP}" | |
echo "connecting to $ERLANG_NODE" | |
function control_c { | |
echo -en "\n## Caught SIGINT; Clean up pfctl and Exit \n" | |
# UNCOMMENT THE FOLLOWING LINE FOR LINUX | |
# sudo iptables -t nat -D OUTPUT -d 10.90.4.143 -j DNAT --to-destination 127.0.0.1 | |
# UNCOMMENT THE FOLLOWING LINE FOR BSD | |
sudo pfctl -f /etc/pf.conf | |
rm ./tmp_pf_rule.conf | |
exit $? | |
} | |
trap control_c SIGINT | |
trap control_c SIGTERM | |
# UNCOMMENT THE FOLLOWING LINES FOR LINUX | |
# -------------------------------------- | |
# echo "Setting IP tables" | |
# sudo iptables -t nat -A OUTPUT -d 10.90.4.143 -j DNAT --to-destination 127.0.0.1 | |
# USE THE FOLLOWING LINES FOR BSD SYSTEMS | |
# --------------------------------------- | |
echo "Enabling pcftl" | |
sudo pfctl -E || true | |
echo "Setting new rule on pfctl" | |
sudo ifconfig lo0 alias $POD_IP | |
echo "rdr pass on lo0 inet proto tcp from any to $POD_IP port 4369 -> 127.0.0.1" > ./tmp_pf_rule.conf | |
echo "rdr pass on lo0 inet proto tcp from any to $POD_IP port $OTP_PORT -> 127.0.0.1" >> ./tmp_pf_rule.conf | |
sudo pfctl -f /etc/pf.conf -f tmp_pf_rule.conf | |
# Start the iex session | |
echo "iex --name $ERL_USER@$POD_IP --cookie $ERL_COOKIE --hidden -e \"Node.connect(:\"$ERLANG_NODE\"); :observer.start\"" | |
iex --name $ERL_USER@$POD_IP --cookie $ERL_COOKIE --hidden -e "Node.connect(:\"$ERLANG_NODE\"); :observer.start" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment