# 安装
[root@calico ~]# curl -sL  https://github.com/projectcalico/calicoctl/releases/download/v3.13.2/calicoctl -o /usr/bin/calicoctl
[root@calico ~]# chmod +x /usr/bin/calicoctl

# 默认加载 /etc/calico/calicoctl.cfg 读取配置 (其中指定了datastoreType与etcdEndpoints等重要参数)
[root@calico ~]# cat > /etc/calico/calicoctl.cfg <<'EOF'
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "kubernetes"       # https://docs.projectcalico.org/getting-started/calicoctl/configure/kdd
  kubeconfig: "/root/.kube/config"
  # datastoreType: "etcdv3"         # https://docs.projectcalico.org/getting-started/calicoctl/configure/etcd
  # etcdEndpoints: "http://etcd1:2379,http://etcd2:2379"
  # etcdKeyFile: /etc/calico/key.pem
  # etcdCertFile: /etc/calico/cert.pem
  # etcdCACertFile: /etc/calico/ca.pem
EOF

# 查看 BGP Peer
[root@calico ~]# calicoctl get bgppeer
......

# 收集诊断
[root@calico ~]# calicoctl node diags
......

# 查看所有的BGP节点,若携带右侧参数则能输出AS号,一个编号就是一个自治系统
[root@calico ~]# calicoctl get nodes [--output=wide]
NAME         
k8s-master
k8s-node1    
k8s-node2

