跳到主要内容

端口转发服务脚本编写

这里将 Systemd 服务和 Bash 脚本相结合,创建一个方便管理 Kubernetes 端口转发的工具。下面的步骤会指导你如何实现这一目标。

创建 Systemd 服务

sudo vim /etc/systemd/system/kube-port-forward.service 
[Unit]
Description=Kube Port Forward Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/kube-port-forward.sh start
ExecStop=/usr/local/bin/kube-port-forward.sh stop
ExecReload=/usr/local/bin/kube-port-forward.sh restart
User=root

[Install]
WantedBy=multi-user.target

重新加载 systemd 以识别新的服务模板:

sudo systemctl daemon-reload

如果你未来可能会有很多需要端口转发的服务,创建一个通用的 systemd 服务模板可能会更加方便。下面是一个如何创建这样一个模板的例子:

例如,如果你运行以下命令启动服务:

sudo systemctl start kube-port-forward@my-service.my-namespace.8080.80.service

步骤 2: 创建管理脚本

1、使用你喜欢的文本编辑器,创建一个新的 Bash 脚本文件:

sudo vim /usr/local/bin/kube-port-forward.sh

2、在文件中添加以下内容:

#!/bin/bash

CONFIG_FILE="/etc/kube-port-forward.conf"
COMMAND="/usr/local/bin/kubectl"
LOG_FILE="/var/log/kube-port-forward.log"

log() {
local msg=$1
local level=$2
if [ -z "$level" ]; then
level="INFO"
fi
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $level: $msg" | tee -a $LOG_FILE
}

check_port_availability() {
local target_port=$1
if lsof -i :$target_port &> /dev/null; then
log "Port $target_port is already in use" "ERROR"
return 1
else
log "Port $target_port is available"
return 0
fi
}

find_process_using_port() {
local target_port=$1
local process_info
process_info=$(sudo lsof -i :$target_port)

if [ -z "$process_info" ]; then
log "No process is using port $target_port"
else
log "Port $target_port is used by the following process:"
echo "$process_info"
fi
}

