最近不少云廠商都推出了云主機(jī)包年優(yōu)惠活動,雖然配置不高但好在有公網(wǎng) IP,恰好家里有一臺 Mac mini 在吃灰,花了三杯咖啡錢買了一年某云的云主機(jī)打算將其和家里的 Mac mini 組成 k8s 集群,方便平時學(xué)習(xí)和測試同時也能通過云主機(jī)的公網(wǎng) IP 訪問到 Mac mini 上運(yùn)行的服務(wù)。為了方便講解下面以 ecs
和 macmini
表示兩臺主機(jī),先來看看兩臺主機(jī)的網(wǎng)絡(luò)信息:
-
ecs
- eth0
172.19.174.87
- internet
47.102.84.170
- eth0
-
macmini
- eth0
172.16.14.253
- eth0
兩臺主機(jī)處于不同的網(wǎng)絡(luò)中,其中 ecs
主機(jī)具有公網(wǎng) IP,很顯然這兩臺主機(jī)并不滿足 k8s 的網(wǎng)絡(luò)要求,因此需要先使用 ZeroTier 組建一個虛擬局域網(wǎng)將兩臺主機(jī)連接起來。ZeroTier 是一個基于 P2P 的虛擬局域網(wǎng)軟件,理論上只要主機(jī)連接了互聯(lián)網(wǎng)就能與其它主機(jī)組成虛擬局域網(wǎng),并且組網(wǎng)的主機(jī)不需要有公網(wǎng) IP。使用 ZeroTier 組網(wǎng)非常簡單,再加上網(wǎng)上已經(jīng)有非常多關(guān)于 ZeroTier 的相關(guān)教程所以組網(wǎng)流程簡單帶過。
組建虛擬局域網(wǎng)
打開 ZeroTier 官網(wǎng) 注冊一個賬戶,可以用 Github 或者 Google 賬戶注冊,注冊完畢后進(jìn)入到個人頁面,點(diǎn)擊 Create A Network
按鈕創(chuàng)建一個網(wǎng)絡(luò),創(chuàng)建成功后下方會出現(xiàn)網(wǎng)絡(luò)的信息:
Network ID 是網(wǎng)絡(luò)的唯一標(biāo)識,主機(jī)可以通過這個標(biāo)識加入網(wǎng)絡(luò)。主機(jī)加入網(wǎng)絡(luò)后 ZeroTier 會在 Subnet 指定的網(wǎng)段內(nèi)給主機(jī)分配 IP 地址,如果網(wǎng)段與主機(jī)網(wǎng)絡(luò)的網(wǎng)段有沖突則需要點(diǎn)擊網(wǎng)絡(luò)進(jìn)入網(wǎng)絡(luò)管理頁面,在 IPv4 Auto-Assign
欄中修改網(wǎng)段。
網(wǎng)絡(luò)創(chuàng)建好之后就可以將主機(jī)加入到網(wǎng)絡(luò)中,加入網(wǎng)絡(luò)流程也非常簡單,在 下載頁面 下載對應(yīng)操作系統(tǒng)的客戶端安裝即可,Linux 系統(tǒng)可以使用以下命令一鍵安裝:
curl -s https://install.zerotier.com | sudo bash
ZeroTier 客戶端包含核心程序 zerotier-one
以及命令行管理工具 zerotier-cli
,安裝完畢后就可以使用管理工具將主機(jī)加入到創(chuàng)建好的虛擬網(wǎng)絡(luò)中:
$ zerotier-cli join <network-id>
200 join OK
將 <network-id>
替換為剛創(chuàng)建的網(wǎng)絡(luò) Network ID,返回 200 join OK
表示正常,接下來在需要組網(wǎng)的主機(jī)上重復(fù)以上步驟即可。
所有主機(jī)都操作完后回到 ZeroTier 控制臺,點(diǎn)擊剛創(chuàng)建的網(wǎng)絡(luò)進(jìn)入網(wǎng)絡(luò)管理頁面,下拉找到 Members
欄就會看到剛加入的主機(jī),選中主機(jī)前面的 Auth?
復(fù)選框授主機(jī)加入網(wǎng)絡(luò),稍等片刻后刷新頁面,在 Managed IPs
列可以看到 ZeroTier 為主機(jī)分配的 IP 地址,網(wǎng)絡(luò)中的主機(jī)可以通過這個 IP 地址與其它主機(jī)進(jìn)行通信。
在主機(jī)上執(zhí)行 zerotier-cli listnetworks
命令可以查看主機(jī)所加入的網(wǎng)絡(luò)信息:
$ zerotier-cli listnetworks
200 listnetworks <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>
200 listnetworks 233ccaac273421e8 berserk_taylor ea:55:d4:39:11:4a OK PRIVATE ztr4n75dop 192.168.195.183/24
為了更好的區(qū)分主機(jī)可以給主機(jī)設(shè)置 short-name
,這個名字并不只是起到裝飾作用,配合 ZeroTier 提供的 ZeroNSD 可以通過這個名字訪問指定的主機(jī),如同 k8s 集群中使用 .cluster.local
域名訪問 Service,具體操作流程這里就不展開了感興趣的同學(xué)可以看官方文檔。
從圖中可以看到 ecs
主機(jī)分配的 IP 地址為 192.168.195.79
,macmini
主機(jī)分配的 IP 地址為 192.168.195.183
,下面在 ecs
使用虛擬局域網(wǎng) IP 來 ping 一下 macmini
測試網(wǎng)絡(luò)連通性:
$ ping 192.168.195.79 -c 3
PING 192.168.195.79 (192.168.195.79) 56(84) bytes of data.
64 bytes from 192.168.195.79: icmp_seq=1 ttl=64 time=875 ms
64 bytes from 192.168.195.79: icmp_seq=2 ttl=64 time=5.67 ms
64 bytes from 192.168.195.79: icmp_seq=3 ttl=64 time=5.69 ms
--- 192.168.195.79 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 5.671/295.576/875.365/409.972 ms
到這里兩臺處于不同網(wǎng)絡(luò)的主機(jī)已經(jīng)可以通過 ZeroTier 網(wǎng)絡(luò)相互通信了,需要注意的是網(wǎng)絡(luò)連接質(zhì)量與主機(jī)所處的網(wǎng)絡(luò)有關(guān)。理想情況下主機(jī)之間是通過 P2P 直接通信的,但在建立通信前仍需向 ZeroTier 服務(wù)器請求對方主機(jī)的信息所以第一個 PING 的延遲會比較高。即使兩臺主機(jī)可以直接通信,所處的網(wǎng)絡(luò)有防火墻或者 NAT 網(wǎng)絡(luò)也會導(dǎo)致網(wǎng)絡(luò)連接質(zhì)量下降。云主機(jī)機(jī)房是在我所在的城市所以與家里的 Mac mini 連接質(zhì)量還不錯,但在離家不到五公里的公司訪問虛擬局域網(wǎng)內(nèi)的主機(jī)會嚴(yán)重丟包甚至無法連接,所以連接質(zhì)量還是與主機(jī)所在的網(wǎng)絡(luò)有關(guān)。
最壞的情況下主機(jī)之間無法直接通信,此時 ZeroTier 會通過中繼服務(wù)器轉(zhuǎn)發(fā)數(shù)據(jù)包,這種情況下網(wǎng)絡(luò)連接質(zhì)量會非常差,但可以通過搭建 moon 節(jié)點(diǎn)來優(yōu)化,具體流程可以參考 ZeroTier 官方文檔 這里就不展開討論。
主機(jī)加入網(wǎng)絡(luò)后 ZeroTier 會在主機(jī)上新增一個以 zt
開頭的虛擬網(wǎng)卡,也就是 zerotier-cli listnetworks
命令 <dev>
列的值,在我的主機(jī)上名字是 ztr4n75dop
,這塊網(wǎng)卡的名字非常重要,后面我們會用到它。
到這里組網(wǎng)就完成了,最后來匯總一下主機(jī)的網(wǎng)絡(luò)信息:
-
ecs
- eth0
172.19.174.87
- internet
47.102.84.170
- ztr4n75dop
192.168.195.79
- eth0
-
macmini
- eth0
172.16.14.253
- ztr4n75dop
192.168.195.183
- eth0
搭建 k8s 集群
解決了節(jié)點(diǎn)間的連通問題后就可以按照正常流程部署 k8s 集群了,唯一需要注意的是 cni 插件要使用 ZeroTier 創(chuàng)建的虛擬網(wǎng)卡來完成節(jié)點(diǎn)間的通信。下面使用輕量化 k8s 發(fā)行版 k3s 來搭建集群,由于云主機(jī)的配置比較低所以我 macmini
主機(jī)作為 master 節(jié)點(diǎn)。
k3s 為我們提供了幾種配置集群的方法,這里使用 命令行參數(shù) 方式配置 master 節(jié)點(diǎn):
以下命令用到的 IP 地址請按照實(shí)際情況替換
$ curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC=server sh -s - \
--flannel-iface=ztr4n75dop \
--flannel-backend=host-gw \
--tls-san=192.168.195.183 \
--tls-san=47.102.84.170 \
--node-name=macmini
解釋一下關(guān)鍵參數(shù):
-
--flannel-iface=ztr4n75dop
指定 flannel 使用 ZeroTier 虛擬網(wǎng)卡 -
--flannel-backend=host-gw
使用 flannel 使用性能更好的 host-gw 模式 -
--tls-san=192.168.195.183
將 master 節(jié)點(diǎn)的 ZeroTier IP 添加到 TLS SAN 中,以便后續(xù)通過這個 IP 訪問 k8s 集群 -
--tls-san=47.102.84.170
將云主機(jī)公網(wǎng) IP 添加到 TLS SAN 中,以便后續(xù)通過公網(wǎng) IP 訪問 k8s 集群
安裝命令執(zhí)行完畢使用 k3s kubectl get no
命令查看 master 節(jié)點(diǎn)狀態(tài):
$ k3s kubectl get no
NAME STATUS ROLES AGE VERSION
macmini Ready control-plane,master 1m v1.29.0+k3s1
master 節(jié)點(diǎn) Ready 后就可以配置 worker 節(jié)點(diǎn)了,在此之前需要在 master 節(jié)點(diǎn)上執(zhí)行 k3s token create
命令生成一個 bootstrap token。接著在 worker 節(jié)點(diǎn)上執(zhí)行以下命令:
$ curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC=agent sh -s - \
--server=https://192.168.195.183:6443 \
--token=<bootstrap token> \
--flannel-iface=ztr4n75dop \
--node-label=svccontroller.k3s.cattle.io/enablelb=true \
--node-external-ip=172.19.174.87 \
--node-name=ecs
worker 節(jié)點(diǎn)的安裝參數(shù)與 master 節(jié)點(diǎn)稍微有點(diǎn)區(qū)別:
-
--server=https://192.168.195.183:6443
指定 master 節(jié)點(diǎn)的地址 -
--node-label=svccontroller.k3s.cattle.io/enablelb=true
為 worker 節(jié)點(diǎn)添加svccontroller.k3s.cattle.io/enablelb
標(biāo)簽,擁有這個標(biāo)簽的節(jié)點(diǎn)會被 k3s 用作集群負(fù)載均衡的節(jié)點(diǎn),因?yàn)?worker 節(jié)點(diǎn)有公網(wǎng) IP 所以需要將這個標(biāo)簽添加到 worker 節(jié)點(diǎn)上 -
--node-external-ip=172.19.174.87
將 eth0 網(wǎng)卡的 IP 地址設(shè)置為節(jié)點(diǎn)的 external ip,k3s 會用這個 IP 地址作為 Service 的 LoadBalancer IP
需要注意的是 --node-label=svccontroller.k3s.cattle.io/enablelb=true
與 --node-external-ip=172.19.174.87
這兩個參數(shù)需要加到擁有公網(wǎng) IP 的節(jié)點(diǎn)上,無論這個節(jié)點(diǎn)是 worker 還是 master。
稍等片刻后回到 master 節(jié)點(diǎn)上確認(rèn)一下 worker 節(jié)點(diǎn)的狀態(tài):
$ k3s kubectl get no
NAME STATUS ROLES AGE VERSION
macmini Ready control-plane,master 10m v1.29.0+k3s1
ecs Ready <none> 30s v1.29.0+k3s1
到這里集群就搭建完畢了,通過 ZeroTier 虛擬網(wǎng)絡(luò)兩臺「相隔千里」的主機(jī)成功組成了一個 k8s 集群!
訪問集群
為了方便運(yùn)維可以將 APIServer 通過公網(wǎng) IP 暴露出來,這樣就可以通過公網(wǎng) IP 訪問集群了,在 master 節(jié)點(diǎn)創(chuàng)建 /root/apiserver-expose.yaml
文件:
# /root/apiserver-expose.yaml
apiVersion: v1
kind: Service
metadata:
name: apiserver-expose
namespace: default
spec:
ports:
- protocol: TCP
port: 8443 # 注意,不能使用 6443 端口,因?yàn)檫@個端口已經(jīng)被 APIServer 占用了
targetPort: 6443
name: apiserver
type: LoadBalancer
---
kind: Endpoints
apiVersion: v1
metadata:
name: apiserver-expose
namespace: default
subsets:
- addresses:
- ip: 192.168.195.183 # master 節(jié)點(diǎn)的 ZeroTier IP 地址
ports:
- port: 6443
name: apiserver
執(zhí)行 k3s kubectl apply -f /root/apiserver-expose.yaml
命令創(chuàng)建 Service,然后將 master 節(jié)點(diǎn)上 /etc/rancher/k3s/k3s.yaml
文件復(fù)制到本地 /root/.kube/config
,將里面 server
字段的 IP 替換為云主機(jī)的公網(wǎng) IP,注意端口要修改為 8443,最后在云主機(jī)管理后臺放行 8443 端口,然后就可以在本地使用 kubectl
訪問集群了。
ingress
k3s 自帶 traefik ingress controller,我們可以創(chuàng)建一個 whoami 應(yīng)用測試一下 ingress 是否正常工作:
# /root/whoami.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
namespace: default
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
name: whoami
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami
imagePullPolicy: IfNotPresent
restartPolicy: Always
nodeSelector:
kubernetes.io/hostname: macmini
---
apiVersion: v1
kind: Service
metadata:
name: whoami
namespace: default
spec:
selector:
app: whoami
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: whoami
namespace: default
spec:
rules:
- http:
paths:
- backend:
service:
name: whoami
port:
number: 80
pathType: Prefix
path: /whoami
我特意將 Pod 部署在 macmini
節(jié)點(diǎn),以便驗(yàn)證是否可以通過云主機(jī)的公網(wǎng) IP 訪問 macmini
上運(yùn)行的服務(wù)。將配置文件提交到 k8s 后就可以進(jìn)行測試了:
$ curl http://47.102.84.170/whoami
Hostname: whoami-564b668c57-rb689
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.9
IP: fe80::f47f:bfff:fedf:88f0
RemoteAddr: 10.42.0.8:39084
GET /whoami HTTP/1.1
Host: 47.102.84.170
User-Agent: curl/8.4.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.195.79
X-Forwarded-Host: whoami.tests.com
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-f4564c4f4-7swl5
X-Real-Ip: 192.168.195.79
可以看到 ingress 正常工作,但是從 whoami 輸出的 X-Real-Ip
頭可以看出 whoami 并沒有獲取到正確的客戶端 IP,通過 X-Forwarded-For
頭可以斷定根因是 traefik 沒有獲取到客戶端 IP 地址。有經(jīng)驗(yàn)的同學(xué)立馬就知道問題出在哪里:
$ k3s kubectl get svc/traefik -n kube-system -o=jsonpath='{.spec.externalTrafficPolicy}'
Cluster
問題就出在 traefik Service 的 externalTrafficPolicy
字段,關(guān)于這個字段的作用以及會如何影響客戶端 IP 大家可以查看 k8s 官方文檔 這里就不展開討論了,解決方案是將 externalTrafficPolicy
字段修改為 Local
。k3s 使用 Helm Controller 來管理 traefik 所以我們要在 /var/lib/rancher/k3s/server/manifests/traefik.yaml
文件進(jìn)行修改:
# /var/lib/rancher/k3s/server/manifests/traefik.yaml
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: traefik-crd
namespace: kube-system
spec:
chart: https://%{KUBERNETES_API}%/static/charts/traefik-crd-25.0.2+up25.0.0.tgz
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: traefik
namespace: kube-system
spec:
chart: https://%{KUBERNETES_API}%/static/charts/traefik-25.0.2+up25.0.0.tgz
set:
global.systemDefaultRegistry: ""
valuesContent: |-
...
service:
ipFamilyPolicy: "PreferDualStack"
# 修改 externalTrafficPolicy 字段
spec:
externalTrafficPolicy: Local
# 新增 nodeSelector 字段,將 traefik 部署在擁有公網(wǎng) IP 的節(jié)點(diǎn)上
nodeSelector:
svccontroller.k3s.cattle.io/enablelb: 'true'
這里對 traefik Chart 的 Values 進(jìn)行了兩處修改:
-
service.spec
將 Service 的externalTrafficPolicy
修改為Local
-
nodeSelector
將 traefik 部署在集群負(fù)載均衡節(jié)點(diǎn),因?yàn)?externalTrafficPolicy 字段設(shè)置為 Local 后外部流量進(jìn)入集群后不會進(jìn)行轉(zhuǎn)發(fā),云主機(jī)是外部流量的入口,如果云主機(jī)上沒有 traefik Pod 那么就無法處理請求了,而macmini
節(jié)點(diǎn)沒有公網(wǎng) IP 因此不會有外部流量流入,沒有必要部署 traefik。
修改完畢后 Helm Controller 會自動應(yīng)用更改,稍等片刻后再次訪問 whoami 應(yīng)用:文章來源:http://www.zghlxwxcb.cn/news/detail-816466.html
$ curl http://47.102.84.170/whoami
Hostname: whoami-564b668c57-rb689
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.9
IP: fe80::f47f:bfff:fedf:88f0
RemoteAddr: 10.42.1.5:53872
GET /whoami HTTP/1.1
Host: 47.102.84.170
User-Agent: curl/8.4.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 119.131.118.130
X-Forwarded-Host: 47.102.84.170
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-7c99f95995-dj6q7
X-Real-Ip: 119.131.118.130
可以看到修改后 traefik 獲取到了真實(shí)的客戶端 IP 地址并傳遞給了 whoami,至此就可以通過公網(wǎng) IP 訪問集群以及 macmini 上運(yùn)行的應(yīng)用了!文章來源地址http://www.zghlxwxcb.cn/news/detail-816466.html
到了這里,關(guān)于使用 zerotier 打通云上與本地網(wǎng)絡(luò)并搭建 k8s 集群的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!