K3s 部署中解决获取真实 IP 的问题:使用 Calico 实现真实 IP 传递

共 9378字,需浏览 19分钟

 ·

2024-01-09 11:19


辣个男人Devin资深运维工程师曾在银行,支付,区块链领域从事多年运维工作。Rancher&K3s 深度用户。


cc9e5e3b79a07c8c6fb4f70b7d56eea8.webp

前言

在 Kubernetes 集群中,获取用户真实 IP 地址是一个至关重要的需求。然而,在 K3s 部署中,很多运维人员可能会遇到一些困扰,尤其是在使用 K3s 默认的 CNI Flannel 作为网络插件时,难以准确获取到用户的真实 IP 地址。

本文将分享在解决这一问题的过程中的实践经验,尤其是通过使用 Calico 替代 Flannel 的方式,成功实现了真实 IP 的传递。值得注意的是,虽然 Flannel 也可以实现获取真实 IP 的功能,但我选择使用 Calico 来代替 Flannel,以获得更灵活和可定制的网络方案。

环境准备

在阿里云环境中进行测试,使用机器内网网段为 172.19.112.0/20,推荐使用全新机器以避免潜在问题。

测试环境 (sip.pro.com)

  • 一台 master(10.42.0.0),三台 node(10.42.1.0 10.42.2.0 10.42.3.0)
  • K3s 版本:1.25.12
  • 操作系统:Ubuntu 20.04.6
  • Traefik 版本:2.9.10(通过 Helm 安装)
  • Rancher 版本:2.7.9

问题发现

在部署中发现 x-forwarded-forx-real-ip 无法获取到用户请求的真实 IP 地址。

探寻原因

通过查阅 K3s 的相关讨论[1],发现使用内置的 Flannel 无法获取到用户真实 IP,最多只能到 LB 的 IP。解决方案可以禁用掉默认的 flannel,通过手动部署的形式修改 flannel 参数,或者是使用 Calico 替代 Flannel

测试和解决方案尝试

为验证真实 IP 是否正确获取,统一使用 SIP 进行测试。测试环境映射到 https://sip.pro.com。

      
      kubectl create deployment source-ip-app --image=corelab/echoserver:1.4

1. 默认配置

验证:访问 https://sip.pro.com

      
      CLIENT VALUES:
client_address=10.42.0.27
...
x-forwarded-for=10.42.3.0
x-real-ip=10.42.3.0

未更改 CNI,使用默认的 K3s 安装的 Flannel,只能获取到 Pod 的网段地址 10.42.3.0。

2. Traefik Service 配置 externalTrafficPolicy: Local

利用 HelmChartConfig 自定义 Traefik Service:

      
      cat << EOL > /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    service:
      spec:
        externalTrafficPolicy: Local
EOL

验证:访问 https://sip.pro.com

      
      CLIENT VALUES:
client_address=10.42.0.27
...
x-forwarded-for=10.42.2.203
x-real-ip=10.42.2.203

可以获取到指定 node 的 Klipper-lb (Service LB)的 pod ip

3. 禁用 Flannel,安装 Calico

禁用默认的 Flannel,同时禁用网络策略,安装 Calico。

      
      curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
    INSTALL_K3S_VERSION=v1.25.12+k3s1 \
    INSTALL_K3S_MIRROR=cn \
    INSTALL_K3S_EXEC='--flannel-backend=none --disable-network-policy --cluster-cidr=192.168.0.0/16' \
    sh -

安装 Calico(Manifest 版本):

      
      kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/calico.yaml

等待节点安装完成即可。

单节点测试 Calico:

这次按照上文中 K3s 讨论 中说的,换成 calico,真实 ip 已经能到达节点 ip 了,不过现在这个实验场景是使用的单个 k3s 节点。

      
      #sip.pro.com

CLIENT VALUES:
client_address=192.168.105.200
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://sip.pro.com:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding=gzip, deflate
accept-language=zh-CN,zh;q=0.9,en;q=0.8
cache-control=max-age=0
host=777.xydao.cn
upgrade-insecure-requests=1
user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
x-forwarded-for=172.19.112.37
x-forwarded-host=sip.pro.com
x-forwarded-port=80
x-forwarded-proto=http
x-forwarded-server=traefik-66fd46ccd-n9qzd
x-real-ip=172.19.112.37
BODY:
-no body in request-

多节点测试:

      
      #sip.pro.com

CLIENT VALUES:
client_address=192.168.105.200
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://sip.pro.com:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding=gzip, deflate
accept-language=zh-CN,zh;q=0.9,en;q=0.8
host=sip.pro.com
upgrade-insecure-requests=1
user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
x-forwarded-for=171.214.1.1
x-forwarded-host=sip.pro.com
x-forwarded-port=80
x-forwarded-proto=http
x-forwarded-server=traefik-66fd46ccd-n9qzd
x-real-ip=171.214.1.1
BODY:
-no body in request-

发现已经拿到公网 ip,成功~可以上生产啦!

结论

通过替代 Flannel 为 K3s 选择 Calico,我们成功解决了在生产环境中获取真实 IP 的问题。这个优化不仅确保了 IP 的准确性,还提高了 Kubernetes 集群的可用性。

进一步阅读

若想深入了解本文所涉及的技术和问题,建议阅读以下参考链接:

  • Kubernetes 官方文档:Source IP for Services with Type=LoadBalancer:https://kubernetes.io/zh-cn/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-loadbalancer
  • 解决 K3s 下 Traefik 无法获取真实客户端 IP 的问题:https://comphilip.wordpress.com/2021/05/23/k3s-thing-make-traefik-forward-real-client-ip/
  • K3s 部署中使用 Calico 的快速入门:https://docs.tigera.io/calico/latest/getting-started/kubernetes/k3s/quickstart
  • Calico 官方文档:https://www.escapelife.site/posts/754ba85c.html
  • K3s 使用 Calico 的 Manifest 示例:https://github.com/jawabuu/kloud-3s/blob/2865603f08e47bc159965faaebe60c3e4e9c138c/service/k3s/templates/flannel.yaml#L184-L192

后记

感谢大家阅读本文,希望能为 K3s 用户在解决真实 IP 获取问题上提供一些有用的经验。欢迎大家分享和讨论,一起探讨 Kubernetes 在实际应用中的优化与实践。

参考资料

[1]

K3s 官方 GitHub 讨论: https://github.com/k3s-io/k3s/discussions/2997


A b o u t   k 3 s


k 3 s     C N C F     K 8 S     C N C F     K 8 S   2 0 1 9 3 G i t H u b   S t a r   1 7 , 0 0 0   K 8 S   K 3 s 1 0 0 2 3 0 %


k 3 s     K u b e r n e t e s     x 8 6 A R M 6 4     A R M v 7     K u b e r n e t e s   k 3 s   R a n c h e r   2 . X   +   k 3 s   K 8 S   K u b e r n e t e s - a s - a - S e r v i c e   K u b e r n e t e s   E v e r y w h e r e

k 3 s

h t t p s : / / k 3 s . i o

浏览 70
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报