1

当我们的 POD 耗尽并且可能需要扩展时,Kubernetes 会将这种耗尽与死亡混淆并重新启动我们的 POD:s。当然,这会产生相反的效果,剩余的 POD:s 负载会更大……所以我的问题来了,你能否通过专用的、未耗尽的连接来为 Kubernetes 和 LB 的活跃度和就绪度端点提供服务?

我们有一个在 Kubernetes 中运行的旧系统,一个 Apache httpd 和一个捆绑在每个 POD 中的 tomcat。负载均衡由 Kubernetes 在不同的 POD:s 之间完成,而不是在 httpd 中。Httpd 正在运行 mpm_event+mod_jk 并且有一个到 Tomcat 的 AJP 1.3 连接。Httpd 还从没有 Tomcat 的磁盘中提供一些静态资源。当出现故障时,我们很快就会用完 AJP 线程和 HTTPD 工作线程。

基本上我们看到的是这样的:

  1. 应用程序无法连接到某些资源。某些网络、Memcached、DB 或其他服务开始超时。等待超时会导致线程的寿命很长,我们很快就会用完它们。
  2. Readiness/Liveness probs 没有及时响应,Kubernetes 重新启动 POD(或者,在我们移除 liveness probes 后,使用 readiness 的 LB 将它们从负载均衡中移除,效果基本相同)。
  3. 根本原因问题已解决(以某种方式),但现在负载平衡中剩下的(非)POD 太少了。当 POD 返回时,它会受到所有流量的影响,耗尽,并从 LB 中删除,因为它再次在就绪探测上太慢了。
  4. 我们现在发现很难摆脱这种状态......(到目前为止它发生了两次,我们基本上不得不切断 Cloudflare WAF 上的所有流量,直到重新启动足够的 POD:s/在负载平衡中......)

我对解决方案的想法:

我想我可以从 httpd->tomcat 为 liveness 和 readiness 端点打开一个优先的快速通道,见下文。但是,我可以以某种方式将 httpd (mpm_event) 中的工作人员专用于这些端点吗?否则,当我用完 httpd 工作人员时,我猜我的快车道不会提供任何帮助。或者关于如何确保只要tomcat还活着,即使它已经用尽,我们总是可以服务于活跃/准备就绪的任何其他想法?

这是我当前的 httpd worker 设置:

<IfModule mpm_event_module>
    StartServers             3
    ServerLimit             36
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      900
    MaxConnectionsPerChild   0
</IfModule>

也许只需要一个工作人员来分析请求并找出 URI ... :-/ 或者我可以以某种方式将一个特定的工作人员池专用于活跃性和准备工作吗?

我的 httpd->tomcat 快速通道:

我正在玩弄与 tomcat 的第二个 AJP 连接,专门用于准备就绪和活跃度端点。乍一看,它似乎工作。

在 server.xml 中,我在端口 8008 上添加了一个连接器:

    <Connector
        port="8009"
        protocol="AJP/1.3"
        redirectPort="8443"
        connectionTimeout="60000"
        minSpareThreads="2"
        maxThreads="20"
        acceptorThreadCount="2"
        URIEncoding="UTF-8"
        address="127.0.0.1"
        secretRequired="false" />

    <!--
      This is the prioritized connector used for health checks.
    -->
    <Connector
        port="8008"
        protocol="AJP/1.3"
        redirectPort="8443"
        connectionTimeout="-1"
        keepAliveTimeout="-1"
        acceptorThreadPriority="6"
        minSpareThreads="2"
        maxThreads="5"
        acceptorThreadCount="1"
        URIEncoding="UTF-8"
        address="127.0.0.1"
        secretRequired="false" />

在我workers.properties的(JkWorkersFile)中,我添加了新连接并将其命名为ajp13prio

worker.list=ajp13,ajp13prio
worker.ajp13.type=ajp13
worker.ajp13.port=8009
worker.ajp13.host=127.0.0.1
worker.ajp13.lbfactor=1
worker.ajp13prio.type=ajp13
worker.ajp13prio.port=8008
worker.ajp13prio.host=127.0.0.1
worker.ajp13prio.lbfactor=1

在我的 httpd conf 中,我将探针配置为使用新的连接器:

<VirtualHost *:80>
...
    # health checks (readiness and liveness probes) are prioritized
    JkMount /api/v2/health/* ajp13prio

    # All requests go to worker1 by default
    JkMount /* ajp13
...
</VirtualHost>
4

1 回答 1

0

只是为了结束如果其他人在这里结束,在 kubernetes 中运行旧的 Apache 设置。

最后,我向 Tomcat 添加了第二个连接器,它是 HTTP,而不是 AJP。这个连接器的端口从容器中暴露出来,并被 LB 和 Kubernetes 使用。因此,健康检查完全绕过 HTTPD。然后此端口(默认情况下)在 LB 中被阻止以供外部访问。

服务器.xml

    <Connector
        port="8080"
        address="0.0.0.0"
        protocol="HTTP/1.1"
        enableLookups="false"
        maxThreads="5"
        minSpareThreads="2"
        acceptorThreadCount="1"
        acceptorThreadPriority="9"
        connectionTimeout="2000"
        keepAliveTimeout="-1"
        disableUploadTimeout="false"
        connectionUploadTimeout="3600000"
        redirectPort="8443"
        URIEncoding="UTF-8"
        maxPostSize="1" />

部署.yaml


tomcat container:
          readinessProbe:
            httpGet:
              path: /health/readiness
              port: 8080
            initialDelaySeconds: 120
          livenessProbe:
            httpGet:
              path: /health/liveness
              port: 8080
          ports:
            - name: ajp
              containerPort: 8009
              protocol: TCP
            - name: http-prio
              containerPort: 8080
              protocol: TCP

服务.yaml:

apiVersion: v1
kind: Service
metadata:
...
  annotations:
    cloud.google.com/backend-config: '{"default": "app-backendconfig"}'
spec:
  ports:
  - name: http
    port: 80
  - name: http-prio
    port: 8080

...

后端配置.yaml

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
...
spec:
...
  healthCheck:
    type: HTTP
    requestPath: /health/readiness
    port: 8080
于 2021-07-07T07:18:00.907 回答