【k8s】从Flannel到Calico:网络插件升级与精细化网络策略实战
1. 为什么需要从Flannel迁移到Calico?
很多刚开始接触Kubernetes的同学都会选择Flannel作为默认网络插件,因为它简单易用,开箱即用。我在早期搭建测试环境时也经常用Flannel,毕竟一条kubectl apply -f kube-flannel.yml命令就能搞定整个集群的网络连通。但随着业务规模扩大,特别是需要实现多租户隔离时,Flannel的局限性就逐渐暴露出来了。
Flannel最大的问题是缺乏细粒度的网络策略控制。它就像小区里的公共走廊,所有住户(Pod)都可以自由串门。这在生产环境是极其危险的,想象一下你的数据库Pod可以被任意业务Pod访问,甚至被恶意攻击者利用漏洞入侵。我曾经就遇到过因为Flannel默认全通策略导致的数据库被误删事故,从那以后就开始研究更安全的网络方案。
Calico则像给每个房间装了智能门锁,你可以精确控制谁能进谁不能进。它通过Linux内核的iptables/ebtables实现网络策略,性能损耗几乎可以忽略不计。实测下来,在相同硬件环境下,Calico的网络延迟比Flannel低15%-20%,这对于高频交易类应用非常关键。
另一个重要区别是网络模型。Flannel使用Overlay网络(默认VXLAN模式),所有数据包都要经过封装/解封装;而Calico默认是纯三层路由(BGP模式),就像快递直接按门牌号送货,不需要额外包装。这带来的性能优势在大流量场景下尤为明显,我们有个视频处理集群在切换到Calico后,网络吞吐量直接提升了30%。
2. 迁移前的准备工作
2.1 环境检查与兼容性验证
在动手迁移前,建议先用kubectl get nodes -o wide检查所有节点状态,确保没有NotReady节点。我遇到过因为节点磁盘压力导致网络插件安装失败的情况,后来通过kubectl describe node发现是磁盘空间不足。
关键检查项:
- Kubernetes版本(建议1.16+)
- 节点操作系统(Calico对内核版本有要求)
- 现有Pod的网络连接状态
- 关键业务服务的Endpoint是否正常
2.2 安全清理Flannel残留配置
直接删除Flannel可能会导致网络中断,正确的操作顺序应该是:
# 先删除DaemonSet kubectl delete -f kube-flannel.yml # 清理CNI配置(所有节点执行) mv /etc/cni/net.d/10-flannel.conflist /tmp/ # 检查iptables规则(可选) iptables-save | grep flannel特别注意:如果有Pod正在使用Flannel创建的虚拟网卡,强制删除可能导致这些Pod网络异常。建议在业务低峰期操作,或者先通过kubectl drain排空节点。
3. Calico的安装与核心配置
3.1 两种部署模式详解
从官网下载的calico.yaml默认使用IPIP模式,这对新手最友好。但生产环境我更推荐BGP模式,它需要额外的路由配置:
# 修改calico.yaml关键参数 - name: CALICO_IPV4POOL_IPIP value: "Never" # 禁用IPIP - name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16" # 需与kube-controller-manager的--cluster-cidr一致如果集群跨多个子网(比如不同可用区),还需要配置BGP对等:
cat <<EOF | kubectl apply -f - apiVersion: projectcalico.org/v3 kind: BGPPeer metadata: name: peer-to-route-reflector spec: nodeSelector: !has(i-am-route-reflector) peerSelector: has(i-am-route-reflector) EOF3.2 关键组件解析
安装完成后,用kubectl get pods -n kube-system会看到这些核心组件:
Felix:每个节点上的守护进程,负责配置路由和ACL规则。出问题时可以查看它的日志:
kubectl logs -n kube-system -l k8s-app=calico-node -c calico-nodeBIRD:BGP路由守护进程。通过
calicoctl node status可以查看路由分发状态:# 需要先安装calicoctl curl -L https://github.com/projectcalico/calico/releases/download/v3.21.4/calicoctl-linux-amd64 -o calicoctl chmod +x calicoctl ./calicoctl node statusTypha:大规模集群中用于降低API Server负载的组件。当节点超过50个时建议启用。
4. 网络策略实战进阶
4.1 基础隔离:禁止所有入站流量
安全的第一原则是最小化开放权限。这个策略会阻止所有入站连接,相当于给Pod上了默认锁:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all spec: podSelector: {} policyTypes: - Ingress应用后测试方法:
# 启动测试Pod kubectl run tester --image=alpine -- sleep 3600 # 尝试ping其他Pod(应该失败) kubectl exec tester -- ping <target-pod-ip>4.2 精确控制:基于标签的访问
给前端Pod开放数据库访问权限的典型场景:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-db spec: podSelector: matchLabels: app: mysql ingress: - from: - podSelector: matchLabels: tier: frontend ports: - protocol: TCP port: 3306常见踩坑点:标签选择器是AND逻辑。如果Pod有多个标签,必须在matchLabels中全部指定才能匹配。
4.3 跨命名空间隔离
财务系统的Namespace需要特殊保护:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-cross-ns namespace: finance spec: podSelector: {} ingress: - from: - namespaceSelector: matchLabels: role: trusted配合Namespace标签使用:
kubectl label ns finance role=trusted4.4 出口流量控制
防止数据泄露的重要策略:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: restrict-egress spec: podSelector: matchLabels: sensitive: "true" egress: - to: - ipBlock: cidr: 10.244.0.0/16 # 只允许访问集群内IP - ports: - protocol: UDP port: 53 # 放行DNS5. 生产环境调优经验
5.1 性能优化参数
在calico-node的DaemonSet中添加这些环境变量:
env: - name: FELIX_IPTABLESREFRESHINTERVAL value: "60s" # 降低iptables刷新频率 - name: FELIX_IPV6SUPPORT value: "false" # 禁用IPv6减少规则数量 - name: FELIX_LOGSEVERITYSCREEN value: "error" # 减少日志量5.2 监控与排错
推荐使用这些Prometheus指标:
felix_active_local_endpoints:节点上健康的Pod数量felix_ipset_calls:规则更新频率bgp_session_up:BGP会话状态
关键日志分析命令:
# 查看拒绝的连接 kubectl logs -n kube-system -l k8s-app=calico-node | grep "Dropped packet"5.3 高可用部署
对于关键业务集群,建议部署Route Reflector:
kubectl label node k8s-master-1 i-am-route-reflector=true calicoctl patch node k8s-master-1 -p '{"spec":{"routeReflectorClusterID":"224.0.0.1"}}'6. 迁移后的验证清单
基础连通性测试:
kubectl run test-nginx --image=nginx kubectl run test-client --image=busybox --command -- /bin/sh -c "while true; do wget -q -O- http://test-nginx; sleep 1; done"网络策略生效验证:
# 应该被拒绝 kubectl exec test-client -- ping <db-pod-ip> # 应该成功 kubectl exec test-client -- wget -q -O- http://frontend-service性能基准测试:
# 安装qperf工具 kubectl run qperf-server --image=arjanschaaf/qperf kubectl run qperf-client --image=arjanschaaf/qperf --command -- /bin/sh -c "sleep 10; qperf <server-ip> tcp_bw tcp_lat"
迁移完成后,建议持续监控网络延迟和丢包率至少24小时。我们曾经遇到过BGP路由收敛慢导致的间歇性连接问题,后来通过调整BGP_KEEPALIVETIME参数解决。
