K3s 部署中解决获取真实 IP 的问题:使用 Calico 实现真实 IP 传递
作 者 简 介
辣个男人Devin,资深运维工程师曾在银行,支付,区块链领域从事多年运维工作。Rancher&K3s 深度用户。
前言
在 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-for
和 x-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