Tailscale + k3s使用指北

0x00. 背景

之前一直使用docker-compose来进行服务的管理,但是它使用起来总归是没有k8s那么方便,我就在想,有没有一种轻量化的方案能同时管理云上云下的机器呢?答案是有的:Tailscale + K3s。
Tailscale能够保证在不需要云下机器具备独立公网IP的前提下完成组网,且不会像穿透方案那么复杂且不安全(机器打通的端口暴露在公网),而K3s则提供了轻量化的容器编排服务,很适合个人使用,本文对配置和使用过程做一个简单记录。

0x01. 安装

1. 前置准备

  • 各节点安装Tailscale并组网成功
  • 修改各个节点的hostname
  • 配置节点中的镜像仓库加速
1
2
3
4
5
6
7
8
mkdir -p /etc/rancher/k3s

cat >> /etc/rancher/k3s/registries.yaml <<EOF
mirrors:
aliyunmirror:
endpoint:
- "https://xxxx.mirror.aliyuncs.com"
EOF

2. 正式安装

Server节点初始化

主节点除了需要制定好Tailscale网卡对应的IP以外,还需要指定API Server额外的监听地址,通常是VPC IP或者是公网IP,用于各个网络环境下的客户端连接。

1
2
3
4
EXPOSE_IP=<API Server额外的监听地址>

# 这里指定了POD CIDR和 Service CIDR,可以不配置,仅需要保证和内网网段不冲突且互相不冲突即可
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC="server --node-ip $TAILSCALE_IP --advertise-address $TAILSCALE_IP --tls-san $EXPOSE_IP --node-external-ip $TAILSCALE_IP --flannel-iface tailscale0 --cluster-cidr 172.18.0.0/16 --service-cidr 172.16.0.0/16" sh -

执行结束后,可以拿到kubeconfig以及 Agent加入节点所需的Node Token。

1
2
3
4
5
# 默认kubeconfig
cat /etc/rancher/k3s/k3s.yaml

# 获取MASTER_NODE_TOKEN
cat /var/lib/rancher/k3s/server/node-token

Agent节点初始化

Agent节点加入集群时,配置好IP、K3s master节点地址 以及 上一步获取的Node Token即可完成初始化。

1
2
3
4
5
K3S_SERVER=https://<master节点 Tailscale网卡对应的IP>:6443
MASTER_NODE_TOKEN=<k3s master节点token>
TAILSCALE_IP=<Tailscale网卡对应的IP>

curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC="agent --server $K3S_SERVER --token $MASTER_NODE_TOKEN --node-ip $TAILSCALE_IP --node-external-ip $TAILSCALE_IP --flannel-iface tailscale0" sh -

3. 后续配置

Treafik Ingress优化

在默认情况下,K3s集群中安装的trafik endpoint仅有web/websecure两个,分别对应http/https服务。如果对外的Ingress需要暴露原始的TCP/UDP服务,则需要增加以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# kubectl edit deploy -n kube-system traefik -o yaml

apiVersion: apps/v1
kind: Deployment
...
spec:
template:
spec:
containers:
- args:
...
- --entrypoints.metrics.address=:9100/tcp
- --entrypoints.traefik.address=:9000/tcp
- --entrypoints.web.address=:8000/tcp
# 增加TCP/UDP Entrypoint
- --entrypoints.tcpep.address=:8099/tcp
- --entrypoints.udpep.address=:9001/udp
- --entrypoints.websecure.address=:8443/tcp
...
ports:
...
# 增加端口映射
- containerPort: 8099
name: tcpep
protocol: TCP
- containerPort: 9001
name: udpep
protocol: UDP

修改完毕Deployment中的traefik配置后,需要按照上述端口调整traefik的LoadBalancer Service。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# kubectl edit -n kube-system service/traefik

apiVersion: v1
kind: Service
...
spec:
ports:
// 其他端口配置
...
// 新增TCP/UDP对应端口配置
- name: tcpep
nodePort: 32518
port: 8099
protocol: TCP
targetPort: tcpep
- name: udpep
nodePort: 30047
port: 9001
protocol: UDP
targetPort: udpep

通过以上配置,我们就可以配合traefik的IngressRouteTCP/IngressRouteUDP对外暴露一些TCP或者UDP服务了, 比如:dns/redis等。

0x02. 其他

目前用下来K3s和K8s没有很明显的差异,主要在这种云上云下打通的场景下使用需要注意几个点:

  1. Traefik副本最好需要保证一个节点一个Pod,这样Ingress能够以最短路径路由到,否则数据完全走Tailscale的跨节点overlay网络延迟会比较严重
  2. 通过给节点打标签以及在负载上修改NodeSelector或者节点亲和性的方式,保证对公网服务的负载优先调度到公网节点上最大程度减少延迟
  3. 云上存储类型VPC内使用几乎是免费的(无流量和请求费用),和K3s本身的 local-path StorageClass混合使用的时候要注意Pod Volume不要跨节点调度
  4. 自建Tailscale Derper能够大幅降低节点间延迟,建议自建,使用Docker搭建即可

后续使用过程有坑再补充,先这么多。

0x03. 参考资料

K3s官网:https://www.rancher.cn/k3s/
Tailsacle安装:https://tailscale.com/download/linux
Traefik文档: https://doc.traefik.io/traefik/
HTTPS服务域名自动签名:https://www.frytea.com/technology/k8s/k3s-uses-letsencrypt-and-traefik-to-deploy-the-https/