乐趣区

关于云计算:开启-Calico-eBPF-数据平面实践

简介

Calico 从 v3.13 开始,集成了 eBPF 数据立体。

对于什么是 eBPF, 以及 Calico 为什么引入了 eBPF , 并不是本篇文章的重点,感兴趣的敌人能够自行浏览相干文档。

相比于 Calico 的默认基于 iptables 数据立体,eBPF 具备更高的吞吐量以外,还具备 source IP preservation 这个性能。

在 K8s 中通常都是间接或者间接以 NodePort 形式对外裸露接口的。而对于 K8s 这个分布式集群来讲,通常状况下,客户端连贯 Node Port 端口的节点和负责响应申请的后端业务 Pod 所在的节点不是同一个节点,为了买通整个数据链路,就不可避免的引入了 SNAT。然而这样显然也会带来一个副作用,即业务 Pod 在收到 Packet 当前,其 SRC IP 曾经不再是客户端的理论 IP(被伪装成节点的内网 IP)。另一方面,对于一些业务利用来讲,获取客户端 IP 是一个实实在在的刚需。比方:业务利用须要通过客户端 IP 来获取客户登陆的 geo 信息。

目前 K8s 次要是通过设置 externaltrafficpolicy 来躲避这个问题的,然而这个计划自身并不能齐全令人满意。Calico 从 v3.13 开始通过集成 eBPF 优雅地解决了这个问题。

在本篇文章中,咱们将首先演示通过 KubeKey 创立一个规范的 K8s 集群,并切换数据立体到 eBPF,最初基于该数据立体做一个简略的演示。

前提条件

较新的内核,个别 v4.18+ 即可。

笔者的测试集群:

部署 K8s 集群

Kubekey 默认的 CNI 插件为 Calico(ipip 模式)。这里为了部署不便,间接应用 KubeKey 部署了一个全新的 K8s 集群,版本为 v1.18.6。KubeKey 的具体用法参见文档。

切换 Calico 数据立体

Calico 反对多种数据立体,通过批改配置能够不便地进行切换,详细信息能够参见官网文档。

次要分为以下几步:

  1. 确认 BPF 文件系统曾经挂载:
mount | grep "/sys/fs/bpf"

如果能看到以下信息,则代表 BPF 文件系统曾经挂载:

  1. 创立 Calico 配置文件:
  • 首先获取 ks-apiserver endpoints 信息:
kubectl get endpoints kubernetes -o wide
  • 因为 KubeKey 是通过 manifest 形式装置的 Calico,这里咱们只须要创立一个 cm 即可:
kind: ConfigMap
apiVersion: v1
metadata:
  name: kubernetes-services-endpoint
  namespace: kube-system
data:
  KUBERNETES_SERVICE_HOST: "<API server host>"
  KUBERNETES_SERVICE_PORT: "<API server port>"
  • 重启 Calico pods,并期待 Calico Pod 从新变为 Running 状态
kubectl delete pod -n kube-system -l k8s-app=calico-node
kubectl delete pod -n kube-system -l k8s-app=calico-kube-controllers
  • 敞开 kube-proxy
kubectl patch ds -n kube-system kube-proxy -p '{"spec":{"template":{"spec":{"nodeSelector":{"non-calico":"true"}}}}}'
  • 开启 eBPF 模式
calicoctl patch felixconfiguration default --patch='{"spec": {"bpfEnabled": true}}'
  • 因为咱们须要保留客户端 IP,所以须要开启 DSR 模式。
calicoctl patch felixconfiguration default --patch='{"spec": {"bpfExternalServiceMode":"DSR"}}'

至此,Calico 的整个网络环境曾经配置结束。

体验

为了验证 Calico 切换到 eBPF 数据立体当前,后端的确能够拿到客户端的实在 IP,上面咱们会在集群中部署一个 Nginx 服务,并通过 nodeport 形式裸露接口。

创立 Nginx 实例并裸露内部接口:

master:~$ kubectl apply -f - <<EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      nodePort: 30604
EOF 

期待 Pod 变为 Running 状态:

内部调用 Nginx 服务:

curl http://<external-ip>:30604

查问 Nginx 日志,查看 client IP:

留神:如果集群自身部署在云平台环境中,如果节点位于 VPC 网络当中,须要设置相应的端口转发规定,并开启相应的防火墙端口。

本文由博客一文多发平台 OpenWrite 公布!

退出移动版