k8s 获取真实ip地址

发布于:2025-09-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

k8s 获取真实ip地址

说明:自建的的k8s环境是 一主二从 的架构。主节点 k8s-master 从节点 k8s-node1 k8s-node2 (主节点是污节点,默认是不会调度到污节点的)。控制面板使用 Kuboard

externalTrafficPolicy Local Cluster 区别

在 Kubernetes 中,Service 的 externalTrafficPolicy 字段用于控制外部流量(来自集群外的请求)如何路由到后端 Pod,主要有 Cluster(默认值)和 Local 两种模式

1. 流量转发机制

  • Cluster 模式(默认)
    集群中的所有节点(包括没有运行目标 Pod 的节点)都可以接收外部流量。
    当请求到达任意节点时,节点会跨节点转发流量到集群内任意健康的目标 Pod(无论 Pod 是否在当前节点上)。
  • Local 模式
    节点只处理本地运行的目标 Pod 的流量
    当请求到达某个节点时,如果该节点上没有目标 Pod,请求会被直接丢弃(不会转发到其他节点)。

2. 源 IP 保留

  • Cluster 模式
    由于可能存在跨节点转发,请求的源 IP 会被中间节点替换为节点自身的 IP,因此后端 Pod 无法获取真实客户端 IP(只能拿到转发节点的 IP)。
  • Local 模式
    流量不会跨节点转发,请求直接发送到本地 Pod,因此后端 Pod 可以保留并获取真实的客户端源 IP

3. 负载均衡与可用性

  • Cluster 模式
    • 优点:负载均衡更均衡,可充分利用集群资源(所有节点都能接收流量并转发)。
    • 缺点:无法获取真实客户端 IP;跨节点转发会增加网络开销。
  • Local 模式
    • 优点:保留真实客户端 IP;减少跨节点网络开销。
    • 缺点:负载均衡可能不均衡(只有运行 Pod 的节点能处理流量);若节点上的 Pod 故障,该节点接收的请求会被丢弃(需依赖外部负载均衡器健康检查规避)。

情况一

  • ​ nginx 作为流量的入口
第一步:服务选择 nodePort 模式
第二步: 修改 externalTrafficPolicy 的值为 Local (默认都是Cluster)
第三步:节点调度策列 选择根据【节点名称】选择节点,选择 master 节点
第四步:容忍 key选择污点--选择exists--选择NoSchedule

第三点和第四点 对应的yaml配置内容(也可以通过修改yaml文件实现)
spec:
  template:
      spec:
      	nodeName: k8s-master
      	tolerations:
          - effect: NoSchedule
          	key: node-role.kubernetes.io/master
          	operator: Exists
  • nginx.conf 的主要配置
        location /api/ {
                #proxy_set_header Host              $host;
                #proxy_set_header X-Real-IP         $remote_addr; 
                #proxy_set_header X-Forwarded-Proto $scheme;
                #proxy_set_header X-Forwarded-Host  $host;
                #proxy_set_header X-Forwarded-Port  $server_port;
                proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
                proxy_pass http://网关地址:端口/;
        }
  • gateway服务
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.ServerHttpRequest;
import reactor.core.publisher.Mono;

@Configuration
public class RealIpConfig {

    @Bean
    public GlobalFilter realIpFilter() {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            
            // 1. 优先从 X-Real-IP 获取(通常由 ingress-nginx 直接写入真实 IP)
            String realIp = request.getHeaders().getFirst("X-Real-IP");
            
            // 2. 若 X-Real-IP 不存在,从 X-Forwarded-For 取第一个 IP(格式:客户端IP, 代理1IP, 代理2IP...)
            if (realIp == null || realIp.isEmpty()) {
                String xForwardedFor = request.getHeaders().getFirst("X-Forwarded-For");
                if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
                    realIp = xForwardedFor.split(",")[0].trim();
                }
            }
            
            // 3. 若以上都不存在, fallback 到直接连接的 IP(可能是代理 IP)
            if (realIp == null || realIp.isEmpty()) {
                realIp = request.getRemoteAddress().getHostString();
            }
            
            // 将真实 IP 存入上下文,供后续使用(如日志、业务逻辑)
            exchange.getAttributes().put("REAL_CLIENT_IP", realIp);
            
