千家信息网

基于calico网络策略

发表于:2024-11-14 作者:千家信息网编辑
千家信息网最后更新 2024年11月14日,一、简介Calico是一个纯三层的协议,为OpenStack虚机和Docker容器提供多主机间通信。Calico不使用重叠网络比如flannel和libnetwork重叠网络驱动,它是一个纯三层的方法
千家信息网最后更新 2024年11月14日基于calico网络策略

一、简介

Calico是一个纯三层的协议,为OpenStack虚机和Docker容器提供多主机间通信。Calico不使用重叠网络比如flannel和libnetwork重叠网络驱动,它是一个纯三层的方法,使用虚拟路由代替虚拟交换,每一台虚拟路由通过BGP协议传播可达信息(路由)到剩余数据中心。

为什么Calico网络选择BGP?

参考地址:https://blog.51cto.com/weidawei/2152319

我们在Calico网络中使用BGP去宣告数据终端(end points)路由是因为如下原因:

(1)BGP是一种简单的路由协议

(2)拥有当前行业的最佳实践

(3)唯一能够支撑Calico网络规模的协议

1、原理

如下图所示,描述了从源容器经过源宿主机,经过数据中心的路由,然后到达目的宿主机最后分配到目的容器的过程。

整个过程中始终都是根据iptables规则进行路由转发,并没有进行封包,解包的过程,这和flannel相比效率就会快多了。

2、框架

calico包括如下重要组件:Felix,etcd,BGP Client,BGP Route Reflector。下面分别说明一下这些组件。

(1)Felix:主要负责路由配置以及ACLS规则的配置以及下发,它存在在每个node节点上。

(2)etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;

(3)BGP Client(BIRD), 主要负责把 Felix写入 kernel的路由信息分发到当前 Calico网络,确保 workload间的通信的有效性;

(4)BGPRoute Reflector(BIRD), 大规模部署时使用,摒弃所有节点互联的mesh模式,通过一个或者多个 BGPRoute Reflector 来完成集中式的路由分发;

二、服务搭建

1、环境准备

1)系统环境

主机名

系统

宿主IP

服务

master01

CentOS7.4

172.169.18.210

docker1.13.1

etcd3.2.22

calico2.6.10

node01

CentOS7.4

172.169.18.162

docker1.13.1

etcd3.2.22

calico2.6.10

node02

CentOS7.4

172.169.18.180

docker1.13.1

etcd3.2.22

calico2.6.10

2)暂时关闭防火墙和selinux服务

3)配置hosts,添加如下

# vim /etc/hosts

172.169.18.210 master01

172.169.18.162 node01

172.169.18.180 node02

2、安装docker服务(三个节点)

1)yum安装docker1.13版本

# yum install docker -y

2)修改默认docker0的网卡信息

# vim /etc/docker/daemon.json

#追加如下参数

"bip":"172.169.10.1/24"

其他节点:

node01网络地址:172.169.20.1/24

node01网络地址:172.169.30.1/24

重启docker服务


3、安装etcd服务(在三个节点机上都要安装etcd,构成etcd集群环境

1)yum安装etcd3.2.22版本

# yum install etcd -y

2)修改etcd配置文件

# vim /etc/etcd/etcd.conf

#maser01节点

ETCD_DATA_DIR="/var/lib/etcd/"

ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://127.0.0.1:4001"

ETCD_NAME="master01"

ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_INITIAL_CLUSTER="master01=http://172.169.18.210:2380,node01=http://172.169.18.162:2380,node02=http://172.169.18.180:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

#node01节点

ETCD_DATA_DIR="/var/lib/etcd"

ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://127.0.0.1:4001"

ETCD_NAME="node01"

ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_INITIAL_CLUSTER="master01=http://172.169.18.210:2380,node01=http://172.169.18.162:2380,node02=http://172.169.18.180:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

#node02

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"

ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"

ETCD_NAME="node02"

ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_INITIAL_CLUSTER="master01=http://172.169.18.210:2380,node01=http://172.169.18.162:2380,node02=http://172.169.18.180:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

按如上配置分别启动集群,启动集群后,将会进入集群选举状态,若出现大量超时,则需要检查主机的防火墙是否关闭,或主机之间是否能通过2380端口通信,集群建立后通过以下命令检查集群状态。

3)在任意节点查看集群状态

# etcdctl member list

当关闭master01节点后,选举自动切换到node02上

4)检查集群健康状态(在三个节点中的任意一个上面都可以查看)

# etcdctl cluster-health

到此,etcd集群搭建完毕!!!


4、搭建Calico服务(docker集合采用2.6版本)

备注:新老版本的执行命令有所差异,注意了!!!

Calico实现了一个Docker网络插件,可用于为Docker容器提供路由和高级网络策略。

calico地址:https://github.com/projectcalico/calicoctl/tags

1)下载

# wget -O /usr/local/bin/calicoctl https://github.com/projectcalico/calicoctl/releases/download/v1.6.4/calicoctl

# chmod +x /usr/local/bin/calicoctl

2)配置calicoctl - etcdv2数据存储区

官方配置地址:https://docs.projectcalico.org/v2.6/reference/calicoctl/setup/etcdv2

# mkdir -p /etc/calico

# vim /etc/calico/calicoctl.cfg

# cat /etc/calico/calicoctl.cfg

apiVersion: v1

kind: calicoApiConfig

metadata:

spec:

datastoreType: "etcdv2"

etcdEndpoints: http://172.169.18.210:2379,http://172.169.18.162:2379,http://172.169.18.180:2379

3)帮助信息

# calicoctl -help

启动Calico服务

