Calico网络方案
参考文档:
- Difficulties with traditional overlay networks:https://www.projectcalico.org/learn/
- Get Start(v2.6.x):https://docs.projectcalico.org/v2.6/getting-started/docker/
- Calico组件(v2.6.x):https://docs.projectcalico.org/v2.6/reference/architecture/
- 配置calicoctl(v2.6.x):https://docs.projectcalico.org/v2.6/reference/calicoctl/setup/etcdv2
- 资源定义:https://docs.projectcalico.org/v2.6/reference/calicoctl/resources/
- Calico网络模型:http://cizixs.com/2017/10/19/docker-calico-network
- 白话kubernetes网络:http://dockone.io/article/2616
一.Calico架构
Calico是一个纯三层的方案,为虚机及容器提供多主机间通信,没有使用重叠网络(如flannel)驱动,采用虚拟路由代替虚拟交换,每一台虚拟路由器通过BGP协议传播可达信息(路由)到其他虚拟或物理路由器。
1. 框架

- Felix:Calico agent,运行在每台workload节点,主要负责配置路由及ACLs等信息,确保endpoint的连通状态;
- Etcd:分布式kv存储,主要负责网络元数据一致性,确保Calico网络状态的准确性;
- BGP Client(BIRD):主要负责把Felix写入kernel的路由信息分发到当前Calico网络,确保workload间的通信的有效性;
- 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.html(Daocloud)
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

六.定义ipPool(option)
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)。 |
|
Calico网络方案的更多相关文章
- 理解Docker(6):若干企业生产环境中的容器网络方案
本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- kubeadm单集群部署k8s1.15.1&calico网络
说明 本次实验在Windows下的VMware进行 系统配置及初始化配置在所有的主机执行 容器镜像全部替换为国内可拉取的 pod网络采用calico 实验环境 主机名 IP地址 角色 OS CPU/M ...
- Kubernetes网络方案 Flannel和calico
摘抄某博客 1. Flannel Flannel是为kubernetes设计的一个非常简洁的多节点三层网络方案,解决不同host上的容器互联问题,原理是为每个host分配一个subnet,容器从此 ...
- k8s的两种网络方案与多种工作模式[flannel与calico]
k8s的两种网络方案与多种工作模式 1. Flannel: flannel有三种工作模式: 1. vxlan(隧道方案) 2. host-gw(路由方案) 2. udp(在用户态实现的数据封装解封装, ...
- 容器中跨主机的网络方案-Calico
容器中的网络是建立docker集群的重要内容. 本文将介绍如何用Calico实现容器的多节点互通. Calico的组件结构如下: Calico通过etcd同步Bridge的信息,各个Docker no ...
- 如何部署 Calico 网络?- 每天5分钟玩转 Docker 容器技术(67)
Calico 是一个纯三层的虚拟网络方案,Calico 为每个容器分配一个 IP,每个 host 都是 router,把不同 host 的容器连接起来.与 VxLAN 不同的是,Calico 不对数据 ...
- Docker 跨主机网络方案分析
PS:文章首发公众号,欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 上篇文章介绍了容器网络的单主机网络,本文将进一步介绍多 ...
- k8s 各种网络方案 - 每天5分钟玩转 Docker 容器技术(170)
网络模型有了,如何实现呢? 为了保证网络方案的标准化.扩展性和灵活性,Kubernetes 采用了 Container Networking Interface(CNI)规范. CNI 是由 Core ...
- k8s网络之Calico网络
k8s网络主题系列: 一.k8s网络之设计与实现 二.k8s网络之Flannel网络 三.k8s网络之Calico网络 简介 Calico 是一种容器之间互通的网络方案.在虚拟化平台中,比如 Open ...
随机推荐
- 超简单,centos7安装docker
1.在centos7上直接yum安装docker [root@localhost ~]# yum install docker 2.启动docker [root@localhost ~]#servic ...
- weblogic之CVE-2018-3246 XXE分析
通过ftp通道将数据传出来.上传1.xml <!DOCTYPE xmlrootname [<!ENTITY % aaa SYSTEM "http://192.168.172.12 ...
- Day6 jQuery
元素的操作 dom对象和jQuery对象 dom对象:原生js获取节点 jQuery对象:通过jQuery获取节点对象 //dom对象 var oP = document.getElementById ...
- Day5 类和对象
面向对象编程OOP 类:相似对象的集合. 对象 对象:实体.一切可以被描述的事物. 属性:特征. 方法:动作,行为. 类和对象的区别 [1]类时抽象的,对象是具体的. [2]类是一个模板,创建出来的对 ...
- ES6新特性3:函数的扩展
本文摘自ECMAScript6入门,转载请注明出处. 一.函数参数默认值 1. ES6允许为函数的参数设置默认值,即直接写在参数定义的后面. function log(x, y = 'World') ...
- Sequelize-nodejs-9-Scopes
Scopes作用域 Scoping allows you to define commonly used queries that you can easily use later. Scopes c ...
- 横向滑动页面,导航条滑动居中的 js 实现思路
最近在做新闻咨询页的项目,各个新闻频道通过横向滑动切换,顶部的导航active栏需要跟着切换到对应频道,并且active到达中部时,要一直处在中间. 类似效果就是uc浏览器<UC头条>的导 ...
- Java代码输出到txt文件(申请专利贴源码的必备利器)
最近公司在申请专利,编写不少文档,项目的代码量实在是过于庞大.如果一个一个的复制粘贴虽然能够完成,但是对于程序员而言实在没有这个必要.shell或者python就能解决这个问题.由于我个人对于shel ...
- 【题解】洛谷P1070 道路游戏(线性DP)
次元传送门:洛谷P1070 思路 一开始以为要用什么玄学优化 没想到O3就可以过了 我们只需要设f[i]为到时间i时的最多金币 需要倒着推回去 即当前值可以从某个点来 那么状态转移方程为: f[i]= ...
- 美团热修复Robust-源码篇
上一篇主要分析了Robust的使用方法,这一篇就来总结一下Robust的源码分析. 我个人倾向于将Robust框架分为两个部分,自动插入代码和动态加载Patch. 一.Robust源码分析 目前我的分 ...