Calico網絡方案


參考文檔:

  1. Difficulties with traditional overlay networks:https://www.projectcalico.org/learn/
  2. Get Start(v2.6.x):https://docs.projectcalico.org/v2.6/getting-started/docker/
  3. Calico組件(v2.6.x):https://docs.projectcalico.org/v2.6/reference/architecture/
  4. 配置calicoctl(v2.6.x):https://docs.projectcalico.org/v2.6/reference/calicoctl/setup/etcdv2
  5. 資源定義:https://docs.projectcalico.org/v2.6/reference/calicoctl/resources/
  6. Calico網絡模型:http://cizixs.com/2017/10/19/docker-calico-network
  7. 白話kubernetes網絡:http://dockone.io/article/2616

 一.Calico架構

Calico是一個純三層的方案,為虛機及容器提供多主機間通信,沒有使用重疊網絡(如flannel)驅動,采用虛擬路由代替虛擬交換,每一台虛擬路由器通過BGP協議傳播可達信息(路由)到其他虛擬或物理路由器。

1. 框架

  1. Felix:Calico agent,運行在每台workload節點,主要負責配置路由及ACLs等信息,確保endpoint的連通狀態;
  2. Etcd:分布式kv存儲,主要負責網絡元數據一致性,確保Calico網絡狀態的准確性;
  3. BGP Client(BIRD):主要負責把Felix寫入kernel的路由信息分發到當前Calico網絡,確保workload間的通信的有效性;
  4. BGP Route Reflector(BIRD):一般在大規模部署時采用,與所有節點互聯的mesh模式不同,通過一個或多個BGP Route Reflector來完成集中式的路由分發。

二.環境 

1. 環境規划

docker服務(含加速)與etcd集群服務已提前部署,可參考:

docker安裝服務: https://docs.docker.com/install/linux/docker-ce/centos/ 

                        https://www.cnblogs.com/netonline/p/7420047.html

docker鏡像加速:https://yq.aliyun.com/articles/29941(阿里雲)

                         https://www.cnblogs.com/netonline/p/7420188.htmlDaocloud

etcd: https://www.cnblogs.com/netonline/p/8665847.html

Hostname

IP

Service

os

Remark

calico-node1

172.30.200.36

docker 1.12.6

etcd v3.3.0

calico v2.6.10

centos7.4

selinux disabled

calico-node2

172.30.200.37

docker 1.12.6

etcd v3.3.0

calico v2.6.10

centos7.4

selinux disabled

calico-node3

172.30.200.38

docker 1.12.6

etcd v3.3.0

calico v2.6.10

centos7.4

selinux disabled

注:這里並未采用calico v3.x.x版本,v2與v3版本在命令以及資源下發等操作區別較大。

2. 設置iptables

# 統一設置iptables,以calico-node1節點為例;
# 初始環境已使用iptables替代centos7.x自帶的firewalld;
[root@calico-node1 ~]# vim /etc/sysconfig/iptables
# tcp179:bgp通信端口;
# tcp2375:docker-api端口;
# tcp2379:etcd監聽端口;
# tcp2380:etcd集群通信端口;
# 注釋“FORWARD”表的禁止轉發規則
-A INPUT -p tcp -m state --state NEW -m tcp --dport 179 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 2375 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 2379 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 2380 -j ACCEPT
#-A FORWARD -j REJECT --reject-with icmp-host-prohibited

[root@calico-node1 ~]# service iptables restart

三.配置calicoctl 

1. 安裝calicoctl

# 以下操作主要在calico-node1節點執行,其余節點類似,做適當調整;
# 下載calicoctl命令行工具
[root@calico-node1 ~]# cd /usr/local/src
[root@calico-node1 src]# curl -O -L https://github.com/projectcalico/calicoctl/releases/download/v1.6.4/calicoctl

# 下載的”calicoctl”賦予權限后,可直接運行
[root@calico-node1 src]# chmod +x calicoctl
[root@calico-node1 src]# mv /usr/local/src/calicoctl /usr/local/bin/

2. 配置calicoctl