            return chain.filter(exchange);
        };
    }
}

情况二

  • ingress-nginx作为流量入口

    ingress-nginx部署文件下载 wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml

    修改deploy.yaml内容

    # Source: ingress-nginx/templates/controller-configmap.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      labels:
        helm.sh/chart: ingress-nginx-3.33.0
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/version: 0.47.0
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/component: controller
      name: ingress-nginx-controller
      namespace: ingress-nginx
    data:
      # 添加以下配置
      compute-full-forwarded-for: "true" # 启用完整的X-Forwarded-For头计算
      forwarded-for-header: "X-Forwarded-For"
      use-forwarded-headers: "true" # 启用对转发头的处理(但仅信任直接连接的源 IP)
      use-proxy-protocol: "false"  # 如果前端有代理(如负载均衡器)使用 proxy protocol,需开启
      real-ip-header: "X-Forwarded-For"  # 从 X-Forwarded-For 头获取真实 IP
    
    spec:
      template:
        spec:
          # 添加节点选择器,指定部署到 master 节点
          nodeSelector:
            node-role.kubernetes.io/master: ""
          # 添加容忍度,允许调度到有污点的 master 节点
          tolerations:
            - key: "node-role.kubernetes.io/master"
              operator: "Exists"
              effect: "NoSchedule"
              
    删掉原来的这个配置
           nodeSelector:
            kubernetes.io/os: linux
    
    • nginx.conf 的主要配置

       		#从哪个头中获取真实 IP(与 ingress-nginx 配置对应)
              real_ip_header    X-Forwarded-For;
              #信任来自 ingress-nginx 的 IP(填写 ingress-nginx 的 service 网段或具体 IP)
              set_real_ip_from  10.96.0.0/16;
              #信任来自 ingress-nginx 的 IP(填写 ingress-nginx 的 Pod 网段或具体 IP)
              set_real_ip_from  178.38.0.0/16;
              #如果 X-Forwarded-For 中有多个 IP(如多级代理),取第一个作为真实 IP
              real_ip_recursive on;
      
              location /api/ {
                      #proxy_set_header Host              $host;
                      #proxy_set_header X-Real-IP         $remote_addr; 
                      #proxy_set_header X-Forwarded-Proto $scheme;
                      #proxy_set_header X-Forwarded-Host  $host;
                      #proxy_set_header X-Forwarded-Port  $server_port;
                      proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
         			   proxy_pass http://网关地址:端口/;
              }
      
    • 网关服务

      import org.springframework.cloud.gateway.filter.GlobalFilter;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.http.server.reactive.ServerHttpRequest;
      import reactor.core.publisher.Mono;
      
      @Configuration
      public class RealIpConfig {
      
          @Bean
          public GlobalFilter realIpFilter() {
              return (exchange, chain) -> {
                  ServerHttpRequest request = exchange.getRequest();
                  
                  // 1. 优先从 X-Real-IP 获取(通常由 ingress-nginx 直接写入真实 IP)
                  String realIp = request.getHeaders().getFirst("X-Real-IP");
                  
                  // 2. 若 X-Real-IP 不存在,从 X-Forwarded-For 取第一个 IP(格式:客户端IP, 代理1IP, 代理2IP...)
                  if (realIp == null || realIp.isEmpty()) {
                      String xForwardedFor = request.getHeaders().getFirst("X-Forwarded-For");
                      if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
                          realIp = xForwardedFor.split(",")[0].trim();
                      }
                  }
                  
                  // 3. 若以上都不存在, fallback 到直接连接的 IP(可能是代理 IP)
                  if (realIp == null || realIp.isEmpty()) {
                      realIp = request.getRemoteAddress().getHostString();
                  }
                  
                  // 将真实 IP 存入上下文,供后续使用(如日志、业务逻辑)
                  exchange.getAttributes().put("REAL_CLIENT_IP", realIp);
                  
                  return chain.filter(exchange);
              };
          }
      }
      
      

k8s 查看污点

1. 查看所有节点的污点

kubectl describe nodes | grep Taint -A 10

2. 查看指定节点的污点

kubectl describe node <节点名称> | grep Taint

3. 更简洁的方式(推荐)

kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

网站公告

今日签到

点亮在社区的每一天
去签到