本文的主要内容是对Calico的部署以及简单使用的总结,相关的详细概念还请参考官网。(https://www.projectcalico.org)
一、Calico简述
Calico是一个纯三层的方案,为虚机及容器提供多主机间通信,没有使用重叠网络驱动,采用虚拟路由代替虚拟交换,每一台虚拟路由器通过BGP协议传播可达信息到其他虚拟或物理路由器。
Calico架构图如图所示(网上找的,Calico的官网连结构图都没有)。
从图中可以看出Calico的主要组件有:
- Felix:Calico agent,运行在每台workload节点,主要负责配置路由及ACLs等信息,确保endpoint的连通状态;
- Etcd:分布式kv存储,主要负责网络元数据一致性,确保Calico网络状态的准确性;
- BGP Client(BIRD):主要负责把Felix写入kernel的路由信息分发到当前Calico网络,确保workload间的通信的有效性;
- BGP Route Reflector(BIRD):一般在大规模部署时采用,与所有节点互联的mesh模式不同,通过一个或多个BGP Route Reflector来完成集中式的路由分发
二、实验环境
- 3台阿里云的虚机
- 配置kubernetes集群,master,node1,node2
- Calico对应版本3.8
k8s集群搭建不在赘述,Calico部署请参照官网(https://www.projectcalico.org),并部署calicoctl。
三、Calico的部署方式
Calico的部署方式有两种,第一种是IP in IP模式,第二种是BGP模式。通过设置calico.yaml(官网下载)中CALICO_IPV4POOL_IPIP的值来实现。
通过实验发现:
- 阿里云不支持Calico的BGP模式
- AWS支持Calico的BGP模式,但是要把EC2的联网-更改源/目标,检查关闭
四、Calico IPAM的形式
- Using host-local IPAM
将IPAM的type设置为host-local
{
"name": "any_name",
"cniVersion": "0.1.0",
"type": "calico",
"kubernetes": {
"kubeconfig": "/path/to/kubeconfig",
"node_name": "node-name-in-k8s
},
"ipam": {
"type": "host-local",
"ranges": [
[
{ "subnet": "usePodCidr" }
],
[
{ "subnet": "2001:db8::/96" }
]
],
"routes": [
{ "dst": "0.0.0.0/0" },
{ "dst": "2001:db8::/96" }
]
}
}
- Using Kubernetes annotations
基于每个命名空间或每个pod指定IP池
cni.projectcalico.org/ipv4pools:
annotations:
"cni.projectcalico.org/ipv4pools": "[\"default-ipv4-ippool\"]"
cni.projectcalico.org/ipv6pools:
annotations:
"cni.projectcalico.org/ipv6pools": "[\"2001:db8::1/120\"]"
请求特定的IP地址
cni.projectcalico.org/ipAddrs:
annotations:
"cni.projectcalico.org/ipAddrs": "[\"192.168.0.1\"]"
cni.projectcalico.org/ipAddrsNoIpam:
annotations:
"cni.projectcalico.org/ipAddrsNoIpam": "[\"10.0.0.1\"]"
申请浮动IP
annotations:
"cni.projectcalico.org/floatingIPs": "[\"10.0.0.1\"]"
Using IP pools node selectors
使用IP pools的nodeSelector相关实例介绍
- namespace绑定IPPool
(1)创建IPPool
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: external-pool
spec:
cidr: 172.16.0.0/26
blockSize: 29
ipipMode: Always
natOutgoing: true
---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: internal-pool
spec:
cidr: 192.169.0.0/24
blockSize: 29
ipipMode: Always
natOutgoing: true
calicoctl apply -f pools.yaml
(2)将IPPool绑定到对应的namespace
kubectl create namespace external-ns
kubectl create namespace internal-ns
kubectl annotate namespace external-ns "cni.projectcalico.org/ipv4pools"=‘[“external-pool"]’
kubectl annotate namespace internal-ns "cni.projectcalico.org/ipv4pools"=‘[“internal-pool"]’
(3)创建namespace下的pod进行验证
kubectl run nginx --image nginx --namespace external-ns --replicas 3
kubectl run nginx --image nginx --namespace internal-ns --replicas 3
- node绑定IPPool
(1)删除默认ippool
calicoctl delete ippools default-ipv4-ippool
(2)为node添加label
kubectl label nodes master rack=0
kubectl label nodes node1 rack=0
kubectl label nodes node2 rack=1
(3)创建ippool
calicoctl create -f -<
(4)部署应用并查看服务IP
kubectl run nginx --image nginx --replicas 5
- pod 绑定IPPool
(1)创建ippool
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: my.ippool-1
spec:
cidr: 10.1.0.0/16
ipipMode: CrossSubnet
natOutgoing: true
nodeSelector: all()
(2)在pod的yaml文件中添加ippool
annotations:
"cni.projectcalico.org/ipv4pools": "[\"your-ippool\"]"
五、BGP相关介绍
BGP协议这里不在说明,感兴趣的可以自己查看。这里介绍一些Calico与BGP相关的知识。
BGPPeer的方式:
- Node-to-Node mesh:个人理解是每个节点之间都存在路由
- Route Reflector (路由放射):将Calico的节点设置为路由反射器,减少节点之间的路由。
- 个人理解设置一个节点作为全局的BGP peer。
- 这种方式貌似和机架相关。
上面标红的两种方式没有特别理解,还请了解大佬多多指教,谢谢。
RR模式的实现
(1)配置禁用全局全连接(node-to-node mesh)
$ cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 64512
EOF
(2)配置BGP node 与 Route Reflector的连接建立规则,通过BGPPeer 资源告诉其他的calico node与反射路由节点建立连接
cat << EOF | calicoctl create -f -
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
name: peer-to-rrs
spec:
# 规则1:普通 bgp node 与 rr 建立连接
nodeSelector: !has(i-am-a-route-reflector)
peerSelector: has(i-am-a-route-reflector)
(3)配置Route Reflector节点
#(1).先导出 node node1 的配置,准备修改
$ calicoctl get node master -o yaml > rr0.yaml
apiVersion: projectcalico.org/v3
kind: Node
metadata:
creationTimestamp: null
name: master
spec:
bgp:
ipv4Address: 172.17.201.143/20
ipv4IPIPTunnelAddr: 10.244.219.64
# (2).修改上述 rr01.yml 的配置如下
apiVersion: projectcalico.org/v3
kind: Node
metadata:
name: master
labels:
# 设置标签
i-am-a-route-reflector: true
spec:
bgp:
ipv4Address: 172.17.201.143/20
ipv4IPIPTunnelAddr: 10.244.219.64
# 设置集群ID
routeReflectorClusterID: 224.0.0.1
# (3).应用修改后的 rr node 配置
$ calicoctl apply -f rr01.yml
(4)对比路由表
六、Network Policy
Calico与其他虚拟网络的最大不同是引入了Network Policy,Calico的Netork Policy 包括GlobalNetworkPolicy,GlobalNetWorkSet,NetworkPolicy,NetworkSet,HostEndPoint,WorkloadEndPoint等内容,详细信息请参考官方网站。
下面主要介绍一些简单的应用:
首先通过NodePort的方式搭建Webserver服务,通过公网IP加NodePort访问返回webserver信息。
- 通过GlobalNetworkPolicy限制访问
(1)为node1和node2添加hostendpoint
Node1:
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: node1-eth0
labels:
type: host-endpoint
role: node1-ingress
spec:
interfaceName: eth0
node: node1
Node2:
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: node2-eth0
labels:
type: host-endpoint
role: node2-ingress
spec:
interfaceName: eth0
node: node2
(2)创建Global network policy
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: drop-ingress
spec:
order: 20
preDNAT: true
applyOnForward: true
ingress:
- action: Deny
selector: role == 'node1-ingress'
(3)通过nodeport访问,可以发现,node1提供的服务无法访问,node2可以访问
- 通过NetworkPolicy限制访问
(1)设置NetworkPolicy禁止所有访问
Deny.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: deny-wep-webserver
namespace: webserver
spec:
types:
- Ingress
ingress:
- action: Deny
(2)创建NetworkPolicy允许部分网段访问
Allow.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-nets-wep-webserver
namespace: webserver
spec:
types:
- Ingress
ingress:
- action: Allow
source:
nets:
- 10.244.166.0/24
- 通过使用NetworkSet限制访问
(1)创建NetworkPolicy禁止所有方式访问webserver
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: deny-wep-webserver
namespace: webserver
spec:
selector: run == 'webserver'
types:
- Ingress
ingress:
- action: Deny
(2)创建NetworkSet,在其中加入可以访问webserver的nets范围
apiVersion: projectcalico.org/v3
kind: NetworkSet
metadata:
name: node1-nts
namespace: webserver
labels:
role: db
spec:
nets:
- 10.244.166.0/24
(3)创建NetworkPolicy允许NetworkSet中的网段访问webserver
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: access-wep-webserver
namespace: webserver
spec:
selector: run == 'webserver'
types:
- Ingress
ingress:
- action: Allow
source:
selector: role == 'db'
End
以上是近期对Calico的一些总结,只是针对Calico的功能进行了尝试,哪里存在问题还请指正。接下来还要对Calico进行深一步的了解。