# 運行calicoctl時,默認調用/etc/calico/calicoctl.cfg文件,其中指定了datastoreType與etcdEndpoints等重要參數;
# 或在運行calicoctl時,通--config參數指定文件
[root@calico-node1 ~]# mkdir -p /etc/calico
[root@calico-node1 ~]# vim /etc/caloco/calicoctl.cfg
[root@calico-node1 ~]# cat /etc/calico/calicoctl.cfg
apiVersion: v1
kind: calicoApiConfig
metadata:
spec:
  datastoreType: "etcdv2"
  etcdEndpoints: http://172.30.200.36:2379,http://172.30.200.37:2379,http://172.30.200.38:2379

四.設置docker連接etcd 

1. 設置docker連接etcd

# 修改docker服務的啟動參數,即”ExecStart=/usr/bin/dockerd”;
# -H(option): 指定api端口;
# --cluster-store:連接etcd,docker支持跨主機的多節點網絡時,需要設置此參數,否則網絡元數據無法協同
[root@calico-node1 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375 --cluster-store etcd://172.30.200.36:2379,172.30.200.37:2379,172.30.200.38:2379

[root@calico-node1 ~]# systemctl daemon-reload && systemctl restart docker

五.啟動calico服務

Calico服務以container的方式運行,container內包含bird路由管理、Felix協議等,並采用host網絡與外部通信。

所有workload節點啟用Calico服務,做為calico節點(通過etcd)互相通信。

1. 下載鏡像

# calico服務默認鏡像”quay.io/calico/node:v2.6.10”;
# 如拉取鏡像有困難,可通過docker.io下載
[root@calico-node1 ~]# docker pull calico/node:v2.6.10

# 下載busybox鏡像用作驗證
[root@calico-node1 ~]# docker pull busybox

2. calico服務

或直接運行:calicoctl node run --node-image=calico/node:v2.6.10

1)system service文件

# EnvironmentFile:ExecStart中大量引用的環境變量,在/etc/calico/calico.env文件中設置;
# ExecStartPre操作:如果環境中存在calico-node服務,刪除;
# ExecStart操作:”--net”設置網絡參數;“--privileged”以特權模式運行;‘“--nam”設置容器名;“calico/node:v2.6.10”指定鏡像,這里默認是“quay.io/calico/node:v2.6.10”;
# ExecStop操作:停止容器;
# -v /var/run/docker.sock:/var/run/docker.sock:此映射關系在官方文檔中未給出;
# 會導致在創建容器時報錯“docker: Error response from daemon: failed to create endpoint test1 on network net1: NetworkDriver.CreateEndpoint: Network 44322b3b9b8c5eface703e1dbeb7e3755f47ede1761a72ea4cb7cec6d31ad2e5 inspection error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.”;
# 即在calico類型的網絡上不能創建容器,因為無法調用docker服務的sock,需要指明calico服務調用docker sock的路徑,請見:https://github.com/projectcalico/calico/issues/1303
[root@calico-node1 ~]# vim /usr/lib/systemd/system/calico.service
[Unit]
Description=calico-node
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/etc/calico/calico.env
ExecStartPre=-/usr/bin/docker rm -f calico-node
ExecStart=/usr/bin/docker run --net=host --privileged \
 --name=calico-node \
 -e NODENAME=${CALICO_NODENAME} \
 -e IP=${CALICO_IP} \
 -e IP6=${CALICO_IP6} \
 -e CALICO_NETWORKING_BACKEND=${CALICO_NETWORKING_BACKEND} \
 -e AS=${CALICO_AS} \
 -e NO_DEFAULT_POOLS=${CALICO_NO_DEFAULT_POOLS} \
 -e CALICO_LIBNETWORK_ENABLED=${CALICO_LIBNETWORK_ENABLED} \
 -e ETCD_ENDPOINTS=${ETCD_ENDPOINTS} \
 -e ETCD_CA_CERT_FILE=${ETCD_CA_CERT_FILE} \
 -e ETCD_CERT_FILE=${ETCD_CERT_FILE} \
 -e ETCD_KEY_FILE=${ETCD_KEY_FILE} \
 -v /var/log/calico:/var/log/calico \
 -v /run/docker/plugins:/run/docker/plugins \
 -v /var/run/docker.sock:/var/run/docker.sock \ -v /lib/modules:/lib/modules \
 -v /var/run/calico:/var/run/calico \
 calico/node:v2.6.10

ExecStop=-/usr/bin/docker stop calico-node

Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

2)calico.env變量文件