start_service() {
if [ $# -eq 0 ]; then
log "Starting all services from config file"
while IFS= read -r line; do
set -- $line
namespace=$1
service=$2
target_port=$3
container_port=$4

if ! check_port_availability $target_port; then
continue
fi

$COMMAND -n $namespace port-forward svc/$service $target_port:$container_port &
local pid=$!
local pid_file="/var/run/k3s_kpf_${namespace}_${service}.pid"
echo $pid > "$pid_file"
log "Started $namespace/$service, PID: $pid, PID file: $pid_file"
done < "$CONFIG_FILE"
else
local namespace=$1
local service=$2
local target_port=$3
local container_port=$4

if ! check_port_availability $target_port; then
return 1
fi

$COMMAND -n $namespace port-forward svc/$service $target_port:$container_port &
local pid=$!
local pid_file="/var/run/k3s_kpf_${namespace}_${service}.pid"
echo $pid > "$pid_file"
log "Started $namespace/$service, PID: $pid, PID file: $pid_file"
fi
}

stop_service() {
local namespace=$1
local service=$2
local pid_file="/var/run/k3s_kpf_${namespace}_${service}.pid"
if [ -f "$pid_file" ]; then
kill $(cat "$pid_file")
rm -f "$pid_file"
log "Stopped $namespace/$service, removed PID file: $pid_file"
else
log "Service not running" "ERROR"
fi
}

status_service() {
local namespace=$1
local service=$2
if [ -f "/var/run/k3s_kpf_${namespace}_${service}.pid" ]; then
echo "Service is running"
else
echo "Service is not running"
fi
}

add_service() {
echo "$@" >> $CONFIG_FILE
log "Added service $2 to config file"
}

remove_service() {
local namespace=$1
local service=$2
sed -i "/^$namespace $service /d" $CONFIG_FILE
log "Removed service $service in namespace $namespace from config file"
}

list_services() {
cat $CONFIG_FILE
}

usage() {
echo "Usage: $0 {start|stop|restart|status|list|add|remove} [args]"
}

if [ $# -lt 1 ]; then
usage
exit 1
fi

case "$1" in
start)
if [ $# -eq 1 ]; then
start_service
elif [ $# -eq 5 ]; then
start_service $2 $3 $4 $5
else
echo "Usage: $0 start [<namespace> <service> <target_port> <container_port>]"
exit 1
fi
;;
stop)
if [ $# -ne 3 ]; then
echo "Usage: $0 stop <namespace> <service>"
exit 1
fi
stop_service $2 $3
;;
restart)
if [ $# -ne 5 ]; then
echo "Usage: $0 restart <namespace> <service> <target_port> <container_port>"
exit 1
fi
stop_service $2 $3
start_service $2 $3 $4 $5
;;
status)
if [ $# -ne 3 ]; then
echo "Usage: $0 status <namespace> <service>"
exit 1
fi
status_service $2 $3 $4
;;
list)
list_services
;;
find)
if [ $# -ne 2 ]; then
echo "Usage: $0 find <port>"
exit 1
fi
find_process_using_port $2
;;
add)
if [ $# -ne 5 ]; then
echo "Usage: $0 add <namespace> <service> <target_port> <container_port>"
exit 1
fi
add_service $2 $3 $4 $5
;;
remove)
if [ $# -ne 3 ]; then
echo "Usage: $0 remove <namespace> <service>"
exit 1
fi
remove_service $2 $3
;;
*)
usage
exit 1
;;
esac

exit 0

3、创建配置文件,用于存储已添加的服务:

sudo touch /etc/kube-port-forward.conf

4、使脚本可执行:

sudo chmod +x /usr/local/bin/kube-port-forward.sh

创建命令

sudo ln -s /usr/local/bin/kube-port-forward.sh /usr/local/bin/kpf

使用例子

以下是如何使用这个脚本的一些示例:

  1. 添加服务到配置文件:

    /usr/local/bin/kube-port-forward.sh add mynamespace myservice 8080 80

    这个命令会将一个名为 myservice 的服务,运行在 mynamespace 命名空间中,从容器的 80 端口转发到本地的 8080 端口,添加到配置文件 /etc/kube-port-forward.conf 中。

  2. 列出所有配置的服务:

    /usr/local/bin/kube-port-forward.sh list

    这个命令将显示 /etc/kube-port-forward.conf 文件中所有配置的服务。

  3. 启动服务:

    /usr/local/bin/kube-port-forward.sh start

    这个命令将根据 /etc/kube-port-forward.conf 文件中的配置启动所有服务。

    或者,你可以使用以下命令仅启动一个特定服务:

    /usr/local/bin/kube-port-forward.sh start mynamespace myservice 8080 80
  4. 停止服务:

    /usr/local/bin/kube-port-forward.sh stop mynamespace myservice 8080

    这个命令将停止转发到本地 8080 端口的服务。

  5. 查看服务状态:

    /usr/local/bin/kube-port-forward.sh status mynamespace myservice 8080

    这个命令将显示指定服务的状态(运行中或停止)。

  6. 重新启动服务:

    /usr/local/bin/kube-port-forward.sh restart mynamespace myservice 8080 80

    这个命令将停止并重新启动指定的服务。

  7. 从配置文件中移除服务:

    /usr/local/bin/kube-port-forward.sh remove myservice

    这个命令将从配置文件中移除名为 myservice 的服务。

以上命令假设你已经将脚本放在了 /usr/local/bin/kube-port-forward.sh 路径下,并且已经给予了执行权限。你可能需要根据你的系统和需求调整命令的路径和参数。在执行这些命令之前,请确保 Kubernetes 和 kubectl 已经正确配置,并且你有足够的权限执行这些操作。