[root@calico ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 172.31.40.217 | node-to-node mesh | up    | 17:38:47 | Established |  # node-to-node mesh 网格的形式
| 172.31.40.30  | node-to-node mesh | up    | 17:40:09 | Established |  # 这种形式是个全互联的模式
| 172.31.45.29  | node-to-node mesh | up    | 17:40:20 | Established |
| 172.31.37.123 | node-to-node mesh | up    | 17:40:29 | Established |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

# 查看IP池相关信息 ...
[root@calico ~]# calicoctl get ipPool -o yaml [-o wide]
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: 2019-04-28T08:53:12Z
    name: default-ipv4-ippool
    resourceVersion: "1799"
    uid: 0df17422-6993-11e9-bde3-005056918222
  spec:
    blockSize: 26
    cidr: 192.168.0.0/16    # 
    ipipMode: Always        # IPINIP模式
    natOutgoing: true       # 允许工作负载访问Internet,ref:https://docs.projectcalico.org/networking/workloads-outside-cluster
    nodeSelector: all()
kind: IPPoolList
metadata:
  ……

基于 calicoctl 操作的BGP配置YAML资源: BGPConfiguration

kubectl apply -f - <<'EOF'
apiVersion: projectcalico.org/v3
kind: BGPConfiguration          # https://docs.projectcalico.org/reference/resources/bgpconfig
metadata:
  name: default
spec:
  logSeverityScreen: Info       # 全局日志级别
  nodeToNodeMeshEnabled: true   # 使用完整的BGP节点到节点网格
  asNumber: 63400
  serviceClusterIPs:            # Kubernetes服务IP的CIDR块将通过BGP通告(通过BGP在集群外部发布Cluster_IP)
  - cidr: 10.96.0.0/12
  serviceExternalIPs:
  - cidr: 104.244.42.129/32     # Kubernetes服务的扩展IP的CIDR块将通过BGP通告,仅当服务外部IP位于列表之一时才进行公告
  - cidr: 172.217.3.0/24
EOF

公告Kubernetes服务IP

# ref: https://docs.projectcalico.org/networking/advertise-service-ips
# 通常服务IP仅在群集内可达,因此对该服务的外部访问需要专用的负载均衡器或入口控制器。如果服务IP无法路由则可使用其外部IP访问该服务
# 就像通过BGP发布POD IP一样,也支持通过BGP在集群外发布Kubernetes的服务IP,这避免了需要专用的负载平衡器
# 由于Calico使用BGP因此可通过将kubernetes的服务IP通告到BGP网络中来将外部流量直接路由到Kubernetes服务! ...
# 如果Calico部署为与群集外的BGP路由器对等,则这些路由器及这些路由器传播到的任何其他上游位置将能够将流量发送到Kubernetes服务群集IP并最终路由到Endpoint中
# 此功能还支持群集中各节点之间的等价多路径(ECMP)负载平衡,以及在需要更多控制时为本地服务保留源IP地址

# 群集的范围可以从传递给Kubernetes API服务器的选项 "--service-cluster-ip-range" 查看
# 检查是否具有默认的BGPConfiguration: (即查看BGP网络的配置情况)
[root@calico ~]# calicoctl get bgpconfig default
# 根据以上结果更新或创建BGPConfiguration
# 使用以下命令创建默认的BGPConfiguration。在serviceClusterIPs字段中添加CIDR块,其中包括要宣告的群集IP
[root@calico ~]# calicoctl create -f - <<'EOF'
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  serviceClusterIPs:            # Kubernetes服务IP的CIDR块将通过BGP通告(通过BGP在集群外部发布Kubernetes的服务IP)
  - cidr: 10.96.0.0/16
  - cidr: fd00:1234::/112
EOF

IP - calico-ipam

# Calico提供了自己的CNI标准的IPAM类型的插件 calico-ipam,该插件旨在与Calico很好的配合使用,其提供许多功能 ...
# calico-ipam 使用Calico的 IP pool resource 控制如何为集群中的POD分配IP (它是Calico安装时默认使用的CNI插件)
# 默认情况下Calico对整个 Kubernetes Pod CIDR 使用单个IP池,但是它可以将 Pod CIDR 划分为多个池 ...
# 可以在 namespaces 中将单独的IP池分配给特定的节点、团队、用户、应用程序 ...

You can control which pools Calico uses for each pod using
#   1.node selectors
#   2.an annotation on the pod’s namespace
#   3.an annotation on the pod

# ------------------------------------------------- IP Pool - Block on Node 

# 在 calico-ipam 中IP池被细分为多个Block,这些经划分后的小Block与群集中的特定节点关联 ...
# 集群中每个节点可以具有一或多个与其关联的Block,Calico会根据集群中节点和Pod数量的增减自动创建和销毁它们 ...
# Block使Calico能有效地聚合分配给同一节点的Pod的地址,从而减小路由表的大小
# 默认情况下它会尝试从关联的Block中分配IP,并在必要时创建新的Block ...
# Calico还可以为不与该节点关联的Block内的IP分配到该节点内的Pod,这允许不与该节点关联的IP分配给其Pod!
# 默认创建的块可容纳64个地址 (掩码为/26),不过它是可以自定义的 ....

# ------------------------------------------------- IP Pool - Change Block Size

# 注: 该段说明仅针对在部署Calico时进行修改,若在生产运行过程中修改需再去看官方文档 ....
# 因为 blockSize 在Calico安装后无法直接编辑生效,因此最好在安装前更改以最大程度地减少对Pod连接的破坏 ...
# 以下为 Calico 的YAML部署清单 ...
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
  pec:
   calicoNetwork:             # Configures Calico networking.
    ipPools:                  # Note: The ipPools section cannot be modified post-install.
    - blockSize: 26           # 修改此处掩码即可 ...
      cidr: 10.48.0.0/21      # CIDR ...
      encapsulation: IPIP
      natOutgoing: Enabled
      nodeSelector: all()
    - blockSize: 122          # 针对IPv6 ...
      cidr: 2001::00/64 
      encapsulation: None 
      natOutgoing: Enabled 
      nodeSelector: all()

# ------------------------------------------------- 为POD申请浮动IP (Based on the annotation)

# 首先确保 calico-ipam 插件处于使用状态: /etc/cni/net.d/10-calico.conflist
# 使用浮动IP的前提是Calico的CNI配置文件中启用如下Json属性 (可通过kube-system空间中的configmap修改) ...
...
"feature_control": {
     "floating_ips": true
},
...

# ref: https://docs.projectcalico.org/networking/add-floating-ip
# 与集群服务的概念类似,浮动IP提供稳定的地址来访问某些网络服务,且该网络服务可能在不同时间由不同的POD使用 ...
# 与集群服务不同的是浮动IP一次仅位于一个POD之中,因此不能用于负载平衡 ...
# 浮动IP是分配给某节点的其他IP,之所以称其浮动是因为其能够在群集中移动并在不同的时间作用于不同的节点之中
# 而POD本身通常不知道浮动IP,因为节点在将数据包传送到POD之前使用网络地址转换 (NAT) 将浮动IP改成了POD的实际IP

# Configure a pod to use a floating IP ...
# 对POD使用名为 cni.projectcalico.org/floatingIPs 的key进行注释
annotations:
    "cni.projectcalico.org/floatingIPs": "[\"10.0.0.1\"]"    # 浮动IP必须在已配置IP池的范围内 ...
  # "cni.projectcalico.org/ipAddrsNoIpam": "[\"10.0.0.1\"]"  # 不调用calico-ipam

# ------------------------------------------------- 为POD申请绑定IP  (Based on the annotation)

# 某些应用需要使用稳定的IP,或者想在外部的DNS中创建直接指向POD的记录时就需要静态IP了 ^-^
# 集群中POD地址的CIDR是在部署时预先定义的,并由各种 Kubernetes 组件用来确定IP是否属于POD ...
# 例如 kube-proxy 对待流量的方式取决于此IP是否属于这个CIDR ...
# 因此要绑定的这个静态IP也必须在POD的CIDR地址池中且当前未被使用,使用该功能之前需确认calico使用的CNI插件是 calico-ipam ...

# Configure a pod to use a static IP
# 对POD使用名为 cni.projectcalico.org/ipAddrs 的key进行注释 (每个POD仅支持绑定1个)
annotations:
    "cni.projectcalico.org/ipAddrs": "[\"192.168.0.1\"]"

# ------------------------------------------------- 为特定标签的节点设置分配的IP池(基于注释进行拓扑方式的地址分配)

# 如果在不同区域或机架中拥有工作负载,则可能希望它们从同一个IP池中获取IP地址 ...
# 该策略对于减少网络中所需的路由数量或满足外部防火墙设备或策略所施加的要求很有用
# 此时可使用带有节点标签和节点选择器的IP池资源来实现此需求 ...
# 注意: calico-ipam不会将IP重新分配给正在运行的POD,因此必须重建它们,官方建议在投入生产前或在维护期间进行此操作 ...

# 查看默认的IP池与节点的关联信息 .....
[root@calico ~]# calicoctl get ippool -o wide
NAME                  CIDR             NAT    IPIPMODE   DISABLED   SELECTOR
default-ipv4-ippool   192.168.0.0/16   true   Always     false      all()       # 此处的 all() 配置了所有节点 

# 由于 default-ipv4-ippoolIP 池已经存在并占了整个/16,因此必须首先删除
[root@calico ~]# calicoctl delete ippools default-ipv4-ippool

# 用 zone=west 标签标记节点 (节点仅从与之关联的IP池中分配POD地址,为避免POD无法获取IP,需确保至少由一个IP池选择所有节点)
kubectl label nodes kube-node-1 zone=west
kubectl label nodes kube-node-2 zone=west

# Assign IP addresses based on topology ...
kubectl apply -f - <<'EOF'
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
   name: rack-1-ippool
spec:
   cidr: 192.168.0.0/24                 # 用于分配的IP池
   ipipMode: Always                     # 可选值: Always、CrossSubnet、Never	
   natOutgoing: true                    # 允许在托管每个POD的计算节点上本地执行出站NAT ...
   nodeSelector: zone == "west"         # 该池仅用于标签为 zone=west 的节点分配IP
EOF

# 查看IPAM的IP地址池
[root@calico ~]# calicoctl get ippool -o wide
NAME                  CIDR             NAT    IPIPMODE   DISABLED   SELECTOR
rack-1-ippool         192.168.0.0/24   true   Always     false      zone == "west"
rack-2-ippool         192.168.1.0/24   true   Always     false      zone == "west"

# :-) ...

# ------------------------------------------------- 指定命名空间可使用的IP池 (Based on the annotation)

# IP池是Calico从集群的 POD CIDR 中分配的地址范围,默认情况下Calico为整个集群创建了一个IP池 ...
# 用户可以将其优化来实现将这个默认的地址池再细分为若干个池子,然后使用节点选择器或其他对象的选择器如命名空间来进行池子的分配 ...

# 创建地址池 (https://docs.projectcalico.org/archive/v3.19/reference/resources/ippool)
kubectl apply -f - <<'EOF'
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: example                         # IP池的名称 ...
spec:
  cidr: 172.16.0.0/26                   # kubernetes Cluster POD CIDR
  blockSize: 29                         # Mask (Pool range) ...
  ipipMode: Always                      # 可选值: Always、CrossSubnet(跨子网)、Never(禁用)
  natOutgoing: true
# nodeSelector: all()                   # 这要注释 :-)
# ---
# apiVersion: projectcalico.org/v3
# kind: IPPool
# metadata:
#   name: internal-pool
# spec:
#   ......
EOF

# 增加命名空间的注释 (限制名称空间中所有Pod使用的IP地址范围),值为IP池的名称
annotations:
    "cni.projectcalico.org/ipv4pools": "[\"example\",\"pool_2...\"]"    # IPv4
  # "cni.projectcalico.org/ipv6pools": "[\"2001:db8::1/120\"]"          # IPv6

# 若Pod和Pod所处的命名空间都具有注释则Pod的注释优先 ...

Calico 使用 BGP Route Reflector (非全互联模型 RR)

# 使用BGP路由反射器来减少每个节点上使用的BGP对等体的数量
# ref: https://docs.projectcalico.org/networking/bgp

# Calico的默认行为是在每个节点彼此对等的情况下创建完整的内部BGP (iBGP) 连接 (当集群小于100个节点时是可以的) ...
# 可将集群中的个别节点配置为路由反射器的角色,为此这些特殊的反射节点必须具有群集ID,此ID通常是未使用的IPv4地址 ...
# 注: 可能会导致在重配置过程中短暂失去Pod网络连接,官方建议在维护时段进行此类更改 :-(

# 必须先禁用默认的节点到节点的 BGP Mesh 才能启用其他BGP拓扑 (禁用全网状) ...
# 注意: 若默认BGP配置资源不存在则需首先创建: https://docs.projectcalico.org/reference/resources/bgpconfig 
calicoctl patch bgpconfiguration default -p '{"spec": {"nodeToNodeMeshEnabled": false}}'

# 创建全局BGP对等体
# 全局BGP对等体适用于群集中的所有节点 (若生产的网络拓扑包括与部署中的每个Calico节点与其建立对等的关系时相当有用)
# 下例创建了全局的BGP对等体,该对等体将集群中的每个节点配置为与AS号为64567的BGP路由与 192.20.30.40 进行对等 ...
kubectl apply -f - <<'EOF'
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: my-global-peer
spec:
  peerIP: 192.20.30.40      # ...
  asNumber: 64567           # AS Number ...
EOF

# 配置节点充当路由反射器 
# 要用作路由反射器的每个节点必须具有群集ID,它通常是未使用的IPv4地址 ...
# 运行以下命令将节点配置为集群ID为 244.0.0.1 的路由反射器:
calicoctl patch node RR-NODE -p '{"spec": {"bgp": {"routeReflectorClusterID": "244.0.0.1"}}}'

# 标记该节点以表明它是路由反射器从而允许BGPPeer资源选择它
kubectl label node RR-NODE route-reflector=true

# 然后再使用标签选择器将路由反射器节点与其他非路由反射器节点配置为对等:
kubectl apply -f - <<'EOF'
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: peer-with-route-reflectors
spec:
  nodeSelector: all()
  peerSelector: route-reflector == 'true'
EOF

# 查看当前节点的BGP对等状态,这对确认配置是否按预期运行很有用 ...
# 该命令与本地Calico代理通信,因此必须在要查看其状态的节点上执行它 ...
calicoctl node status

修改Calico中BGP默认的AS号

# ------------------------------------------------- 更改默认的全局AS编号 

# 除非指定每个节点的AS否则所有Calico节点都使用编号为 64512 的自治系统
# 可通过修改默认的 BGPConfiguration 资源来更改所有节点的全局默认值,以下命令将全局默认AS编号设为 64513
# 注意: 若默认BGP配置资源不存在则需首先创建: https://docs.projectcalico.org/reference/resources/bgpconfig 
calicoctl patch bgpconfiguration default -p '{"spec": {"asNumber": "64513"}}'

# ------------------------------------------------- 更改特定节点的AS编号

# 可以修改节点对象从而为特定节点配置AS,例如将名为 node-1 的节点更改为AS属于64514
calicoctl patch node node-1 -p '{"spec": {"bgp": {"asNumber": "64514"}}}'

关于 Calico 的节点资源

# 节点资源代表运行Calico的节点,将主机添加到Calico群集时需要创建一个节点资源,其中包含calico/node在主机上运行的实例的配置

apiVersion: projectcalico.org/v3
kind: Node                                  # https://docs.projectcalico.org/reference/resources/node
metadata:                                   #
  name: node-hostname                       # 启动calico/node实例时提供给该实例的名称应与Node资源中配置的名称匹配
spec:                                       # 默认情况下启动calico/node实例时将使用hostname来自动创建节点资源
  bgp:                                      # 
    asNumber: 64512                         # 节点使用的AS编号 
    ipv4Address: 10.244.0.1/24              # The IPv4 address must be specified if BGP is enabled .
    ipv6Address: 2001:db8:85a3::8a2e:370:7334/120
    ipv4IPIPTunnelAddr: 192.168.0.1         # 不应手动更新

复杂网络环境下使用叠加网络

# 整整三天,不学了睡觉...
https://docs.projectcalico.org/networking/vxlan-ipip

Logo

开源、云原生的融合云平台

更多推荐