- 本地 DevOps 服务器:安装并登录 Tailscale
- 实验环境 toolbox:安装二进制,在
tmux中启动tailscaled和端口转发 - 本地验证
- 上传 kubeconfig 到 DevOps 平台
一、本地 DevOps 服务器 执行官方脚本systemd安装
在本地服务器执行:
curl -fsSL https://tailscale.com/install.sh | sh
启动 Tailscale:
systemctl enable --now tailscaled
登录:
tailscale up --hostname=devops-one
如果输出登录地址,打开地址完成认证。
查看本机 Tailscale 地址:
tailscale ip -4
应为:
100.78.105.87
查看状态:
tailscale status
二、实验环境 toolbox
进入 toolbox:
kubectl exec -it toolbox -- sh
如果容器中还没有安装 Tailscale:
apt-get update
apt-get install -y curl tmux
curl -fsSL https://tailscale.com/install.sh | sh
创建持久化目录:
mkdir -p /data/tailscale
先找到Kubernetes API地址
kubectl config view --minify \
-o jsonpath='{.clusters[0].cluster.server}'
确认 Kubernetes API 在 toolbox 内可访问:.
curl -k https://kubernetes.default.svc/version
能返回 Kubernetes 版本信息即可。
三、在 tmux 中启动 tailscaled
创建新的 tmux 会话:
tmux new -s tailscale
进入 tmux 后,执行:
mkdir -p /data/tailscale
tailscaled \
--tun=userspace-networking \
--state=/data/tailscale/tailscaled.state \
--socket=/data/tailscale/tailscaled.sock \
>/data/tailscale/tailscaled.log 2>&1 &
等待启动:
sleep 2
确认 daemon 正常:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
status
四、登录实验环境的 Tailscale
仍然在 tmux 窗口内执行:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
up \
--hostname=toolbox-k8s-proxy
如果出现登录 URL,用浏览器打开完成认证。
查看 toolbox 的 Tailscale 地址:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
ip -4
当前地址是:
100.77.210.85
五、在 tmux 中启动 Kubernetes API 转发
toolbox 内部的 Kubernetes API 地址是:
https://kubernetes.default.svc:443
在同一个 tmux 窗口继续执行:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
serve \
--tcp 16443 \
tcp://kubernetes.default.svc:443
看到类似输出就表示成功:
tcp://100.77.210.85:16443
-> tcp://kubernetes.default.svc:443
这个命令保持前台运行即可,tmux 会话会维持它。
退出 tmux 但不停止隧道:
Ctrl+B
然后按 D
不要按 Ctrl+C,否则会停止端口转发。
查看会话:
tmux ls
重新进入:
tmux attach -t tailscale
六、本地服务器验证隧道
回到本地 DevOps 服务器执行:
tailscale ping 100.77.210.85
测试 Kubernetes API:
curl -k https://100.77.210.85:16443/version
预期返回:
{
"major": "1",
"minor": "33",
"gitVersion": "v1.33.4"
}
再测试 DevOps 后端容器:
docker exec dev-ops-one-backend-1 \
wget -qO- --no-check-certificate \
https://100.77.210.85:16443/version
如果也返回版本信息,说明后端容器可以通过隧道访问实验集群。
七、准备上传到平台的 kubeconfig
先从实验环境导出 kubeconfig:
kubectl config view --raw --minify > /data/tailscale/tunnel-kubeconfig
查看原始 API 地址:
grep "server:" /data/tailscale/tunnel-kubeconfig
将其中的:
server: https://kubernetes.default.svc
改为:
server: https://100.77.210.85:16443
可以使用 sed:
sed -i \
's#https://kubernetes.default.svc#https://100.77.210.85:16443#g' \
/data/tailscale/tunnel-kubeconfig
确认:
grep "server:" /data/tailscale/tunnel-kubeconfig
应显示:
server: https://100.77.210.85:16443
以下为完整内容,但是这里引用了文件
apiVersion: v1
clusters:
- cluster:
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
server: https://kubernetes.default.svc
name: in-cluster
contexts:
- context:
cluster: in-cluster
namespace: user-176-1514
user: sa
name: in-cluster
current-context: in-cluster
kind: Config
preferences: {}
users:
- name: sa
user:
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
遇到导入devops平台报错的问题执行以下操作拿到容器控制api的token
SA_DIR=/var/run/secrets/kubernetes.io/serviceaccount
CA_DATA="$(base64 -w0 "$SA_DIR/ca.crt")"
TOKEN="$(cat "$SA_DIR/token")"
cat > /data/tailscale/platform-kubeconfig.yaml <<EOF
apiVersion: v1
kind: Config
clusters:
- name: experiment
cluster:
server: https://100.77.210.85:16443
certificate-authority-data: ${CA_DATA}
contexts:
- name: experiment
context:
cluster: experiment
user: toolbox-service-account
current-context: experiment
users:
- name: toolbox-service-account
user:
token: ${TOKEN}
EOF
chmod 600 /data/tailscale/platform-kubeconfig.yaml
itops导入显示以下报错
request to https://100.77.210.85:16443/api/v1/nodes failed, reason: Hostname/IP does not match certificate's altnames: IP: 100.77.210.85 is not in the cert's list: 10.200.0.1, 192.168.2.101, 192.168.2.100, 192.168.2.102, 192.168.2.103
使用不校验ca证书的配置:
- cluster: 里面
加入 insecure-skip-tls-verify: true
删除 certificate-authority-data
apiVersion: v1
kind: Config
clusters:
- name: experiment
cluster:
insecure-skip-tls-verify: true
server: https://100.77.210.85:16443
contexts:
- name: experiment
context:
cluster: experiment
user: toolbox-service-account
current-context: experiment
users:
- name: toolbox-service-account
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjhhQmxPd0hPb2wzUW9QYkpvaDVfbzBFRW10V2UxNnpQcnlDbWkwSm1URkEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxODIyMTkwNDczLCJpYXQiOjE3OTA2NTQ0NzMsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiMWVjMjk1ODYtZjlmNS00MTY3LWFlMGItZDU4OTUxZGNmODI3Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJ1c2VyLTE3Ni0xNTE0Iiwibm9kZSI6eyJuYW1lIjoiazhzLXcyLTAwNSIsInVpZCI6ImUyNWIyZjY4LWQ1MDYtNDFmZS04NWZlLWRlMDc2YzNkZmI3OCJ9LCJwb2QiOnsibmFtZSI6InRvb2xib3giLCJ1aWQiOiIwNjI3NjRmNi02N2E4LTQ0YzgtODNjMC1iOTNmNDMyMGE2ZTUifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6InN0dWRlbnQiLCJ1aWQiOiJiMzYzZmU1OC1hNzc2LTQzN2EtODE5MS04OTZiMDA2MmQ4NzYifSwid2FybmFmdGVyIjoxNzkwNjU4MDgwfSwibmJmIjoxNzkwNjU0NDczLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6dXNlci0xNzYtMTUxNDpzdHVkZW50In0.EzRxUus0tDzbNAOdilgY71Cel1DquWQIbljKXNX0YDDgBaJZNpPCUhUZZcnPmxMsiqnlSpQte5rIwSi0sp14hMYYlShm16bqU9m_ZANtp5Rr8lqcGQD8HVL4IeRxU3-XcxHIM3iB4PccHsTn6DHLAhnktiBfc56A51s7DzD1OTC56jolRcAjdwmkltX_MTXWNJFNEMf7CDVQlJYY8_83wbkm7vn720vghm3S4bBmRRmnFOYKwnWHuHxH5HIkZeCDSukvwc3Vurjp-stvUJULaAFWImbuY_dv1UvBh5m0ZOMHzVFuH9XOh39OVU64d4LXBC8P07oFQUdW-YKxfq-SfA
八、在 DevOps 平台添加集群
在前端打开:
http://本地服务器地址:18081
进入:
集群管理 -> 添加集群
上传:
/data/tailscale/tunnel-kubeconfig
平台中最终使用的地址是:
server: https://100.77.210.85:16443
不要使用:
server: https://127.0.0.1:16443
也不要使用:
server: https://kubernetes.default.svc
集群内配置nodeport实现隧道内机器访问+内网穿透
保留两个 Service:
# StatefulSet 内部使用,提供稳定 Pod DNS nonoservice
# 外部访问使用 nodeport
- 确认服务端能访问 NodePort
在 toolbox-k8s-proxy 上执行:
curl http://192.168.2.104:30081
如果返回:
Pod: stateful-demo-0
说明后端可达。
- 启动 Tailscale Serve
tailscale \
--socket=/data/tailscale/tailscaled.sock \
serve \
--bg \
http://192.168.2.104:30081
第一次使用时,如果出现:
Serve is not enabled on your tailnet
打开它提示的授权链接,授权后重新执行上面的命令。
- 查看状态
必须继续使用自定义 socket:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
serve status
应看到类似:
https://toolbox-k8s-proxy.tail46632a.ts.net/
|-- proxy http://192.168.2.104:30081
- 隧道内机器访问
在 Windows 本机或其他已加入同一个 Tailnet 的设备上访问:
https://toolbox-k8s-proxy.tail46632a.ts.net/
或者:
curl https://toolbox-k8s-proxy.tail46632a.ts.net/
如果本机配置了 HTTP/HTTPS 代理,需要把以下域名加入直连:
*.ts.net
否则请求可能被本地代理拦截。
- 验证确实访问了多个 Pod
连续请求:
for i in $(seq 1 10); do
curl -sk https://toolbox-k8s-proxy.tail46632a.ts.net/
echo
done
页面可能显示不同的:
Pod: stateful-demo-0
Pod: stateful-demo-1
Pod: stateful-demo-2
这说明 Service 正在做负载转发。
实现任意人公网访问
Tailscale Serve只能让同一个 Tailnet 内的设备访问。公网匿名访问需要使用:
Tailscale Funnel
在 toolbox-k8s-proxy 上执行:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
funnel \
--bg \
http://192.168.2.104:30081
查看状态:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
funnel \
status
如果第一次提示未启用,打开它给出的授权链接。启用后,公网用户可以访问类似:
https://toolbox-k8s-proxy.tail46632a.ts.net/
区别是:
Serve:只有 Tailnet 成员可以访问
Funnel:任意公网用户可以访问
唯一需要注意的是:如果 192.168.2.104 这台节点故障,Funnel 后端入口会失效。实验环境可以保持这样;生产环境再考虑用 HAProxy、Ingress 或负载均衡器代理多个节点。
查看当前 Serve 配置
tailscale \
--socket=/data/tailscale/tailscaled.sock \
serve \
status
查看当前公网 Funnel 配置:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
funnel \
status
重启后的恢复方式
由于 toolbox 没有 systemd,容器重启后需要重新启动 tmux 和 tailscaled:
tmux new -s tailscale
然后重新执行:
tailscaled \
--tun=userspace-networking \
--state=/data/tailscale/tailscaled.state \
--socket=/data/tailscale/tailscaled.sock \
>/data/tailscale/tailscaled.log 2>&1 &
sleep 2
tailscale \
--socket=/data/tailscale/tailscaled.sock \
serve \
--tcp 16443 \
tcp://kubernetes.default.svc:443
因为登录状态保存在:
/data/tailscale/tailscaled.state
通常不需要再次执行 tailscale up。
需要特别确认 /data 是持久化目录。否则 toolbox 容器删除后,Tailscale 登录状态也会丢失。
tailscale排查命令
卸载systemd安装的tailscale
systemctl disable --now tailscaled
dnf remove tailscale
Toolbox 手动运行模式
先定义 socket,后续命令更短:
TS_SOCKET=/data/tailscale/tailscaled.sock
检查进程、tmux 和 socket:
pgrep -af tailscaled
tmux ls
test -S "$TS_SOCKET" && echo "socket OK" || echo "socket missing"
检查 Tailscale 状态和 IP:
tailscale --socket="$TS_SOCKET" status
tailscale --socket="$TS_SOCKET" ip -4
tailscale --socket="$TS_SOCKET" version
检查网络条件:
tailscale --socket="$TS_SOCKET" netcheck
tailscale --socket="$TS_SOCKET" ping 100.78.105.87
netcheck 重点看:
UDP: true
Nearest DERP
MappingVariesByDestIP
通过 DERP 中继也能正常使用,只是延迟更高;不一定必须建立 direct 连接。
检查端口转发:
tailscale --socket="$TS_SOCKET" serve status
应包含:
tcp://100.77.210.85:16443
-> tcp://kubernetes.default.svc:443
检查 toolbox 到 Kubernetes API:
curl -k --connect-timeout 5 \
https://kubernetes.default.svc/version
查看日志:
tail -n 100 /data/tailscale/tailscaled.log
tail -f /data/tailscale/tailscaled.log
查看 tmux 中两个窗口:
tmux attach -t tailscale
切换窗口:
Ctrl+B,然后按 N
退出但保持运行:
Ctrl+B,然后按 D
手动启动 daemon:
tailscaled \
--tun=userspace-networking \
--state=/data/tailscale/tailscaled.state \
--socket=/data/tailscale/tailscaled.sock
另一个 tmux 窗口启动转发:
tailscale \
--socket=/data/tailscale/tailscaled.sock \
serve \
--tcp 16443 \
tcp://kubernetes.default.svc:443
停止手动进程:
pkill -x tailscaled
注意:userspace 模式通常不会出现 tailscale0 网卡,而且不要在 toolbox 内使用普通 curl 回连自己的 100.77.210.85,应从另一台 Tailscale 设备测试。
systemd 托管模式
检查服务:
systemctl status tailscaled --no-pager
systemctl is-active tailscaled
systemctl is-enabled tailscaled
启动、停止、重启:
systemctl start tailscaled
systemctl stop tailscaled
systemctl restart tailscaled
systemctl enable --now tailscaled
查看日志:
journalctl -u tailscaled -n 100 --no-pager
journalctl -u tailscaled -f
journalctl -u tailscaled --since "30 minutes ago"
检查默认 socket:
ls -l /var/run/tailscale/tailscaled.sock
tailscale status
tailscale ip -4
tailscale netcheck
tailscale serve status
查看 systemd 启动参数:
systemctl cat tailscaled
systemctl show tailscaled \
-p ActiveState \
-p SubState \
-p MainPID \
-p ExecMainStatus