确定在随机本地端口上进行端口转发时使用的本地端口



kubectl允许一个端口转发到类似的远程服务

$ kubectl port-forward service/my-service :12345 

如何查找kubectl在此命令中选择并使用的本地端口

其他详细信息:我希望能够从脚本中确定这一点,该脚本为服务寻找活动端口转发。如果找不到端口转发,它会在一个空闲的本地端口上创建一个端口转发,并返回端口号(这就是上面所做的(

使用$ kubectl port-forward service/my-service :12345命令时,必须获得如下输出:

Forwarding from 127.0.0.1:XXXX -> YYYY
Forwarding from [::1]:XXXX -> YYYY

这是识别本地所选端口的唯一方法,您可以在脚本中添加一条从输出中读取该值的指令。XXXX号是本地选择的端口号。我可以建议您使用服务类型Nodeport,而不是端口转发。使用NodePort,您可以将应用程序作为服务公开,并可以从Kubernetes外部访问。查看以下文档以获取更多示例。

这(bash函数(可能不是一种更干净的方法,但适用于kubeadm集群。尝试对不同的pod/svc同时进行多个转发。

get_local_port()
{
port="${1}"
if [ -z "${port}" ];then
echo "[Error]: 1st argument should be the remote port number"
return 1
fi
netstat -plnt |
awk -vpid="$(ps -eaf |awk -v port=${port} '{if(match($0,"port-forward.*"port)) printf "%s|", $2}'|sed -r 's/.$//g')" '{if(match($NF,"^"pid"/")) {split($4,a,":");print a[2]}}'
}

用法:

get_local_port <remote-port-number>

解释:

此命令解析ps -eaf以获得port-forwarding命令的PID,然后通过netstat解析它以获得本地端口。

我无法找到任何其他方法,所以我结束了编写一个脚本,该脚本可以动态地找到一个空闲端口,设置一个转发,然后返回该端口。如果匹配的转发端口已经存在,它可以返回。示例用法如下。请注意,目前我使用另一个脚本来确定一个可用的本地端口,然后使用该端口号来设置端口转发,并且本可以解析我在问题中提到的通用端口转发命令的输出,但我相信这种方法不那么脆弱,而且更可重复使用。

$ kpf help
kubernetes port forward helper
* helps you transparently ensure a port forward is setup for a service.
usage: kpf [require|get|create|remove|remove_all] {SERVICEI} {REMOTE_PORT} {EXTRA_ARGS}
e.g.
# get or create a port forward for your-service on remote port 8080
# returns the port if successful, or fails and shows an error message
kpf require service/your-service 8080
# return any existing port forwards for your-service on remote port 8080, or nothing
kpf get service/your-service 8080
# create a new local port forward for your-service on remote port 8080, returning port used
kpf create service/your-service 8080
# remove any port forwards found to your-service on remote port 8080
kpf remove service/your-service 8080
# remove ALL port forwards to any kubernetes remote ports
kpf remove_all

kpf

#!/usr/bin/env bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; PATH="$DIR:$PATH"
ME=$(basename "$0")
function show_help()
{
IT=$(cat <<EOF
kubernetes port forward helper
* helps you transparently ensure a port forward is setup for a service.
usage: $ME [require|get|create|remove|remove_all] {SERVICE} {REMOTE_PORT} {EXTRA_ARGS}
e.g.
# get or create a port forward for your-service on remote port 8080
# returns the port if successful, or fails and shows an error message
$ME require service/your-service 8080
# return any existing port forwards for your-service on remote port 8080, or nothing
$ME get service/your-service 8080
# create a new local port forward for your-service on remote port 8080, returning port used
$ME create service/your-service 8080
# remove any port forwards found to your-service on remote port 8080
$ME remove service/your-service 8080
# remove ALL port forwards to any kubernetes remote ports
$ME remove_all 
# create a port forward on local port 4569, for localstack, in namespace localstack
$ME create svc/localstack 4569:4569 --namespace localstack  
EOF
)
echo "$IT"
echo
exit
}
if [ -z "$1" ]
then
show_help
fi
if [ "$1" = "help" ] || [ "$1" = '?' ] || [ "$1" = "--help" ] || [ "$1" = "h" ]; then
show_help
fi
OP=$1
SERVICE=$2
REMOTE_PORT=$3
if [ -n "$4" ]
then
shift;
shift;
shift;
EXTRA_ARGS="$@"
fi
LOG_FILE_DIR="/tmp/__${ME}"
function getExistingPortForward(){
listPortForwards | grep "$SERVICE" | grep -e ":$REMOTE_PORT" | head -n1
}
function coln(){
COL=$1
DELIM=${2:-' '}
awk -F"$DELIM" -v col="$COL" '{print $col}' | sort | uniq
}
function err(){
echo "$@" >&2; 
}
function isNumeric(){
INPUT=$*
case ${INPUT#[-+]} in
*[!0-9]* ) echo NO ;;
* ) echo YES ;;
esac
}
function getPid(){
local INFO=$(getExistingPortForward | awk '{print $2}')
if [ "$(isNumeric "$INFO")" == "YES" ]; then
echo "$INFO"
fi
}
function getLocalPort(){
local INFO=$(getExistingPortForward)
INFO=$(echo "$INFO" | awk -F ":$REMOTE_PORT" '{print $1}' | awk '{print $NF}')
if [ "$(isNumeric "$INFO")" == "YES" ]; then
echo "$INFO"
fi
}
function removePortForward(){
local PID=$(getPid)
if [ -z "$PID" ]
then
return;
fi
set -x
kill "$PID"
}
function portForward(){
local LOCAL_PORT=$1
local FILE=$2
kubectl port-forward "$SERVICE" "$LOCAL_PORT":"$REMOTE_PORT" $EXTRA_ARGS > $FILE 2>&1 &
}
function failIfFileContains(){
local FILE=$1
local SUBSTR=$2
local MSG=$3
if grep -iq "$SUBSTR" "$FILE"; then
cat "$FILE" >&2
err "Failed: $MSG"
err "Service:$SERVICE, $REMOTE_PORT $EXTRA_ARGS"
err
exit 1
fi
}
function getTargetLocalPort(){
local RESULT
if [[ $REMOTE_PORT == *":"* ]]; then
RESULT=$(echo $REMOTE_PORT | coln 1 ':')
REMOTE_PORT=$(echo $REMOTE_PORT | coln 2 ':')
else
RESULT=$(port_find_free_local_port)
fi
echo "$RESULT"
}
function createPortForward(){
local LOCAL_PORT=$(getTargetLocalPort)
local LOG_FILE="${LOG_FILE_DIR}/${LOCAL_PORT}_log.txt"
mkdir -p "$LOG_FILE_DIR"
rm -f "$LOG_FILE"
portForward "$LOCAL_PORT" "$LOG_FILE"
# wait for the log file to indicate success or failure
while true
do
sleep 0.5
failIfFileContains "$LOG_FILE" "address already" "Port $LOCAL_PORT already in use"
failIfFileContains "$LOG_FILE" "must be logged" "Please set some PCSK variables, and try again"
failIfFileContains "$LOG_FILE" "Failed" "Please review the above log, and try again"
failIfFileContains "$LOG_FILE" "Error" "Please review the above log, and try again"
if grep -q Forwarding "$LOG_FILE"; then
# port forward successful
echo "$LOCAL_PORT"
break
fi
done
}
function getOrCreatePortForward(){
local PORT=$(getLocalPort)
if [ -n "$PORT" ]
then
echo "$PORT"
exit;
fi
createPortForward
}
function listPortForwards(){
ps aux | grep kubectl | grep port-forward | sort
}
function removeAll(){
listPortForwards | awk '{print $2}' | xargs kill -9
rm -fr "$LOG_FILE_DIR"
}
function require3Args(){
if [ -z "$REMOTE_PORT" ]
then
show_help
fi
}
if [ "$OP" = "get" ]; then
require3Args
getLocalPort
elif [ "$OP" = "create" ]; then
require3Args
createPortForward
elif [ "$OP" = "require" ]; then
require3Args
getOrCreatePortForward
elif [ "$OP" = "remove" ]; then
require3Args
removePortForward
elif [ "$OP" = "list" ]; then
listPortForwards
elif [ "$OP" = "remove_all" ]; then
removeAll
else
show_help
fi

port_find_free_local_port

#!/usr/bin/env python
# https://stackoverflow.com/a/45690594/26510
import socket
from contextlib import closing
def find_free_port():
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
s.bind(('', 0))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
return s.getsockname()[1]
print(find_free_port())

相关内容

  • 没有找到相关文章

最新更新