[root@calico-node1 ~]# vim /etc/calico/calico.env
ETCD_ENDPOINTS=http://172.30.200.36:2379,http://172.30.200.37:2379,http://172.30.200.38:2379
# 啟用ssl/tls時,認證相關文件位置
ETCD_CA_FILE=""
ETCD_CERT_FILE=""
ETCD_KEY_FILE=""
# 留空時默認采用主機hostname作為辨識,所以留空時請確保主機名唯一
CALICO_NODENAME=""
CALICO_NO_DEFAULT_POOLS=""
# 設置路由下一跳,留空時從主機當前端口中自動選擇,有參數”autodetect”強制每次啟動時間自動檢測
CALICO_IP="172.30.200.36"
CALICO_IP6=""
# as number,默認從全局默認設置繼承
CALICO_AS=""
# 啟用libnetwork drive
CALICO_LIBNETWORK_ENABLED=true # 路由協議,可選”bird”,“gobgp”,“none”,默認即”bird”, “gobgp”無ipip模式
CALICO_NETWORKING_BACKEND=bird

3)啟動calico服務

[root@calico-node1 ~]# systemctl daemon-reload
[root@calico-node1 ~]# systemctl enable calico
[root@calico-node1 ~]# systemctl restart calico

[root@calico-node1 ~]# systemctl status calico

[root@calico-node1 ~]# docker ps

4)查看節點狀態

# 任意節點可查看;
# 顯示鄰居節點地址,節點之間是”node-to-node mesh”狀態(區別於bgp rr)
[root@calico-node1 ~]# calicoctl node status

 六.定義ipPooloption 

1. 查看當前ipPool

# 運行calico服務后,默認含1個192.168.0.0/16的ipv4地址池,1個64位的ipv6的地址池,后續網絡分配即地址池獲取;
# NAT:容器獲得的地址是否可nat出host;
# IPIP:ipip是在宿主機網絡不完全支持bgp時,一種妥協的overlay機制,在宿主機創建1個”tunl0”虛擬端口;設置為false時,路由即純bgp模式,理論上ipip模式的網絡傳輸性能低於純bgp模式;設置為true時,又分ipip always模式(純ipip模式)與ipip cross-subnet模式(ipip-bgp混合模式),后者指“同子網內路由采用bgp,跨子網路由采用ipip”
[root@calico-node1 ~]# calicoctl get ipPool -o wide

2. 自定義ipPool

1)定義ipPool

# 在任意節點上定義都可以,ipPool屬於全局;
# calicov2與v3對資源的定義邏輯基本相同,但命令參數區別較大
[root@calico-node1 ~]# calicoctl get ipPool -o yaml >> new-pool-1.yaml
[root@calico-node1 ~]# vim new-pool-1.yaml 
apiVersion: v1
kind: ipPool
metadata:
  # ipPool,每個host節點上的subnet從ipPool中獲取/26位網段
  cidr: 10.254.0.0/24
spec:
  ipip:
    # 默認即true
enabled: true
# mode:always與cross-subnet 
mode: cross-subnet
  # 默認為false,設置為true,允許容器nat出host
  nat-outgoing: true
  # 默認即false,即啟用此ipPool
  disabled: false

# 下發ipPool資源
[root@calico-node1 ~]# calicoctl create -f new-pool-1.yaml

2)刪除默認ipPool(option)

[root@calico-node1 ~]# calicoctl delete ipPool 192.168.0.0/16
[root@calico-node1 ~]# calicoctl get ipPool -o wide

3. 驗證

# 資源下發后,各節點從ipPool獲得1個/26位的subnet網段;
# 同時注意前往其余節點的下一跳網口是“tunl0”,這里因為ipip設置為enable: true;
# 如果不啟用ipip模式,則不會新增”tunl0”網口,下一跳網口應是“eth0”
[root@calico-node1 ~]# ip route show

# 查看網卡,新增網口從命名”tunl0”可看出與隧道有關;
# 同時隧道口獲取的是分配到節點的subnet內的32位地址
[root@calico-node1 ~]# ip address show

七.驗證連通性 

1. 創建network

# 創建網絡“net1”;
# --driver calico:指定使用calico的libnetwork driver;
# --ipam-driver calico-ipam:指定使用calico的IPAM driver管理IP
[root@calico-node1 ~]# docker network create --driver calico --ipam-driver calico-ipam net1

# 新建網絡”net1”的驅動是calico,屬於全局類型網絡,即在其余節點可見;
# 可通過”docker network inspect net1”查看細節
[root@calico-node1 ~]# docker network ls

