介紹
在上一期HA k8s搭建介紹有說到,目前有兩種比較火的HA集群,那么今天我們來說說第二種,也是目前比較主流的部署方式,采用的是haproxy+keepalived+etcd+k8s的模式,和第一種集群相比較多了有個haproxy,它是干嘛的呢,下面是它的大概簡介
HAProxy簡介
(1)HAProxy 是一款提供高可用性、負載均衡以及基于TCP(第四層)和HTTP(第七層)應用的代理軟件,支持虛擬主機,它是免費、快速并且可靠的一種解決方案。 HAProxy特別適用于那些負載特大的web站點,這些站點通常又需要會話保持或七層處理。HAProxy運行在時下的硬件上,完全可以支持數以萬計的 并發連接。并且它的運行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web服務器不被暴露到網絡上。
(2)HAProxy 實現了一種事件驅動、單一進程模型,此模型支持非常大的并發連接數。多進程或多線程模型受內存限制 、系統調度器限制以及無處不在的鎖限制,很少能處理數千并發連接。事件驅動模型因為在有更好的資源和時間管理的用戶端(User-Space) 實現所有這些任務,所以沒有這些問題。此模型的弊端是,在多核系統上,這些程序通常擴展性較差。這就是為什么他們必須進行優化以 使每個CPU時間片(Cycle)做更多的工作。
(3)HAProxy 支持連接拒絕 : 因為維護一個連接的打開的開銷是很低的,有時我們很需要限制攻擊蠕蟲(attack bots),也就是說限制它們的連接打開從而限制它們的危害。 這個已經為一個陷于小型DDoS攻擊的網站開發了而且已經拯救
了很多站點,這個優點也是其它負載均衡器沒有的。
(4)HAProxy 支持全透明代理(已具備硬件防火墻的典型特點): 可以用客戶端IP地址或者任何其他地址來連接后端服務器. 這個特性僅在Linux?2.4/2.6內核打了cttproxy補丁后才可以使用. 這個特性也使得為某特殊服務器處理部分流量同時又不修改服務器的地址成為可能。
性能
HAProxy借助于OS上幾種常見的技術來實現性能的最大化。
1,單進程、事件驅動模型顯著降低了上下文切換的開銷及內存占用。
2,O(1)事件檢查器(event checker)允許其在高并發連接中對任何連接的任何事件實現即時探測。
3,在任何可用的情況下,單緩沖(single buffering)機制能以不復制任何數據的方式完成讀寫操作,這會節約大量的CPU時鐘周期及內存帶寬;
4,借助于Linux 2.6 (>= 2.6.27.19)上的splice()系統調用,HAProxy可以實現零復制轉發(Zero-copy forwarding),在Linux 3.5及以上的OS中還可以實現零復制啟動(zero-starting);
5,內存分配器在固定大小的內存池中可實現即時內存分配,這能夠顯著減少創建一個會話的時長;
6,樹型存儲:側重于使用作者多年前開發的彈性二叉樹,實現了以O(log(N))的低開銷來保持計時器命令、保持運行隊列命令及管理輪詢及最少連接隊列;
7,優化的HTTP首部分析:優化的首部分析功能避免了在HTTP首部分析過程中重讀任何內存區域;
8,精心地降低了昂貴的系統調用,大部分工作都在用戶空間完成,如時間讀取、緩沖聚合及文件描述符的啟用和禁用等;
所有的這些細微之處的優化實現了在中等規模負載之上依然有著相當低的CPU負載,甚至于在非常高的負載場景中,5%的用戶空間占用率和95%的系統空間占用率也是非常普遍的現象,這意味著HAProxy進程消耗比系統空間消耗低20倍以上。因此,對OS進行性能調優是非常重要的。即使用戶空間的占用率提高一倍,其CPU占用率也僅為10%,這也解釋了為何7層處理對性能影響有限這一現象。由此,在高端系統上HAProxy的7層性能可輕易超過硬件負載均衡設備。
在生產環境中,在7層處理上使用HAProxy作為昂貴的高端硬件負載均衡設備故障故障時的緊急解決方案也時長可見。硬件負載均衡設備在“報文”級別處理請求,這在支持跨報文請求(request across multiple packets)有著較高的難度,并且它們不緩沖任何數據,因此有著較長的響應時間。對應地,軟件負載均衡設備使用TCP緩沖,可建立極長的請求,且有著較大的響應時間。
????????????????????????????????????????????????????????????????????????摘抄至HAProxy用法詳解 全網最詳細中文文檔
一般情況下haproxy會和keepalived一起使用。
老規矩,下面附上k8s理想的高可用架構圖。
那在本文中,我們的k8s架構應該是怎么樣的呢,我從網上找到了一個非常符合我們整個K8S HA架構的圖,然后稍微做了修改。本文大致高可用架構圖如下
在原圖中使用的是Nginx作為負載均衡,而我們本文中則使用的是haproxy。好了下面開始目前主流的k8s架構搭建
主機節點清單
主機名IP地址說明組件,如果是沒搭建過k8s集群的,需要先看看我之前寫的初階k8s集群搭建,需要安裝的一些軟件和容器鏡像。
master1節點 192.168.100.1 4核4G內存?
keepalived、haproxy、etcd、kubelet、kube-apiserver、kube-scheduler、kube-proxy、kube-dashboard、heapster
master2節點 192.168.100.2 ?4核4G內存?
keepalived、haproxy、etcd、kubelet、kube-apiserver、kube-scheduler、kube-proxy、kube-dashboard、heapster
master3節點 192.168.100.3?4核4G內存?
keepalived、haproxy、etcd、kubelet、kube-apiserver、kube-scheduler、kube-proxy、kube-dashboard、heapster
vip 192.168.100.4 keepalived?4核4G內存?
在每個master節點上設置好hostname 、hosts
192.168.100.1 master1
192.168.100.2?master2
192.168.100.3?master3
由于本次安裝全部容器化部署,因此部署過程相對比較簡單。
ECTD部署
在每個master節點上
先拉取最新的etcd官方鏡像,這可能需要翻墻,童鞋們可以改下阿里云的加速鏡像地址,這里就不做多概述了,官方最新的etcd鏡像版本對應常規版的etcd是3.2.17版本
docker pull?quay.io/coreos/etcd
docker tag?quay.io/coreos/etcd?quay.io/coreos/etcd:3.2.17
新建一個etcd數據存儲路徑,下面只是例子,童鞋們自行修改
mkdir /u03/etcd_docker?
master1
docker run -d \
--restart always \
-v /etc/etcd/ssl/certs:/etc/ssl/certs \
-v /u03/etcd_docker:/var/lib/etcd \
-p 2380:2380 \
-p 2379:2379 \
--name etcd \
quay.io/coreos/etcd:3.2.17 \
etcd --name=master1 \
--advertise-client-urls=http://192.168.100.1:2379 \
--listen-client-urls=http://0.0.0.0:2379 \
--initial-advertise-peer-urls=http://192.168.100.1:2380 \
--listen-peer-urls=http://0.0.0.0:2380 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster=master1=http://192.168.100.1:2380,master2=http://192.168.100.2:2380,master3=http://192.168.100.3:2380 \
--initial-cluster-state=new \
--auto-tls \
--peer-auto-tls \
--data-dir=/var/lib/etcd
master2
docker run -d \
--restart always \
-v /etc/etcd/ssl/certs:/etc/ssl/certs \
-v /u03/etcd_docker:/var/lib/etcd \
-p 2380:2380 \
-p 2379:2379 \
--name etcd \
quay.io/coreos/etcd:3.2.17 \
etcd --name=master2 \
--advertise-client-urls=http://192.168.100.2:2379 \
--listen-client-urls=http://0.0.0.0:2379 \
--initial-advertise-peer-urls=http://192.168.100.2:2380 \
--listen-peer-urls=http://0.0.0.0:2380 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster=master1=http://192.168.100.1:2380,master2=http://192.168.100.2:2380,master3=http://192.168.100.3:2380 \
--initial-cluster-state=new \
--auto-tls \
--peer-auto-tls \
--data-dir=/var/lib/etcd
master3
docker run -d \
--restart always \
-v /etc/etcd/ssl/certs:/etc/ssl/certs \
-v /u03/etcd_docker:/var/lib/etcd \
-p 2380:2380 \
-p 2379:2379 \
--name etcd \
quay.io/coreos/etcd:3.2.17 \
etcd --name=master3 \
--advertise-client-urls=http://192.168.100.3:2379 \
--listen-client-urls=http://0.0.0.0:2379 \
--initial-advertise-peer-urls=http://192.168.100.3:2380 \
--listen-peer-urls=http://0.0.0.0:2380 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster=master1=http://192.168.100.1:2380,master2=http://192.168.100.2:2380,master3=http://192.168.100.3:2380 \
--initial-cluster-state=new \
--auto-tls \
--peer-auto-tls \
--data-dir=/var/lib/etcd
這樣在三臺節點上完成ETCD集群的部署,在這里沒有使用https,是因為想簡化部署過程,也不需要涉及到外部網絡,如果有安全認證方面的需求可以按照我上一篇高階k8s HA 集群搭建(一)里搭建etcd集群的方式,照葫蘆畫瓢。
如果在部署過程中出現問題,etcd容器沒有啟動或者一直再重啟則通過docker ps -a查看容器id,通過docker logs?CONTAINER ID來排查問題。
驗證方式:
1.如果你安裝了etcdctl則
etcdctl --endpoints=http://192.168.100.1:2379,http://192.168.100.2:2379,http://192.168.100.3:2379 \
cluster-health
etcdctl --endpoints=http://192.168.100.1:2379,http://192.168.100.2:2379,http://192.168.100.3:2379 \
member list
2.直接到etcd容器里驗證
docker exec -ti etcd ash
etcdctl member list
etcdctl cluster-health
exit
keepalived
在每個master節點上執行
拉取keepalived鏡像
docker pull osixia/keepalived:1.4.4
載入內核相關模塊
lsmod | grep ip_vs
modprobe ip_vs
部署keepalived
docker run --net=host --cap-add=NET_ADMIN \
-e KEEPALIVED_INTERFACE=eno16780032 \
-e KEEPALIVED_VIRTUAL_IPS="#PYTHON2BASH:['192.168.100.4']" \
-e KEEPALIVED_UNICAST_PEERS="#PYTHON2BASH:['192.168.100.1','192.168.100.2','192.168.100.3']" \
-e KEEPALIVED_PASSWORD=admin \
--name k8s-keepalived \
--restart always \
-d?osixia/keepalived:1.4.4
其中KEEPALIVED_INTERFACE填的是192.168.100.0/24網段所在的網卡,可以通過ip a命令來查看。KEEPALIVED_VIRTUAL_IPS設置的是需要用到的vip。
三臺master節點部署完成后通過ping?192.168.100.4的方式驗證是否通,或者直接ip a查看第一臺部署的master,網卡上是不是多了一個ip。
如果出現問題,也可以通過docker logs k8s-keepalived來調試。
如果失敗后清理,重新部署
docker rm -f k8s-keepalived
haproxy
在每個master上執行
拉取haproxy鏡像
docker pull haproxy:1.7.8-alpine
創建haproxy配置文件夾
mkdir /etc/haproxy
創建haproxy配置
cat >/etc/haproxy/haproxy.cfg<<EOF
global
? log 127.0.0.1 local0 err
? maxconn 50000
? uid 99
? gid 99
? #daemon
? nbproc 1
? pidfile haproxy.pid
defaults
? mode http
? log 127.0.0.1 local0 err
? maxconn 50000
? retries 3
? timeout connect 5s
? timeout client 30s
? timeout server 30s
? timeout check 2s
listen admin_stats
? mode http
? bind 0.0.0.0:1080
? log 127.0.0.1 local0 err
? stats refresh 30s
? stats uri? ? /haproxy-status
? stats realm? Haproxy\ Statistics
? stats auth ? ?admin:admin
? stats hide-version
? stats admin if TRUE
frontend k8s-https
? bind 0.0.0.0:8443
? mode tcp
? #maxconn 50000
? default_backend k8s-https
backend k8s-https
? mode tcp
? balance roundrobin
? server master1 192.168.100.1:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
? server master1 192.168.100.2:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
? server master1 192.168.100.3:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
EOF
啟動haproxy
docker run -d --name my-haproxy \
-v /etc/haproxy:/usr/local/etc/haproxy:ro \
-p 8443:8443 \
-p 1080:1080 \
--restart always \
haproxy:1.7.8-alpine
驗證
瀏覽器查看狀態
http://192.168.100.1:1080/haproxy-status
http://192.168.100.2:1080/haproxy-status
http://192.168.100.3:1080/haproxy-status
master節點初始化
ps:首先需要將相關軟件安裝一下,k8s相關的組件和鏡像
在第一臺master上創建新的token并記住(一會兒都要用到)
kubeadm token generate
制作配置文件
vim config.yaml
apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
kubeProxy:
? config:
? ? featureGates:
? ? ? SupportIPVSProxyMode: true
? ? mode: ipvs
etcd:
? endpoints:
? - http://192.168.100.1:2379
? - http://192.168.100.2:2379
? - http://192.168.100.3:2379
? dataDir: /u03/etcd_docker
networking:
? serviceSubnet: 10.96.0.0/12
? podSubnet: 10.244.0.0/16
kubernetesVersion: 1.10.0
api:
? advertiseAddress: "192.168.100.1" #每個節點的ip
apiServerExtraArgs:
? endpoint-reconciler-type: lease
controllerManagerExtraArgs:
? node-monitor-grace-period: 10s
? pod-eviction-timeout: 10s
apiServerCertSANs:
- master1
-?master2
-?master3
-?192.168.100.1
-?192.168.100.2
-?192.168.100.3
-?192.168.100.4
token: hpobow.vw1g1ya5dre7sq06 #之前生成的token
tokenTTL: "0"?#token失效時間,0表示永不失效
featureGates:
? CoreDNS: true
我們使用CoreDNS作為k8s內部網絡域名解析,使用ipvs做proxy內網負載均衡
kubeadm init --config?config.yaml?
systemctl enable kubelet
保存初始化完成之后的join命令
如果丟失可以使用命令"kubeadm token list"獲取
# kubeadm join 192.168.100.1:6443 --token hpobow.vw1g1ya5dre7sq06 --discovery-token-ca-cert-hash sha256:0e4f738348be836ff810bce754e059054845f44f01619a37b817eba83282d80f
配置kubectl使用
mkdir -p$HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf$HOME/.kube/config
sudo chown $(id -u):$(id -g)$HOME/.kube/config
或者root 用戶可以直接
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile
安裝網絡插件(只用安裝一次)
下載配置
部署網絡插件我們這里使用canal,既Calico的策略+flannel的網絡,因為在Calico目前還沒有很好的支持ipvs
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/flannel
kubectl apply -f \
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
kubectl apply -f \
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml
由于canal一些組件需要翻墻,先wget?https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml 下來,單獨下載里面的鏡像,再部署
如果Node有多個網卡的話,參考flannel issues 39701,
https://github.com/kubernetes/kubernetes/issues/39701
需要在canal.yaml中使用--iface參數指定集群主機內網網卡的名稱,
否則可能會出現dns無法解析。容器無法通信的情況,需要將canal.yaml下載到本地
修改如下,網卡名稱通過ip a自行查看
- name: kube-flannel
? ? ? ? ? image: quay.io/coreos/flannel:v0.9.1
? ? ? ? ? command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr", "--iface=eno16780032"?]
查看系統組件運行狀況
kubectl get pods --namespace kube-system
kubectl get svc --namespace kube-system
kubectl get nodes
在另外兩臺master節點上初始化
將在master1 的kubeadm生成證書密碼文件分發到master2和master3上面去
scp -r /etc/kubernetes/pki master2:/etc/kubernetes/
scp -r /etc/kubernetes/pki master3:/etc/kubernetes/
生成配置文件
使用和之前master1一樣的配置文件
token保持一致
制作配置文件
vim config.yaml
apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
kubeProxy:
? config:
? ? featureGates:
? ? ? SupportIPVSProxyMode: true
? ? mode: ipvs
etcd:
? endpoints:
? - http://192.168.100.1:2379
? - http://192.168.100.2:2379
? - http://192.168.100.3:2379
? dataDir: /u03/etcd_docker
networking:
? serviceSubnet: 10.96.0.0/12
? podSubnet: 10.244.0.0/16
kubernetesVersion: 1.10.0
api:
? advertiseAddress: "192.168.100.2" #每個節點的ip
apiServerExtraArgs:
? endpoint-reconciler-type: lease
controllerManagerExtraArgs:
? node-monitor-grace-period: 10s
? pod-eviction-timeout: 10s
apiServerCertSANs:
- master1
-?master2
-?master3
-?192.168.100.1
-?192.168.100.2
-?192.168.100.3
-?192.168.100.4
token: hpobow.vw1g1ya5dre7sq06 #之前生成的token
tokenTTL: "0"?#token失效時間,0表示永不失效
featureGates:
? CoreDNS: true
執行初始化
kubeadm init --config config.yaml
systemctl enable kubelet
保存初始化完成之后的join命令(方便工作節點加入)
等另外兩臺master部署完成之后
驗證
查看狀態
kubectl get pod --all-namespaces -o wide | grep master1
kubectl get pod --all-namespaces -o wide | grep?master2
kubectl get pod --all-namespaces -o wide | grep?master3
kubectl get nodes -o wide
修改master節點相關組件配置指向vip(每一臺master都要執行)
sed -i's@server: https://192.168.100.*:6443@server: https://192.168.100.4:8443@g'/etc/kubernetes/{admin.conf,kubelet.conf,scheduler.conf,controller-manager.conf}
重啟kubelet
systemctl daemon-reload
systemctl restart kubelet docker
查看所有節點狀態
kubectl get nodes -o wide
修改kube-proxy的配置
修改kube-proxy的配置指定vip
執行命令
kubectl edit -n kube-system configmap/kube-proxy
將server修改為server: https://192.168.100.4:8443并保存
查看設置
kubectl get -n kube-system configmap/kube-proxy -o yaml
刪除重建kube-proxy
kubectl get pods --all-namespaces -o wide | grep proxy
all_proxy_pods=$(kubectl get pods --all-namespaces -o wide | grep proxy | awk'{print $2}'| xargs)
echo$all_proxy_pods
kubectl delete pods$all_proxy_pods-n kube-system
kubectl get pods --all-namespaces -o wide | grep proxy
這樣三臺HA master節點就搭建完成了
*工作節點
工作節點需要用到剛剛的kubeadm join命令添加
kubeadm join 192.168.100.4:8443 --token hpobow.vw1g1ya5dre7sq06 --discovery-token-ca-cert-hash sha256:0e4f738348be836ff810bce754e059054845f44f01619a37b817eba83282d80f
systemctl enable kubelet
需要的軟件參考我的第一篇k8s集群搭建
修改工作節點kubelet配置并重啟
sed -i's@server: https://192.168.100.*:6443@server: https://192.168.100.4:8443@g'/etc/kubernetes/kubelet.conf
重啟kubelet
systemctl daemon-reload
systemctl restart kubelet docker
查看所有節點狀態
kubectl get nodes -o wide
這樣高可用集群就搭建完成了。這樣的master節點相對于第一種高可用的方式多了haproxy負載均衡,通過負載均衡將三臺master apiserver調用起來,實現資源高可用。
本文大量照搬了以下的文獻并做了一些自己的修改