實驗背景
新版本特性:
- k8s 1.9 做了很大組件性能改進 ,
- 本版本用kube-router組件取代kube-proxy,用lvs做svc負載均衡,更快穩定。
- 用coredns取代kube-dns,DNS更穩定。
- 經過測試1.9版,消除了以往的kubelet docker狂報錯誤日誌的錯誤 ,更完美
- 支持 add動態插件
功能需求:
- 發佈內部k8s網絡,到機房全網
- cluster-ip,external-ip 全網路由
- 解決iptables 性能和負載聚合問題
- 還有iptables 負載NAT 丟失源ip問題
k8s測試版本
kubeadm version: &version. GitVersion:"v1.9.0", BuildDate:"2017-12-15T20:55:30Z"
網絡設備
Cisco 7200
R1 10.129.6.91
R2 10.129.6.92
Vrrp 10.129.6.8
K8s Node網絡
node01 10.129.6.211
node03 10.129.6.213
K8s 網絡
10.244.0.0/16
SVC 網絡
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d
nginx01 ClusterIP 10.110.133.162 10.33.1.11 80/TCP 6d
網絡拓撲如圖:
- 網絡高可用,目前我的方案是
- 雙核心交換機跑VRRP
- 模擬器,模擬網絡設備拓撲 R1 R2 主備路由器
#R1 Cisco Config
interface FastEthernet0/0
ip address 10.129.6.91 255.255.255.0
vrrp 1 ip 10.129.6.8
vrrp 1 priority 150
router bgp 64513
no synchronization
bgp log-neighbor-changes
neighbor 10.129.6.92 remote-as 64513
neighbor 10.129.6.211 remote-as 64512
neighbor 10.129.6.213 remote-as 64512
maximum-paths 2
no auto-summary
ip route 0.0.0.0 0.0.0.0 10.129.6.1
###############################
#R2 Cisco Config
interface FastEthernet0/0
ip address 10.129.6.92 255.255.255.0
vrrp 1 ip 10.129.6.8
vrrp 1 priority 110
router bgp 64513
no synchronization
bgp log-neighbor-changes
neighbor 10.129.6.92 remote-as 64513
neighbor 10.129.6.211 remote-as 64512
neighbor 10.129.6.213 remote-as 64512
maximum-paths 2
no auto-summary
ip route 0.0.0.0 0.0.0.0 10.129.6.1
部署k8s 1.9
此處省略,測試使用所以用
kubeadm 部署簡單快速
具體可以參看官方文檔
https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/
部署 kube-router
體系結構
Kube路由器是圍繞觀察者和控制器的概念而建立的。 觀察者使用Kubernetes監視API來獲取與創建,更新和刪除Kubernetes對象有關的事件的通知。 每個觀察者獲取與特定API對象相關的通知。 在從API服務器接收事件時,觀察者廣播事件。 控制器註冊以獲取觀察者的事件更新,並處理事件。
Kube-router由3個核心控制器和多個觀察者組成,如下圖所示。
主要改進
- 使用ipvs 替代 Iptables 方案 -性能更好
- 使用BGP 組網 更易發佈和擴展對接 之前方案要使用caclio 其他方案
- 集成police 網絡策略 之前網絡層控制很弱
- 負載均衡 更多可選功能 如rr sip hash ip回話保持
更多信息關注https://cloudnativelabs.github.io
deployment部署Yaml文件
在Kubernetes上部署Kube-router的最好的入門方法是使用集羣安裝程序.
- kubeadm 部署Kube-router,比較簡單就是導入yaml文件即可
我們使用的是如下,爲了對接Cisco 網絡設備發佈路由
wget https://github.com/cloudnativelabs/kube-router/blob/master/daemonset/kube-router-all-service-daemonset-advertise-routes.yaml
kubectl apply -f kube-router-all-service-daemonset-advertise-routes.yaml
#我們根據實際環境修改下
containers:
- args:
- --run-router=true
#啓用Pod網絡 - 通過iBGP發佈並學習到Pod的路由。 (默認爲true)
- --run-firewall=true
#啓用網絡策略 - 設置iptables爲pod提供入口防火牆。 (默認爲true)
- --run-service-proxy=true
#啓用服務代理 - 爲Kubernetes服務設置IPVS。 (默認爲true)
- --advertise-cluster-ip=true
#將該服務的集羣IP添加到RIB,以便通告給BGP peers.
- --advertise-external-ip=true
#將服務的外部IP添加到RIB,以便將其通告給BGP peers.
- --cluster-asn=64512
#集羣自身節點運行iBGP的ASN編號.
- --peer-router-ips=10.129.6.8
#所有節點將對等的外部路由器的IP地址,並通告集羣ip和pod cidr。 (默認[])
- --peer-router-asns=64513
#集羣節點將向其通告集羣ip和節點的pid cidr的BGP peers的ASN編號。 (默認[])
- 更多部署請自行查詢
https://github.com/cloudnativelabs/kube-router/tree/master/daemonset
部署的nginx 測試服務
#
apiVersion: v1
kind: Service
metadata:
annotations:
kube-router.io/service.scheduler: sh
labels:
app: nginx01
group: default
role: master
tier: backend
name: nginx01
namespace: default
spec:
clusterIP: 10.110.133.162
externalIPs:
- 10.33.1.11
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx01
group: default
role: master
tier: backend
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx01
# these labels can be applied automatically
# from the labels in the pod template if not set
# labels:
# app: redis
# role: master
# tier: backend
namespace: default
spec:
# this replicas value is default
# modify it according to your case
replicas: 1
# selector can be applied automatically
# from the labels in the pod template if not set
# selector:
# matchLabels:
# app: guestbook
# role: master
# tier: backend
template:
metadata:
labels:
app: nginx01
role: master
tier: backend
group: default
spec:
containers:
- name: nginx01
image: devhub.beisencorp.com/test/nginx:v3 # or just image: redis
resources:
requests:
cpu: 100m
memory: 80Mi
limits:
cpu: 500m
memory: 200M
ports:
- containerPort: 80
測試路由
[root@node01 k8s]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d
nginx01 ClusterIP 10.110.133.162 10.33.1.11 80/TCP 6d
[root@node01 k8s]# curl 10.33.1.11
< !DOCTYPE html>
< html>
< head>
< meta charset="UTF-8">
< title> 主標題 | 副標題< /title>
< /head>
< body>
<p>Hello, world! 我是版本V1
My V2 e WorldZ</p>
<p>Hello, world! ^ ^ ^ ^ ^ ^ V1
My V2 Bye WorldZ</p>
<p>Hello, world! ^ ^ ^ ^ ^ ^ V1
My V2 Bye WorldZ</p>
<p>Hello, world! ^ ^ ^ ^ ^ ^ V1
My V2 Bye WorldZ</p>ZX
< /body>
< /html>
## 我們查看下 網絡設備路由器信息是否學習過來
#BGP鄰居已建立
R1#sh bgp sum
BGP router identifier 10.129.6.91, local AS number 64513
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
10.129.6.92 4 64513 147 146 25 0 0 02:16:05 6
10.129.6.211 4 64512 306 269 0 0 0 01:28:40 Active
10.129.6.213 4 64512 314 270 0 0 0 01:28:40 Active
R1#sh ip route
10.0.0.0/8 is variably subnetted, 7 subnets, 2 masks
B 10.33.1.11/32 [200/0] via 10.129.6.92, 01:28:33
B 10.110.133.162/32 [200/0] via 10.129.6.92, 01:28:33
B 10.96.0.10/32 [200/0] via 10.129.6.92, 01:28:33
B 10.96.0.1/32 [200/0] via 10.129.6.92, 01:28:33
C 10.129.6.0/24 is directly connected, FastEthernet0/0
B 10.244.0.0/24 [200/0] via 10.129.6.211, 01:28:33
B 10.244.1.0/24 [200/0] via 10.129.6.213, 01:28:33
S* 0.0.0.0/0 [1/0] via 10.129.6.1
#R2 同上類同 R2備節點從R1主節點 學習全網路由
### 我們在看下 kube-router鄰居和路由是否學習過來
Here's a quick look at what's happening on this Node
--- BGP Server Configuration ---
AS: ======64512======
Router-ID: 10.129.6.211
Listening Port: 179, Addresses: 0.0.0.0, ::
--- BGP Neighbors ---
Peer AS Up/Down State |#Received Accepted
10.129.6.8 64513 00:00:15 Establ | 6 0
10.129.6.213 64512 03:40:40 Establ | 1 1
--- BGP Route Info ---
Network Next Hop AS_PATH Age Attrs
*> 10.33.1.11/32 10.129.6.211 00:00:58 [{Origin: i}]
*> 10.96.0.1/32 10.129.6.211 00:00:58 [{Origin: i}]
*> 10.96.0.10/32 10.129.6.211 00:00:58 [{Origin: i}]
*> 10.110.133.162/32 10.129.6.211 00:00:58 [{Origin: i}]
*> 10.244.0.0/24 10.129.6.211 00:00:58 [{Origin: i}]
*> 10.244.1.0/24 10.129.6.213 03:40:40 [{Origin: i} {LocalPref: 100}]
--- IPVS Services ---
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.33.1.11:80 sh
-> 10.244.1.16:80 Masq 1 0 0
TCP 10.96.0.1:443 rr persistent 10800
-> 10.129.6.211:6443 Masq 1 0 0
TCP 10.96.0.10:53 rr
-> 10.244.0.13:53 Masq 1 0 0
TCP 10.110.133.162:80 sh
-> 10.244.1.16:80 Masq 1 0 0
UDP 10.96.0.10:53 rr
-> 10.244.0.13:53 Masq 1 0 0
NAME
我們找臺機器加下靜態路由 指向網絡設備測試下 訪問
# 獲取 SVC 和pod ip
[root@node01 k8s]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d <none>
nginx01 ClusterIP 10.110.133.162 10.33.1.11 80/TCP 6d app=nginx01,group=default,role=master,tier=backend
[root@node01 k8s]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx01-d87b4fd74-7tw2x 1/1 Running 0 6d 10.244.1.16 node03
ClusterIP 路由
#ClusterIP 路由
route add -net 10.96.0.0 netmask 255.255.0.0 gw 10.129.6.8
ping 10.96.0.1
64 bytes from 10.96.0.1: icmp_seq=2 ttl=64 time=38.2 ms
64 bytes from 10.96.0.1: icmp_seq=3 ttl=64 time=0.258 ms
64 bytes from 10.96.0.1: icmp_seq=4 ttl=64 time=0.374 ms
external-ip 路由
#external-ip 路由
route add -net 10.33.1.11 netmask 255.255.255.255 gw 10.129.6.8
[root@haproxy02 zeming]# ping 10.33.1.11
PING 10.33.1.11 (10.33.1.11) 56(84) bytes of data.
From 10.129.6.8: icmp_seq=1 Redirect Host(New nexthop: 10.129.6.211)
64 bytes from 10.33.1.11: icmp_seq=1 ttl=64 time=41.4 ms
^C
--- 10.33.1.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 755ms
rtt min/avg/max/mdev = 41.459/41.459/41.459/0.000
# 獲取頁面
[root@haproxy02 zeming]# curl 10.33.1.11
< !DOCTYPE html>
< html>
< head>
< meta charset="UTF-8">
< title> 主標題 | 副標題< /title>
< /head>
< body>
<p>Hello, world! 我是版本V1
My V2 e WorldZ</p>
<p>Hello, world! ^ ^ ^ ^ ^ ^ V1
My V2 Bye WorldZ</p>
<p>Hello, world! ^ ^ ^ ^ ^ ^ V1
My V2 Bye WorldZ</p>
<p>Hello, world! ^ ^ ^ ^ ^ ^ V1
My V2 Bye WorldZ</p>ZX
< /body>
< /html>
pod 路由
#pod 路由
route add -net 10.244.0.0 netmask 255.255.0.0 gw 10.129.6.8
[root@haproxy02 xuzeming]# ping 10.244.0.13
PING 10.244.0.13 (10.244.0.13) 56(84) bytes of data.
64 bytes from 10.244.0.13: icmp_seq=1 ttl=63 time=41.8 ms
64 bytes from 10.244.0.13: icmp_seq=2 ttl=63 time=1.15 ms
主備網絡設備BGP 切換測試
- 測試方式 關閉R1主節點網絡設備 互聯網口 製造 R1離線
- 觀察 Vrrp 狀態轉移到備機
- 觀察 BGP 備機 建立所有mesh 鄰居狀態
R2#
*Mar 1 02:58:09.451: %VRRP-6-STATECHANGE: Fa0/0 Grp 1 state Backup -> Master
R10#
*Mar 1 02:58:46.415: %BGP-5-ADJCHANGE: neighbor 10.129.6.211 Up
R10#
*Mar 1 02:58:53.007: %BGP-5-ADJCHANGE: neighbor 10.129.6.213 Up
#
R10#sh ip rou
Codes: C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route
Gateway of last resort is 10.129.6.1 to network 0.0.0.0
10.0.0.0/8 is variably subnetted, 7 subnets, 2 masks
B 10.33.1.11/32 [20/0] via 10.129.6.213, 00:00:19
[20/0] via 10.129.6.211, 00:00:25
B 10.110.133.162/32 [20/0] via 10.129.6.213, 00:00:19
[20/0] via 10.129.6.211, 00:00:25
B 10.96.0.10/32 [20/0] via 10.129.6.213, 00:00:19
[20/0] via 10.129.6.211, 00:00:25
B 10.96.0.1/32 [20/0] via 10.129.6.213, 00:00:19
[20/0] via 10.129.6.211, 00:00:27
C 10.129.6.0/24 is directly connected, FastEthernet0/0
B 10.244.0.0/24 [20/0] via 10.129.6.211, 00:00:27
B 10.244.1.0/24 [20/0] via 10.129.6.213, 00:00:21
S* 0.0.0.0/0 [1/0] via 10.129.6.1
R10#sh bgp sum
BGP router identifier 10.129.6.92, local AS number 64513
BGP table version is 69, main routing table version 69
6 network entries using 702 bytes of memory
10 path entries using 520 bytes of memory
4 multipath network entries and 8 multipath paths
3/1 BGP path/bestpath attribute entries using 372 bytes of memory
1 BGP AS-PATH entries using 24 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 1618 total bytes of memory
BGP activity 6/0 prefixes, 64/54 paths, scan interval 60 secs
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
10.129.6.91 4 64513 187 194 0 0 0 00:00:33 Active
10.129.6.211 4 64512 683 364 69 0 0 00:02:38 5
10.129.6.213 4 64512 688 362 69 0 0 00:02:32 5
補充拓展
kube-router 參數一欄
Usage of ./kube-router:
--advertise-cluster-ip 將該服務的集羣IP添加到RIB,以便通告給BGP peers.
--advertise-external-ip 將服務的外部IP添加到RIB,以便將其通告給BGP peers.
--cleanup-config 清理iptables規則,ipvs,ipset配置並退出.
--cluster-asn uint 集羣節點運行iBGP的ASN編號.
--cluster-cidr string 羣集中的CIDR範圍。它被用來識別pods的範圍.
--config-sync-period duration apiserver配置同步之間的延遲(例如“5s”,“1m”)。必須大於0.(默認1m0s)
--enable-overlay 當enable-overlay設置爲true時,IP-in-IP隧道將用於跨不同子網中節點的pod-pod聯網。如果設置爲false,則不使用隧道,並且路由基礎架構預計爲不同子網中的節點之間的pod-pod聯網路由流量(默認值爲true)
--enable-pod-egress 從Pod到羣集外的SNAT流量。 (默認爲true)
--hairpin-mode 爲每個服務端點添加iptable規則以支持流量管控.
-h, --help 打印使用信息.
--hostname-override string 覆蓋節點的NodeName。如果kube-router無法自動確定您的NodeName,請設置此項.
--iptables-sync-period duration iptables規則同步之間的延遲(例如'5s','1m')。必須大於0.(默認1m0s)
--ipvs-sync-period duration ipvs config同步之間的延遲(例如'5s','1m','2h22m')。必須大於0.(默認1m0s)
--kubeconfig string 具有授權信息的kubeconfig文件的路徑(主位置由主標誌設置)。
--masquerade-all SNAT所有流量到羣集IP /節點端口。
--master string Kubernetes API服務器的地址(覆蓋kubeconfig中的任何值)。
--nodeport-bindon-all-ip 對於NodePort類型的服務,創建監聽節點的所有IP的IPVS服務.
--nodes-full-mesh 集羣中的每個節點都將建立與其他節點的BGP對等關係。 (默認爲true)
--peer-router-asns uintSlice 集羣節點將向其通告集羣ip和節點的pid cidr的BGP peers的ASN編號。 (默認[])
--peer-router-ips ipSlice 所有節點將對等的外部路由器的IP地址,並通告集羣ip和pod cidr。 (默認[])
--peer-router-passwords stringSlice 用“--peer-router-ips”定義的BGP peers進行認證的密碼。
--routes-sync-period duration 路線更新與廣播之間的延遲(例如“5s”,“1m”,“2h22m”)。必須大於0.(默認1m0s)
--run-firewall 啓用網絡策略 - 設置iptables爲pod提供入口防火牆。 (默認爲true)
--run-router 啓用Pod網絡 - 通過iBGP發佈並學習到Pod的路由。 (默認爲true)
--run-service-proxy 啓用服務代理 - 爲Kubernetes服務設置IPVS。 (默認爲true)```
DSR模式
請閱讀以下博客,瞭解如何結合使用DSR和“–advertise-external-ip”構建高度可擴展和可用的入口。 https://cloudnativelabs.github.io/post/2017-11-01-kube-high-available-ingress/
您可以爲每個服務啓用DSR(直接服務器返回)功能。當啓用的服務端點將直接響應客戶端通過簽署服務代理。啓用DSR時,Kube-router將使用LVS的隧道模式來實現此功能。
要啓用DSR,您需要使用kube-router.io/service.dsr = tunnel註釋來註釋服務。例如,
kubectl annotate service my-service "kube-router.io/service.dsr=tunnel"
在當前的實現中,當在服務上應用註釋時,DSR將僅適用於外部IP。
此外,當使用DSR時,當前的實現不支持端口重新映射。所以你需要使用相同的端口和目標端口的服務
你需要在kube-router守護進程清單中啓用hostIPC:true和hostPID:true。並且必須將主路徑/var/run/docker.sock設置爲kube-router的一個volumemount。
上述更改需要kube-router輸入pod namespace,並在pod中創建ipip隧道,並將外部IP分配給VIP。
對於示例清單,請查看啓用DSR要求的[manifest](../ daemonset / kubeadm-kuberouter-all-features-dsr.yaml).
負載均衡調度算法
kube-router使用LVS作爲服務代理。 LVS支持豐富的調度算法。您可以爲該服務添加註釋以選擇一個調度算法。當一個服務沒有註釋時,默認情況下選擇“輪詢”調度策略
For least connection scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=lc"
For round-robin scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=rr"
For source hashing scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=sh"
For destination hashing scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=dh"
參考文獻