來(lái)源: DevOpSec公眾號(hào)
作者: DevOpSec
背景
自建k8s而非云環(huán)境,組件MySQL類(lèi)部署在虛機(jī)里也即集群外,業(yè)務(wù)服務(wù)部署在k8s集群內(nèi)。
需求:集群內(nèi)、集群外,服務(wù)和組件相互間通過(guò)負(fù)載均衡、高可用的形式連通。
此需求拆解兩個(gè)問(wèn)題進(jìn)行解決,接著往下看。
集群內(nèi):k8s集群
集群外:k8s集群外的應(yīng)用部署在虛擬機(jī)或物理機(jī)環(huán)境
網(wǎng)絡(luò)環(huán)境
局域網(wǎng):192.168.0.0/16
集群外
虛擬機(jī)網(wǎng)絡(luò):192.168.0.0/16
mysql網(wǎng)絡(luò):192.168.0.0/16
Nginx網(wǎng)絡(luò):192.168.0.0/16
集群內(nèi)(k8s集群)
master網(wǎng)絡(luò):192.168.0.0/16
node網(wǎng)絡(luò):192.168.0.0/16
pod網(wǎng)絡(luò):10.234.0.0/18
SVC網(wǎng)絡(luò):10.234.64.0/18
業(yè)務(wù)架構(gòu)圖
上圖中存在的兩個(gè)問(wèn)題
問(wèn)題1. 集群外訪問(wèn)集群內(nèi)pod和svc的網(wǎng)絡(luò)不通?
不通的原因:集群外的主機(jī)并不知道svc和pod的網(wǎng)絡(luò),在路由器上沒(méi)有對(duì)應(yīng)svc和pod ip的路由。
cni網(wǎng)絡(luò)插件的實(shí)現(xiàn)是會(huì)按node分配網(wǎng)段,通過(guò)在路由器上增加不同node上的pod ip段和svc ip段路由給多個(gè)node的路由即可實(shí)現(xiàn)集群外部和內(nèi)部svc和pod的互通。
缺點(diǎn)是當(dāng)節(jié)點(diǎn)或者節(jié)點(diǎn)上的ip段有變化需要修改路由器上的路由策略,需要人工干預(yù)或者寫(xiě)個(gè)程序?qū)崿F(xiàn)成本也不低。
可能有人說(shuō)可以用nodePort的形式把服務(wù)暴露給nginx,但nodePort的方式不便于運(yùn)維,
缺點(diǎn)有兩個(gè):
a、需要維護(hù)模塊和端口的映射不通模塊映射端口不能重復(fù)
b、集群外訪問(wèn)集群內(nèi)部需要通過(guò)node的ip加端口訪問(wèn),node可能隨時(shí)下線
問(wèn)題2. 集群內(nèi)的pod訪問(wèn)集群外的mysql集群沒(méi)有負(fù)載均衡和健康檢查
針對(duì)問(wèn)題2可以通過(guò)集群外部的硬件負(fù)載均衡設(shè)備或者自建的軟負(fù)載均衡比如LVS、HAproxy或nginx等解決
缺點(diǎn):硬件LB成本高,軟LB在集群外維護(hù)成本高
也有人說(shuō)可以已通過(guò)DNS解析多個(gè)數(shù)據(jù)庫(kù)的ip A記錄,通過(guò)域名解析來(lái)實(shí)現(xiàn)LB的功能,業(yè)務(wù)配置域名
缺點(diǎn):一般DNS服務(wù)沒(méi)有健康檢查的功能,沒(méi)辦法實(shí)現(xiàn)故障db的自動(dòng)剔除。
解決方案
問(wèn)題1. 集群外訪問(wèn)集群內(nèi)pod和svc的網(wǎng)絡(luò)不通?
自建k8s,有沒(méi)有類(lèi)似于云廠商一樣提供LB一樣提供和node機(jī)器同一個(gè)網(wǎng)段的ExternalIP解決方案?
有,通過(guò)開(kāi)源metalLB、OpenELB或者pureLB提供LoadBalancer的能力。
在生產(chǎn)環(huán)境中使用的calico VXLAN 模式,考慮到簡(jiǎn)單易用性我們使用LB基于layer2模式,也即LB的EXTERNAL-IP和node的ip同網(wǎng)段。
通過(guò)下面表格綜合對(duì)比一下,metallb出道最早,迭代快,開(kāi)發(fā)者多,且實(shí)測(cè)對(duì)externalTrafficPolicy: Local 支持。
綜合選擇metallb的layer2模式作為生產(chǎn)環(huán)境負(fù)載均衡。
部署MetalLB 使用 layer2模式
- 1. 準(zhǔn)備工作
a. 確保防火墻對(duì)7472、7946端口開(kāi)放,否則可能造成meltallb腦裂。 7472是 MetalLB 控制平面的 API 端口。MetalLB 提供了一個(gè) REST API,用于管理和配置負(fù)載均衡服務(wù)。 7946端口是 MetalLB 使用的控制平面(Control nPlane)通信端口。它用于集群中的 MetalLB Speaker 之間進(jìn)行通信,以便在整個(gè)集群中協(xié)調(diào)負(fù)載均衡服務(wù)的配置和狀態(tài)。
b. 開(kāi)始strict ARP模式
kubectl edit configmap -n kube-system kube-proxy
設(shè)置
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
重啟 kube-proxy
kubectl -n kube-system rollout ds kube-proxy
注意:如果是kubespray部署的k8s集群,需要修改kubespray 配置
vim inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
修改
kube_proxy_strict_arp: true
- 1. 部署MetalLB
kubectl Apply -f https://raw.Githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml
- 1. 配置ip池 注意:ip 地址池和node網(wǎng)絡(luò)同一個(gè)網(wǎng)段,且ip地址池的ip沒(méi)有其他主機(jī)使用
cat ippools.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.200.0/24
- 192.168.201.1-192.168.201.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-advertisement
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
加LoadBlancer后,nginx通過(guò)同網(wǎng)段的ExternalIP就能聯(lián)通業(yè)務(wù)pod。
業(yè)務(wù)pod使用readiness probe 和 liveness probe檢測(cè)pod里的服務(wù)是否正常,如果服務(wù)不正常k8s控制平面通知kube-proxy 從svc中剔除或更新endpoints,間接實(shí)現(xiàn)了svc對(duì)業(yè)務(wù)pod健康檢查的功能。
網(wǎng)絡(luò)架構(gòu)圖如下:
解決了問(wèn)題1,來(lái)看一看問(wèn)題2怎么解。
問(wèn)題2. 集群內(nèi)的pod訪問(wèn)集群外的mysql集群沒(méi)有負(fù)載均衡和健康檢查
集群內(nèi)部訪問(wèn)集群外部組件可以在集群內(nèi)部部署hapoxy或者nginx做反向代理,haproxy和 nginx 支持對(duì)代理的四層和七層服務(wù)做健康檢查和負(fù)載均衡。
這樣我們可以在集群內(nèi)部針對(duì)集群外部組件靈活高效的創(chuàng)建帶檢查的負(fù)載均衡器,負(fù)載均衡器是無(wú)狀態(tài)的可以創(chuàng)建多臺(tái)。
請(qǐng)見(jiàn)下面架構(gòu)圖
這里我們選擇nginx做負(fù)載均衡器,負(fù)載均衡器部署在k8s集群里,負(fù)載均衡器的RealServer是集群外的MySql從庫(kù)集群。
業(yè)務(wù)pod1和pod2里配置的是負(fù)載均衡器nginx的svc的域名,使用域名和數(shù)據(jù)庫(kù)ip解耦,通過(guò)負(fù)載均衡nginx實(shí)現(xiàn)mysqlslave的LB和HA的功能。
針對(duì)每一個(gè)組件分別啟用一個(gè)新的負(fù)載均衡器而非共用負(fù)載均衡器,這樣各個(gè)組件的負(fù)載均衡器變更或者出故障相互之間不受影響。犧牲一些服務(wù)器成本換取穩(wěn)定性。
下面我們看一下負(fù)載均衡nginx的配置
- 1. workload 配置 cat rollout.yaml
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: lb-mysql-server
namespace: release
labels:
app.kube.NETes.io/name: lb-mysql-server
spec:
minAvAIlable: 1
selector:
matchLabels:
app.kubernetes.io/name: lb-mysql-server
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
labels:
app.kubernetes.io/name: lb-mysql-server
name: lb-mysql-server
namespace: release
spec:
replicas: 1
strategy:
canary:
steps:
- setWeight: 20
- pause: { "duration": 30s }
revisionHistoryLimit: 3
selector:
matchLabels:
app.kubernetes.io/name: lb-mysql-server
template:
metadata:
labels:
app.kubernetes.io/name: lb-mysql-server
spec:
imagePullSecrets:
- name: your-registry-secrets
volumes:
- name: etc-nginx
configMap:
name: lb-mysql-server-cm
containers:
- image: nginx:1.23.2-alpine
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 8081
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: nginx-proxy
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 8081
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 25m
memory: 32M
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/nginx
name: etc-nginx
readOnly: true
enableServiceLinks: true
restartPolicy: Always
terminationGracePeriodSeconds: 30
- 1. configMap配置,配置代理Realserver cat cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: lb-mysql-server-cm
namespace: release
labels:
app.kubernetes.io/name: lb-mysql-server
data:
nginx.conf: |
error_log stderr notice;
worker_processes 2;
worker_rlimit_nofile 130048;
worker_shutdown_timeout 10s;
events {
multi_accept on;
use epoll;
worker_connections 16384;
}
stream {
upstream lb_mysql_server {
least_conn;
server 192.168.1.11:3306 max_fails=2 fail_timeout=30s;
server 192.168.1.12:3306 max_fails=2 fail_timeout=30s;
server 192.168.1.13:3306 max_fails=2 fail_timeout=30s;
}
server {
listen 3306;
proxy_pass lb_mysql_server;
proxy_timeout 10m;
proxy_connect_timeout 1s;
}
}
http {
aio threads;
aio_write on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 5m;
keepalive_requests 100;
reset_timedout_connection on;
server_tokens off;
autoindex off;
server {
listen 8081;
location /healthz {
access_log off;
return 200;
}
location /stub_status {
stub_status on;
access_log off;
}
}
}
- 1. svc配置 cat svc.yaml
apiVersion: v1
kind: Service
metadata:
name: lb-mysql-server
namespace: release
labels:
app.kubernetes.io/name: lb-mysql-server
spec:
selector:
app.kubernetes.io/name: lb-mysql-server
ports:
- name: lb-mysql-server
protocol: TCP
port: 3306
targetPort: 3306
nginx負(fù)載均衡健康檢查具體請(qǐng)見(jiàn):TCP Health Checks
nginx loadBalancing