2. 創建容器

1)創建容器

# 創建容器,容器使用calico類型的”net1”網絡
[root@calico-node1 ~]# docker run -tid --name=test1 --net=net1 busybox
[root@calico-node1 ~]# docker ps

2)容器網絡

# 容器的ip地址從ipPool分配到host節點的subnet中獲取,且為/32主機地址;
# 網關為“169.254.1.1”(后面給出原因)
[root@calico-node1 ~]# docker inspect test1

 

3. 網絡變化

1)host節點網卡

# 新增10號網卡”calic255b5bfca1”,對接9號網卡,可以確定創建的容器即使用9號網卡
[root@calico-node1 ~]# ip address show

2)host節點routing table

# 新增1條主機路由,主機地址即容器地址,下一跳即網卡”calic255b5bfca1”
[root@calico-node1 ~]# ip route show

3)容器網卡

# 容器網卡cali0即9號網卡,對接host節點10號網卡;
# 也再次印證容器獲取的是/32位主機地址;
# 注意容器網卡的mac地址”ee:ee:ee:ee:ee:ee”, 這是1個固定的特殊地址(所有calico生成的容器mac地址均一樣),因為calico只關心三層的ip地址,而不關心二層mac地址
[root@calico-node1 ~]# docker exec test1 ip address show

4)容器routing table

# 容器網關“169.254.1.1”是1個預留本地ip地址,通過cali0端口發送到網關;
# calico為簡化網絡配置,將容器的網關設置為1個固定的本地保留地址,容器內路由規則都是一樣的,不需要動態更新;
# 確定下一跳后,容器會查詢下一跳”169.254.1.1”的mac地址
[root@calico-node1 ~]# docker exec test1 ip route show

# 通過”ip neigh show”可查詢arp表(需要觸發),這里查詢到”169.254.1.1”的mac地址是”d6:3d:3a:ca:39:a1”,仔細觀察會發現此mac地址即host節點網卡”calic255b5bfca1”的mac地址
[root@calico-node1 ~]# docker exec test1 ip neigh show

# 通過在host節點”calic255b5bfca1”網卡上抓二層包發現,容器的”cali0”網卡(mac地址”ee:ee:ee:ee:ee:ee”)發出的request包,host節點的”calic255b5bfca1”網卡直接以本地mac地址”d6:3d:3a:ca:39:a1”回復;
# 如果清除容器的arp表,可以更清晰的看到容器的arp請求報文被host節點對應的網卡響應
[root@calico-node1 ~]# tcpdump -i calic255b5bfca1 -e -nn

# 如上,host節點對應容器的網卡並沒有配置ip地址,無論容器發出的arp的請求地址是什么,其直接以自己的mac地址響應即”arp proxy”;
# 容器的后續報文目的IP不變,但mac地址變成了宿主機上對應interface的地址,即所有的報文都會發給宿主機,然后宿主機根據ip地址進行轉發,此feature是calico默認開啟的,可通過如下方式確認:
[root@calico-node1 ~]# cat /proc/sys/net/ipv4/conf/calic255b5bfca1/proxy_arp

4. 容器連通性

# 在calico-node2節點創建容器
[root@calico-node2 ~]# docker run -tid --name=test2 --net=net1 busybox

# 如預期,容器之間可通信
[root@calico-node2 ~]# docker exec test2 ping 10.254.0.5

# 在calico-node1節點的”tunl0”端口抓包,確定容器之間通過tunl0端口通信
[root@calico-node1 ~]# tcpdump -i tunl0 icmp -n

八.補充

針對flannel與calico網絡方案做簡單的對比,如下:

 

Flannel

Calico

overlay方案

1. udp

2. vxlan

ipip,宿主機網絡不能完全支持bgp時,可采用ipip模式

host-gw方案

host-gw,要求宿主機在相同subnet

bgp

網絡策略

不支持

支持

ipam

不支持去中心化ipam

不支持去中心化ipam

性能

理論值

1. host-gw模式的性能優於overlay模式,甚至接近於宿主機直接通信;

2. flannel host-gw模式與calico bgp模式相當;

3. flannel overlay模式與calico ipip模式相當或略差,ipip包頭較vxlan小;

4. flannel udp 模式相對最差,udp封裝方式在linux用戶態,vxlan與ipip封裝在linux內核態完成(ipip安全性不如vxlan)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM