Cilium 官方文档翻译(9) 替换kube-proxy

本文档介绍了如何在Kubernetes集群中使用Cilium替换kube-proxy,强调了Cilium的eBPF kube-proxy replacement功能。内容涵盖了Cilium的快速安装、验证设置、配置选项,如客户端源IP保留、Maglev一致性哈希、DSR模式、XDP加速等。此外,还详细阐述了Cilium如何处理NodePort、LoadBalancer服务,以及与FHRP和VPC的集成。最后,文档讨论了Cilium的混合模式、优雅退出、Session Affinity等高级设置,旨在帮助读者全面理解Cilium在无kube-proxy环境下的工作原理和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本指南解释了如何在没有kube-proxy的情况下配置Kubernetes集群,以及如何使用Cilium完全替换它。为了简单起见,我们将使用kubeadm引导集群。
有关安装kubeadm的帮助和更多配置选项,请参阅kubeadm官方文档

Cilium的kubeProxyReplacement依赖于socket LB功能,这需要v4.19.57、v5.1.16、v5.2.0或更高版本的Linux内核。Linux内核v5.3和v5.8添加了Cilium可以用来进一步优化kube代理替换实现的其他功能。
注意,v5.0.x已经处于EOL阶段且没有运行kube-proxy替换所需的修复程序
在这里插入图片描述

快速开始

通过kubeadm init初始化控制平面节点,并跳过kube-proxy插件的安装:

根据您使用的CRI实现,您可能需要在kubeadm init…命令中使用--cri-socket选项定制CRI。例如:如果您使用的是Docker CRI,您将使用--cri-socket unix:///var/run/cri-dockerd.sock

kubeadm init --skip-phases=addon/kube-proxy

然后,通过指定控制平面节点IP地址和kubeadm init返回的令牌来加入工作节点(对于本教程,至少要向集群添加一个工作节点):

kubeadm join <..>

如果您有多个网络接口,请确保在每个worker上正确设置kubelet的--node-ip。否则,Cilium的kube-proxy 替换可能无法正常工作。您可以通过运行kubectl get nodes-owide来验证这一点,以查看每个节点是否具有分配给每个节点上具有相同名称的设备的InternalIP

对于已经通过DaemonSet安装了kube-proxy的集群,请使用以下命令将kube-proxy其删除。注意:该操作断开现有的服务连接,停止与服务相关的通信,直到安装了cilium替换:

$ kubectl -n kube-system delete ds kube-proxy
$ # Delete the configmap as well to avoid kube-proxy being reinstalled during a Kubeadm upgrade (works only for K8s 1.19 and newer)
$ kubectl -n kube-system delete cm kube-proxy
$ # Run on each node with root permissions:
$ iptables-save | grep -v KUBE | iptables-restore

注意请使用helm3完成本教程的安装操作,helm2是不兼容的。

设置helm仓库:

helm repo add cilium https://helm.cilium.io/

接下来,生成所需的YAML文件并部署它们。重要:请通过kubeadm init报告的kube-apiserver IP地址和端口号确认你设置的 API_SERVER_IPAPI_SERVER_PORT正确(kubeadm默认使用端口6443)。
因为kubeadm init是在没有kube-proxy的情况下直接运行,所以必须要设置这两个环境变量。尽管kubeadm将KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT使用ClusterIP的模式导出到环境变量中。但没有kube-proxy,网络是不通的。因此,需要通过以下配置使cilium了解该信息:

API_SERVER_IP=<your_api_server_ip>
# Kubeadm default is 6443
API_SERVER_PORT=<your_api_server_port>
helm install cilium cilium/cilium --version 1.12.1 \
    --namespace kube-system \
    --set kubeProxyReplacement=strict \
    --set k8sServiceHost=${
   
   API_SERVER_IP} \
    --set k8sServicePort=${
   
   API_SERVER_PORT}

Cilium将自动在默认路径路径/run/cilium/cgroupv2上挂载附加BPF cgroupv2程序所需的cgroup2文件系统。为此,它需要daemonset的init容器挂载主机/proc路径。通过 --set cgroup.autoMount.enabled=false 可禁用自动挂载,并通过使用--set cgroup.hostRoot设置一个已经在主机挂载的cgroup v2文件系统。例如,如果尚未安装,可以通过在主机上运行mount -t cgroup2 none /sys/fs/cgroup命令来安装cgroup v2文件系统,然后早helm安装命令设置参数--set cgroup.hostRoot=/sys/fs/cgroup

helm最终将cilium安装为一个CNI插件,并使用eBPF kube-proxy replacement来实现实现对ClusterIP、NodePort、LoadBalancer类型的Kubernetes服务和具有ExternalIP的服务的处理。此外,eBPF kube-proxy replacement还支持容器的hostPort,因此不再需要使用portmap插件。
最后,验证cilium正确的在集群中安装,并准备好提供网络服务。

$ kubectl -n kube-system get pods -l k8s-app=cilium
NAME                READY     STATUS    RESTARTS   AGE
cilium-fmh8d        1/1       Running   0          10m
cilium-mkcmb        1/1       Running   0          10m

注意,在上述Helm配置中,kubeProxyReplacement已设置为严格(strict)模式。这意味着,如果缺少底层Linux内核支持,Cilium agent将直接退出。
默认情况下,Helm将kubeProxyReplacement设置为disabled,这意味着cilium仅对集群内的ClusterIP服务启用的负载平衡。
Cilium在直接路由和隧道模式中都支持eBPF kube-proxy replacement。

验证设置

在使用上述快速入门指南部署Cilium之后,我们可以首先验证Cilium代理是否以所需模式运行:

$ kubectl -n kube-system exec ds/cilium -- cilium status | grep KubeProxyReplacement
KubeProxyReplacement:   Strict      [eth0 (Direct Routing), eth1]

使用--verbose选项可以查看更多详细信息。

$ kubectl -n kube-system exec ds/cilium -- cilium status --verbose
[...]
KubeProxyReplacement Details:
  Status:                Strict
  Socket LB:             Enabled
  Protocols:             TCP, UDP
  Devices:               eth0 (Direct Routing), eth1
  Mode:                  SNAT
  Backend Selection:     Random
  Session Affinity:      Enabled
  Graceful Termination:  Enabled
  NAT46/64 Support:      Enabled
  XDP Acceleration:      Disabled
  Services:
  - ClusterIP:      Enabled
  - NodePort:       Enabled (Range: 30000-32767)
  - LoadBalancer:   Enabled
  - externalIPs:    Enabled
  - HostPort:       Enabled
[...]

下一步,我们将创建一个Nginx部署。然后,我们将创建一个新的NodePort服务,并验证Cilium是否能正确处理网络服务。
以下yaml用于创建后端Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

验证nginx pod启动并进入running阶段。

$ kubectl get pods -l run=my-nginx -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP             NODE   NOMINATED NODE   READINESS GATES
my-nginx-756fb87568-gmp8c   1/1     Running   0          62m   10.217.0.149   apoc   <none>           <none>
my-nginx-756fb87568-n5scv   1/1     Running   0          62m   10.217.0.107   apoc   <none>           <none>

接下来,为两个pod创建NodePort类型的service。

$ kubectl expose deployment my-nginx --type=NodePort --port=80
service/my-nginx exposed

验证NodePort类型的service是否创建成功。

