haproxy 使用 pod 名称作为服务器名称

haproxy use pod name as server name

我在 k8s 中有一个 haproxy 作为负载均衡器 运行,它有一个路由到一个有两个 运行 pods 的服务。我希望 haproxy 中的服务器命名与我的服务背后的 pod 名称相对应。如果我没记错的话,下面的 configmap / annotation 值应该是这样的:https://haproxy-ingress.github.io/docs/configuration/keys/#backend-server-naming。但对我来说不是,而且我一生都找不到原因。我配置的相关部分如下所示:

控制器部署:

kind: Deployment
metadata:
  labels:
    run: haproxy-ingress
  name: haproxy-ingress
  namespace: haproxy-controller
spec:
  replicas: 2
  selector:
    matchLabels:
      run: haproxy-ingress
  template:
    metadata:
      labels:
        run: haproxy-ingress
    spec:
      serviceAccountName: haproxy-ingress-service-account
      containers:
        - name: haproxy-ingress
          image: haproxytech/kubernetes-ingress
          args:
            - --configmap=haproxy-controller/haproxy-ingress
            - --configmap-errorfiles=haproxy-controller/errorfile-conf
            - --default-ssl-certificate=haproxy-controller/haproxy-tls
            - --ingress.class=haproxy

控制器服务:

kind: Service
metadata:
  labels:
    run: haproxy-ingress
  name: haproxy-ingress
  namespace: haproxy-controller
spec:
  selector:
    run: haproxy-ingress
  type: ClusterIP
  ports:
    - name: https
      port: 443
      protocol: TCP
      targetPort: 443

控制器配置图:

kind: ConfigMap
metadata:
  name: haproxy-ingress
  namespace: haproxy-controller
data:
  server-ssl: "true"
  scale-server-slots: "2"
  cookie-persistence: "LFR_SRV"
  backend-server-naming: "pod"
  backend-config-snippet: |
    cookie LFR_SRV indirect nocache insert maxidle 10m httponly secure

后端服务器入口:

kind: Ingress
metadata:
  name: liferay-dxp
  namespace: backend
  annotations:
    kubernetes.io/ingress.class: "haproxy"
spec:
  tls:
    - secretName: backend-tls
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: backend
                port:
                  number: 443

haproxy.conf 生成的后端部分如下所示:

  mode http
  balance roundrobin
  option forwardfor
  cookie LFR_SRV indirect nocache insert
  ###_config-snippet_### BEGIN                                                                                                                                          
  cookie LFR_SRV indirect nocache insert maxidle 10m httponly secure
  ###_config-snippet_### END
  server SRV_1 10.xx.xx.xx:443 check ssl alpn h2,http/1.1 weight 128 cookie SRV_1 verify none
  server SRV_2 10.xx.xx.xx:443 check ssl alpn h2,http/1.1 weight 128 cookie SRV_2 verify none

backend-server-naming: "pod" 外一切正常。我也无法使用 here 中的任何 session-cookie-* 属性。因此,我使用 backend-config-snippet 将生成的 haproxy.conf 中的 cookie 行覆盖为我的自定义行(我添加了 maxidle 10m httponly secure)。我做错了什么?

这里有一些提示可以帮助您解决问题。

确保您知道 haproxy-ingress 控制器的确切版本:

查看您共享的清单文件,很难判断您在集群中 运行 是 haproxy-ingress-controller 容器的确切版本(顺便说一句,离开它违反了生产环境中的最佳实践w/o 标签,阅读更多 here).

要使 backend-server-naming 配置密钥正常工作,至少需要 v0.8.1 (it was backported)

在继续进行故障排除之前,请首先仔细检查您的入口部署的兼容性。

我对“backend-server-naming=pod”行为的观察

配置动态更新:

如果我没看错的话官方文档就这个configuration key, setting a server naming of backends to pod names (backend-server-naming=pod) instead of sequences, does support a dynamic re-load of haproxy configuration, but does NOT support as of now dynamic updates to haproxy run-time configuration to server names at backend section (it was explained by haproxy-ingress author here, and here)

这意味着您需要先重新启动 haproxy-ingress 控制器实例,才能看到反映在 haproxy 配置中的后端服务器名称的变化,例如出现新的 Pod 副本或 POD_IP 由于 Pod 崩溃而更改的情况(预计 addition/updates 基于序列命名的服务器条目)。

入口Class:

我已经成功测试(参见下面的测试)v0.13.4 上的 backend-server-naming=pod 设置,具有 classified 入口类型,基于 ingressClassName 字段,而不是弃用的注释 kubernetes.io/ingress.class,如您的情况:

我并不是说您的配置不起作用(它也应该起作用),但重要的是要知道,配置的动态更新(包括后端配置的更改)不会发生在未分类的 Ingress 资源或错误分类一个,除非你真的是 运行 v0.12 或更新版本。

测试:

# Ingress class 
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: my-class
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
spec:
  controller: haproxy-ingress.github.io/controller

# Demo Ingress resource
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    haproxy-ingress.github.io/backend-server-naming: "pod"
  name: echoserver
spec:
  ingressClassName: my-class
  rules:
  - http:
      paths:
      - backend:
          service:
            name: echoserver
            port:
              number: 8080
        path: /
        pathType: Prefix

HA 代理配置评论:

backend default_echoserver_8080
    mode http
    balance roundrobin
    acl https-request ssl_fc
    http-request set-header X-Original-Forwarded-For %[hdr(x-forwarded-for)] if { hdr(x-forwarded-for) -m found }
    http-request del-header x-forwarded-for
    option forwardfor
    http-response set-header Strict-Transport-Security "max-age=15768000" if https-request
    # pod name start
    server echoserver-75d6f584bb-jlwb8 172.17.0.2:8080 weight 1 check inter 2s
    # pod name end
    server srv002 127.0.0.1:1023 disabled weight 1 check inter 2s
    server srv003 127.0.0.1:1023 disabled weight 1 check inter 2s
    server srv004 127.0.0.1:1023 disabled weight 1 check inter 2s
    ...