多云环境下部署 k3s 集群
最近在玩k3s,刚好手上有三台云服务器(白嫖的一年亚马逊,双11买的腾讯云,朋友的阿里云),尝试跨云厂商搭建k3s集群玩玩
一.基础配置
服务器信息
系统 | 公网IP | 内网IP | 服务器配置 | 角色 |
---|---|---|---|---|
Centos 8.2 | 82.157.xx.xx (tengxun) | 10.0.24.2 | 2C/4G/8M | Master |
release 7.9 | 47.106.xx.xx(aliyun) | 172.29.221.251 | 2C/4G/1M | node |
RHEL 8.5 | 52.199.xx.xx(aws) | 172.31.4.9 | 1C/1G/- | node |
开放端口
Master节点端口
协议 | 端口 | 描述 |
---|---|---|
TCP | 6443 | Kubernetes API Server |
TCP | 10250 | Kubelet metrics |
UDP | 8472 | 仅对 Flannel VXLAN 需要 |
UDP | 51820 | Flannel 后端使用Wireguard 的端口 |
TCP | 2379-2380 | 只有嵌入式 etcd 高可用才需要 |
TCP | 30000-32767 | 节点暴露服务端口 |
Agent节点端口
协议 | 端口 | 描述 |
---|---|---|
UDP | 8472 | 仅对 Flannel VXLAN 需要 |
UDP | 51820 | Flannel 后端使用Wireguard 的端口 |
TCP | 10250 | Kubelet metrics |
TCP | 30000-32767 | 节点暴露服务端口 |
二.搭建K3s集群
Master节点安装
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
运行此安装后:
- K3s 服务将被配置为在节点重启后或进程崩溃或被杀死时自动重启。
- 将安装其他实用程序,包括
kubectl
、crictl
、ctr
、k3s-killall.sh
和k3s-uninstall.sh
。 - 将kubeconfig文件写入到
/etc/rancher/k3s/k3s.yaml
,由 K3s 安装的 kubectl 将自动使用该文件
Agent节点安装
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://myserver:6443 K3S_TOKEN=mynodetoken sh -
设置
K3S_URL
参数会使 K3s 以 worker 模式运行。
K3s agent 将在所提供的 URL 上向监听的 K3s 服务器注册。
K3S_TOKEN
使用的值存储在你的服务器节点上的/var/lib/rancher/k3s/server/node-token
路径下。
注意
每台计算机必须具有唯一的主机名。如果您的计算机没有唯一的主机名,请传递
K3S_NODE_NAME
环境变量,并为每个节点提供一个有效且唯一的主机名。
离线安装
公司内网环境无法访问互联网,需要离线安装,参考 K3S 安装使用教程
内网不互通问题
k3s集群搭建成功后,各节点上Pod的IP无法互通
产生的原因是不在同一内网且机器的公网IP并未显示的绑定在机器网卡上(典型的云主机),而通常情况下我们都是在同一内网搭建k8s集群,因此很少会遇到
可以看一下 node 的 annotations
:
kubectl get node/aws -o yaml
apiVersion: v1
kind: Node
metadata:
annotations:
flannel.alpha.coreos.com/backend-data: '{"VNI":1,"VtepMAC":"2a:42:f2:71:0c:ba"}'
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: "true"
flannel.alpha.coreos.com/public-ip: 172.31.4.9 #此处Ip为内网IP
以上看到
flannel
给节点打的注解中的节点 IP 是内网 IP。要想让 flannel 使用公网 IP 进行通信,需要额外添加一个注解
public-ip-overwrite
, 用来覆盖节点的公共 IP
kubectl annotate node/tengxun flannel.alpha.coreos.com/public-ip-overwrite=82.157.xx.xx
kubectl annotate node/aliyun flannel.alpha.coreos.com/public-ip-overwrite=47.106.xx.xx
kubectl annotate node/aws flannel.alpha.coreos.com/public-ip-overwrite=52.199.xx.xx
添加
annotate
后需要重启 flannel ,由于flannel是内置k3s里,需要重启k3sServer节点和 Agent节点都需要重启,重启完成后,flannel 的
public-ip
就会被修改为公网 IP
kubectl get node -o yaml|grep public
flannel.alpha.coreos.com/public-ip: 47.106.xx.xx
flannel.alpha.coreos.com/public-ip-overwrite: 47.106.xx.xx
flannel.alpha.coreos.com/public-ip: 82.157.xx.xx
flannel.alpha.coreos.com/public-ip-overwrite: 82.157.xx.xx
flannel.alpha.coreos.com/public-ip: 52.199.xx.xx
flannel.alpha.coreos.com/public-ip-overwrite: 52.199.xx.xx
此时再ping各节点上的Pod 就通了
metrics-server 问题
metrics-server
无法获取指标,是由于kubelet-preferred-address-types
值首选是InternalIP,而云服务器的InternalIP为内网IP,不同云厂商的内网IP段不同,无法通讯
kubectl get deploy/metrics-server -o yaml -n kube-system|grep "kubelet-preferred-address-types"
# kubelet首选地址类型是 InternalIP ,其次才是 公网 IP ,最后是主机名
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
需要修改
metrics-server
的 manifests,使用以下命令在线编辑metrics-server
的 manifests:
kubectl edit deploy metrics-server -n kube-system
找到 kubelet-preferred-address-types 将ExternalIP作为首选:
- --kubelet-preferred-address-types=ExternalIP,InternalIP,Hostname
修改后,会在Agent节点上生成新的metrics-server容器,再次查看指标正常
kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
aws 18m 1% 576Mi 59%
duandian 73m 3% 2284Mi 60%
tengxun 133m 6% 2638Mi 67%
三.使用 WireGuard组网
Flannel 的默认后端是 VXLAN,无加密,要想加密通信,可以使用WireGuard进行组网。
WireGuard是Linux 内核的轻量级 VPN 协议,可以在不同的主机中建立点对点通信隧道,不过WireGuard对内核版本要求极高,要求内核5.x 版本以上,再运生产环境不建议直接升级到高版本内核。
1.所有节点安装 Wireguard
具体安装参考 WireGuard 安装
2.配置启动Wireguard (可选)
详细配置参考: WireGuard 的使用与配置详解
2.1.准备秘钥
生成私钥: wg genkey > example.key
生成公钥 : wg pubkey < example.key > example.key.pub
IP | 公钥 | 私钥 |
---|---|---|
82.157.xx.xx | aH/GnX3kTbmieairpLYtZMIdTfom0C9NWETSSQyCb0c= | SO6KCUZ+EbKSMFrcNEVssqPYy8+lbl1+JAK2Bw2n4Uc= |
47.106.xx.xx(aliyun) | Lnr5n2bh4P2R3h9xUFKDNtPqBYEv7JBYnGG8UXykwTU= | MHf4c2qvDgQ3BLxIr412VGGY8rD18vM2LVrKnj9gm34= |
52.199.xx.xx(aws) | 9ys4TqyO3R2nOdoRSba+wLFquJI+aeqmMYfBg0Xo4CU= | oMdhm2x+c6K0CKOm3p40Jkkq1YSsHs6hrkJxvm/g/0Q= |
2.2.创建配置文件
每台节点都需要把其他需要通信节点加入Peer中,有多少台写多少Peer
Server节点
在server节点(82.157.xxx.xxx)
vi /etc/wireguard/wg0.conf
之后wireguard会根据该文件名自动生成wg0虚拟网卡
[Interface]
Address = 10.10.10.1
ListenPort = 51820
PrivateKey = SO6KCUZ+EbKSMFrcNEVssqPYy8+lbl1+JAK2Bw2n4Uc=
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
Endpoint = 47.106.xx.xx:51820
PublicKey = Lnr5n2bh4P2R3h9xUFKDNtPqBYEv7JBYnGG8UXykwTU=
AllowedIPs = 10.10.10.2
[Peer]
Endpoint = 52.199.xx.xx:51820
PublicKey = 9ys4TqyO3R2nOdoRSba+wLFquJI+aeqmMYfBg0Xo4CU=
AllowedIPs = 10.10.10.3
Client1节点
在 Clinet1 47.106.xxx.xxx
vi /etc/wireguard/wg0.conf
[Interface]
Address = 10.10.10.2
ListenPort = 51820
PrivateKey = MHf4c2qvDgQ3BLxIr412VGGY8rD18vM2LVrKnj9gm34=
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
Endpoint = 82.157.xx.xx:51820
PublicKey = aH/GnX3kTbmieairpLYtZMIdTfom0C9NWETSSQyCb0c=
AllowedIPs = 10.10.10.1
[Peer]
Endpoint = 52.199.xx.xx:51820
PublicKey = 9ys4TqyO3R2nOdoRSba+wLFquJI+aeqmMYfBg0Xo4CU=
AllowedIPs = 10.10.10.3
Client2节点
在 Clinet2 52.199.xxx.xxx
vi /etc/wireguard/wg0.conf
[Interface]
Address = 10.10.10.3
ListenPort = 51820
PrivateKey = oMdhm2x+c6K0CKOm3p40Jkkq1YSsHs6hrkJxvm/g/0Q=
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
Endpoint = 82.157.xx.xx:51820
PublicKey = aH/GnX3kTbmieairpLYtZMIdTfom0C9NWETSSQyCb0c=
AllowedIPs = 10.10.10.1
[Peer]
Endpoint = 47.106.xx.xx:51820
PublicKey = Lnr5n2bh4P2R3h9xUFKDNtPqBYEv7JBYnGG8UXykwTU=
AllowedIPs = 10.10.10.2
配置说明
Interface
: 为本机的配置项
-
Address
: 是分配给 本机的 虚拟IP -
ListenPort
: 是主机之间通讯使用的端口,是 UDP 协议的
Peer
: 是属于需要通信的对等节的信息,有多少需要通信的主机,就添加多少个 Peer
小节
EndPoint
: 是与本机通信的后端节点的公网IP与WireGuard
监听的UDP
端口,这个IP
不一定是公网AllowedIPs
: 允许该对等节点(peer)发送过来的 VPN 流量中的源地址范围,同时发往该地址范围的流量转发到 Endpoint 填写的公网IP上
注意:
如果你的机器通过内网也能通信,直接用内网
IP
也可以,当然要注意这个IP
需要所有加入局域网的主机都能通信才行。
2.3.启动wireguard
快速启动, 所有节点上执行
wg-quick up wg0
设置开机自启
systemctl enable wg-quick@wg0
3.K3s安装时指定wireguard网络
Master节点
启动方式一:
需要事先配置好 wireguard ,并启动 wg0网口
INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh --node-label machine=tengxun --node-external-ip 82.157.xx.xx --advertise-address 82.157.xx.xx --node-ip 10.10.10.1 --flannel-iface wg0 --kube-proxy-arg "proxy-mode=ipvs"
启动方式二:
无须配置wireguard,由 flannel自行创建配置,会生成 flannel.1 网口
INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh --node-label machine=tengxun --node-external-ip 82.157.xx.xx --advertise-address 82.157.xx.xx --flannel-backend wireguard --kube-proxy-arg "proxy-mode=ipvs"
**参数作用: **
--node-label machine=tengxun
为节点打上标签,这样在创建部署时,就可以根据业务需要,调整Pod或其它资源分布的节点。--node-external-ip 82.157.xx.xx
为节点设置外部IP,阿里云VPC的外网IP并未直接绑定到虚拟机网卡上,所以我要设置这个参数,避免k3s组件在设置loadbalance时,将内网IP当作公网IP使用。- `–advertise-address 82.157.xx.xx 用于设置kubectl工具以及子节点进行通讯使用的地址,可以是IP,也可以是域名,在创建apiserver证书时会将此设置到有效域中。
--node-ip 10.10.10.1
如果不设置这个参数,那么第一张网卡设备上的IP就会被选中,所以这个IP常是内网IP。这里自行组建了虚拟局域网,所以需要指定虚拟局域网的IP(也就是WireGuard的IP),这样流量就会通过WireGuard加密传输。--flannel-iface wg0
wg0是WireGuard创建的网卡设备,我需要使用虚拟局域网来进行节点间的通信,所以这里需要指定为wg0。--flannel-backend wireguard
flannel网络插件使用wireguard,并自行创建管理wireguard--kube-proxy-arg "proxy-mode=ipvs"
使用IPVS模式进行流量转发
Agent节点
Client1
INSTALL_K3S_SKIP_DOWNLOAD=true K3S_URL=https://10.10.10.1:6443 K3S_TOKEN=K1052e55520438cfcd35128d0e8dd60fdb19d5cbaaf90d3b2783e36841ca223b2fb::server:44a572e892392c5d718b9636e2a85e67 ./install.sh --node-label machine=aliyun --node-external-ip 47.106.xx.xx --node-ip 10.10.10.2 --flannel-iface wg0
Client2
INSTALL_K3S_SKIP_DOWNLOAD=true K3S_URL=https://10.10.10.1:6443 K3S_TOKEN=K1052e55520438cfcd35128d0e8dd60fdb19d5cbaaf90d3b2783e36841ca223b2fb::server:44a572e892392c5d718b9636e2a85e67 ./install.sh --node-label machine=aws --node-external-ip 52.199.xx.xx --node-ip 10.10.10.3 --flannel-iface wg0
参数作用:
K3S_Token
根据文档说明,去/var/lib/rancher/k3s/server/node-token
获取即可。K3S_URL
需要设置主控的通信地址端口,端口默认是6443,IP地址就是虚拟网域的IP,这样流量就会通过WireGuard加密传输。