$ kubectl get svc my-nginx
NAME       TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
my-nginx   NodePort   10.104.239.135   <none>        80:31940/TCP
<think>好的,我现在需要解答用户的问题:当kube-proxy的mode设置为ipvs时,为什么Service的Cluster IP能够被ping通。用户之前已经询问过类似的问题,并且得到了详细的回答,现在需要更深入的解释。 首先,我要回忆一下用户之前的对话。用户之前提供的kubectl get svc的输出显示有一个名为centos-svc的Service,其Cluster IP是10.106.141.104,并且能够通过ping得到响应。用户对此感到困惑,因为通常Cluster IP是虚拟IP,不应直接响应ICMP请求。之前的回答分析了可能的原因,包括网络插件的行为、kube-proxy模式、进程绑定等,并给出了排查步骤。 现在用户的问题更具体,集中在kube-proxy使用IPVS模式时,为什么Cluster IP能ping通。我需要详细解释IPVS模式的工作原理,以及在这种情况下为何Cluster IP会响应ICMP请求。 首先,我需要确认kube-proxy在IPVS模式下的行为。kube-proxy负责将Service的请求转发到后端Pod。在iptables模式下,它使用iptables规则进行流量转发,而IPVS模式则利用内核的IPVS(IP Virtual Server)功能,后者更高效且支持更多的负载均衡算法。 在IPVS模式下,kube-proxy会为每个Service创建IPVS虚拟服务器,并将虚拟IP(即Cluster IP)绑定到节点的网络接口。当创建一个Service时,IPVS会添加一个虚拟服务器,该服务器监听Cluster IP和端口,并将流量转发到对应的后端Pod。此时,Cluster IP会被绑定到节点的网络接口(如kube-ipvs0),这使得该IP成为节点上的一个有效IP地址,因此能够响应ICMP请求。 接下来,我需要解释为什么在iptables模式下通常无法ping通Cluster IP。因为在iptables模式下,kube-proxy仅设置iptables规则来重写目标地址,而不会将Cluster IP绑定到任何网络接口。因此,这些IP在节点上并不“真实存在”,无法响应ping请求。 此外,不同的CNI插件(如Calico、Flannel)可能会有不同的实现方式,可能会影响Cluster IP的可达性。例如,Calico在IPVS模式下可能会创建一个名为kube-ipvs0的虚拟接口,并将所有Service的Cluster IP绑定到该接口,导致这些IP能够被ping通。 然后,我需要验证这些信息是否正确。查阅Kubernetes官方文档和IPVS相关的资料,确认在IPVS模式下,Cluster IP确实会被绑定到网络接口,从而响应ICMP请求。同时,确认在iptables模式下不会绑定,因此无法ping通。 用户可能需要进一步了解这是否会影响Service的正常工作,或者是否存在安全隐患。需要说明,虽然Cluster IP可以ping通,但这并不影响Service的流量转发功能,只要后端Pod正常,服务仍然可用。另外,虽然能够ping通,但这通常不会导致安全问题,因为Cluster IP仅在集群内部可达,除非网络配置存在错误。 最后,整理这些思路,形成结构化的回答,分点解释IPVS模式下的工作机制,对比iptables模式,说明为何IPVS模式下Cluster IP可ping通,并讨论其影响和注意事项。</think>当 `kube-proxy` 使用 **IPVS 模式** 时,Service 的 Cluster IP 能够被 `ping` 通,这与 IPVS 的实现机制和内核层面的网络配置密切相关。以下是具体原因和详细解释: --- ### **1. IPVS 模式的工作原理** IPVS(IP Virtual Server)是 Linux 内核的一部分,专门用于高性能负载均衡。在 Kubernetes 中,`kube-proxy` 通过 IPVS 实现 Service 的流量转发: - **IPVS 会为每个 Service 创建虚拟服务器(Virtual Server)**,并将 Service 的 Cluster IP 和端口绑定到节点的网络接口(如 `kube-ipvs0`)。 - 当请求到达 Cluster IP 时,IPVS 根据负载均衡算法(如轮询、加权最小连接等)将流量转发到后端 Pod。 #### **关键行为:Cluster IP 被绑定到网络接口** - 在 IPVS 模式下,`kube-proxy` 会为所有 Service 的 Cluster IP **显式绑定到节点的虚拟接口**(如 `kube-ipvs0`)。这使得 Cluster IP 成为节点上的一个“真实” IP 地址。 - 例如,查看节点的网络接口: ```bash ip addr show kube-ipvs0 ``` 输出类似: ``` 10: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default inet 10.96.0.1/32 scope global kube-ipvs0 inet 10.106.141.104/32 scope global kube-ipvs0 # Cluster IP 被绑定到这里 ``` --- ### **2. 为什么 Cluster IP 能响应 `ping`** #### **(1) IP 地址在接口上真实存在** - 由于 Cluster IP 被绑定到节点的 `kube-ipvs0` 接口,**内核会直接响应 ICMP 请求**(如 `ping`),即使没有后端 Pod。 - 这是 IPVS 模式的特性,与 `kube-proxy` 的 iptables 模式不同: - **iptables 模式**:仅通过 iptables 规则修改流量目标,不会将 Cluster IP 绑定到接口,因此无法 `ping` 通。 - **IPVS 模式**:显式绑定 Cluster IP 到接口,因此接口会响应 `ping`。 #### **(2) ICMP 请求的默认处理** - 当 `ping` Cluster IP 时,请求会发送到节点的 `kube-ipvs0` 接口。由于该接口处于 `NOARP` 状态(不参与 ARP 协议),但 IP 地址本身有效,**内核会直接回复 ICMP Echo Reply**。 --- ### **3. 对比 iptables 模式** 在 iptables 模式下,`kube-proxy` 的行为不同: - **Cluster IP 未被绑定到接口**,仅通过 iptables 规则拦截和转发流量。 - 当 `ping` Cluster IP 时,由于没有接口持有该 IP,数据包会被丢弃,因此无法收到响应。 --- ### **4. 影响与注意事项** #### **(1) 不影响 Service 的正常功能** - 即使 Cluster IP 能 `ping` 通,只要 Service 的 Endpoints(后端 Pod)正常,**实际业务流量(如 HTTP)仍会被正确转发**。 - 可以通过以下命令验证 Service 是否正常工作: ```bash curl -I http://10.106.141.104:80 # 替换为你的 Cluster IP 和端口 ``` #### **(2) 安全性与网络策略** - Cluster IP 的 ICMP 响应**仅在集群内部生效**(取决于网络插件配置),外部通常无法访问。 - 若需禁止 `ping` 通 Cluster IP,可以通过以下方式: - **网络策略**:使用 Calico 或 Cilium 等 CNI 插件,配置 NetworkPolicy 丢弃 ICMP 流量。 - **调整内核参数**:禁止 `kube-ipvs0` 接口响应 ICMP(需谨慎操作)。 #### **(3) 与 CNI 插件的关联** - 不同网络插件可能影响 Cluster IP 的绑定行为。例如: - **Calico**:默认创建 `kube-ipvs0` 接口并绑定 Cluster IP。 - **Flannel**:可能不会创建 `kube-ipvs0` 接口,但 IPVS 仍会绑定 Cluster IP 到默认接口。 --- ### **5. 总结** - **根本原因**:IPVS 模式下,Cluster IP 被绑定到节点的 `kube-ipvs0` 接口,导致内核直接响应 ICMP 请求。 - **与 iptables 模式的差异**:iptables 模式不绑定 Cluster IP,因此无法 `ping` 通。 - **无需修复**:这是 IPVS 的预期行为,只要 Service 功能正常,无需干预。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值