在Docker环境中Calico服务是做为容器来运行的,使用host的网络配置。所有容器配置使用Calico服务,做为calico节点互相通信。

Calico在每个主机上通过一个自己的container与其他主机或者网络通讯,即calico-node的container,这个container里面包含了Bird路由管理、Felix协议等。

4)在三个节点上都要下载calico的node镜像

(可以先在一个节点上下载镜像,然后将镜像通过docker save导出保存到本地,再将镜像拷贝到其他节点上通过docker load导入,这样对于其他节点来说,比使用docker pull要快)

[root@master01 ~]# docker pull calico/node:v2.6.10

[root@master01 ~]# docker pull calico/node-libnetwork

5.1)启动三个节点的node服务(方法一)

#master01节点(指定版本--node-image=calico/node:v2.6.10

# calicoctl node run --node-image=calico/node:v2.6.10 --ip=172.169.18.210

#node01

# calicoctl node run --node-image=calico/node:v2.6.10 --ip=172.169.18.162

#node02

# calicoctl node run --node-image=calico/node:v2.6.10 --ip=172.169.18.180

5.2)启动三个节点的node服务(方法二)

#创建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

# 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

#calico.env变量文件

# vim /etc/calico/calico.env

ETCD_ENDPOINTS=http://172.169.128.210:2379,http://172.169.18.162:2379,http://172.169.18.180:2379

# 启用ssl/tls时,认证相关文件位置

ETCD_CA_FILE=""

ETCD_CERT_FILE=""

ETCD_KEY_FILE=""

# 留空时默认采用主机hostname作为辨识,所以留空时请确保主机名唯一

CALICO_NODENAME=""

CALICO_NO_DEFAULT_POOLS=""

# 设置路由下一跳,留空时从主机当前端口中自动选择,有参数"autodetect"强制每次启动时间自动检测

CALICO_IP="172.169.18.210"

CALICO_IP6=""

# as number,默认从全局默认设置继承

CALICO_AS=""

# 启用libnetwork drive

CALICO_LIBNETWORK_ENABLED=true

# 路由协议,可选"bird","gobgp","none",默认即"bird", "gobgp"无ipip模式

CALICO_NETWORKING_BACKEND=bird

#启动服务

# systemctl daemon-reload

# systemctl enable calico

# systemctl restart calico

# systemctl status calico

6)查看状态

可以在三个节点上查看calico-node启动情况

# docker ps -a

# ps -ef | grep calico

查看节点状态信息(在三个节点上都可以查看)

# calicoctl node status

5、使用calicoctl创建ipPool

官方参考地址:https://docs.projectcalico.org/v2.6/reference/calicoctl/resources/ippool

在启动别的容器之前,我们需要配置一个IP地址池带有ipip和nat-outgoing选项。所以带有有效配置的容器就可以访问互联网,在每个节点上运行下面的命令:

先查看calico的ip池(任意一个节点上都能查看)

# calicoctl get ipPool -o wide

参数解释:

# 运行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"

1)在任意节点上定义都可以,ipPool属于全局;

[root@master01 ~]# vim new-pool-1.yaml

apiVersion: v1

kind: ipPool

metadata:

cidr: 172.169.10.0/24

spec:

ipip:

enabled: true

mode: cross-subnet

nat-outgoing: true

disabled: false

2)#创建

# calicoctl create -f new-pool-1.yaml

同理继续把后面两个节点的网段添加完成即可,如下如

3)删除默认的ip地址池

# calicoctl delete ipPool 192.168.0.0/16

查看docker三个节点网络

4)容器网络配置

#修改docker配置文件(三节点修改)

# vim /usr/lib/systemd/system/docker.service

添加如下参数:

-H unix:///var/run/docker.sock -H 0.0.0.0:2375 --cluster-store etcd://172.169.18.210:2379,172.169.18.162:2379,172.169.18.180:2379 \

重启服务

# systemctl daemon-reload

# systemctl restart docker

#创建network(任意一个节点创建即可)

# docker network create --driver calico --ipam-driver calico-ipam net1

# docker network ls

5)创建容器测试

docker run --name web1 --privileged -itd --net=net1 centos:7.4.1708 /usr/sbin/init

(1)#查看容器信息

# docker inspect web1

(2)网络节点变化

(3)host节点routing table

# ip route show

(4)容器routing table

# 容器网关"169.254.1.1"是1个预留本地ip地址,通过cali0端口发送到网关;

# calico为简化网络配置,将容器的网关设置为1个固定的本地保留地址,容器内路由规则都是一样的,不需要动态更新;

# 确定下一跳后,容器会查询下一跳"169.254.1.1"的mac地址

# docker exec web1 ip route show

# docker exec web1 ping 114.114.114.114

通过"ip neigh show"可查询arp表(需要触发),这里查询到"169.254.1.1"的mac地址是"7a:b2:59:f7:0c:91",仔细观察会发现此mac地址即host节点网卡"calic255b5bfca1"的mac地址

# docker exec web1 ip neigh show

host节点对应容器的网卡并没有配置ip地址,无论容器发出的arp的请求地址是什么,其直接以自己的mac地址响应即"arp proxy";

# 容器的后续报文目的IP不变,但mac地址变成了宿主机上对应interface的地址,即所有的报文都会发给宿主机,然后宿主机根据ip地址进行转发,此feature是calico默认开启的,可通过如下方式确认:

# cat /proc/sys/net/ipv4/conf/cali7d1d9f06ed8/proxy_arp

(5)在node02节点创建一个容器web2

# docker run --name web2 --privileged -itd --net=net1 centos:7.4.1708 /usr/sbin/init

# docker exec -ti web2 /bin/bash

即可


补充知识点:


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)。



0