Kubernetes NodePort 并非在所有节点上都可用 - Oracle Cloud Infrastructure (OCI)

2024-01-04

我一直在努力克服这个问题,但现在我没有想法,因此我在这里发布这个问题。

我正在尝试 Oracle 云基础设施 (OCI),我想创建一个公开某些服务的 Kubernetes 集群。

目标是:

  • 正在运行的托管 Kubernetes 集群 (OKE)
  • 至少2个节点
  • 1 项可供外部方访问的服务

基础结构如下所示:

  • 一个完整的 VCN
  • 10.0.1.0/24 上的私有子网
  • 10.0.0.0/24 上的公共子网
  • 私有子网的 NAT 网关
  • 公共子网的 Internet 网关
  • 服务网关
  • 两个子网的相应安全列表,除非有人要求,否则我现在不会共享
  • VCN 中启用公共 Kubernetes API 的容器引擎 K8S (OKE) 集群
  • K8S 集群的节点池目前有 2 个可用域和 2 个实例。这些实例是具有 1 个 OCPU 和 6GB RAM 的 ARM 计算机,运行 Oracle-Linux-7.9-aarch64-2021.12.08-0 映像。
  • K8S集群中的命名空间(暂时称之为staging)
  • 指在端口 3000 上提供流量的自定义 NextJS 应用程序的部署

现在我想公开在端口 3000 上运行的服务。

我有两个明显的选择:

  • 在 K8S 中创建一个 LoadBalancer 服务,该服务将在 OCI 中生成一个经典的负载均衡器,设置其侦听器并设置引用集群中 2 个节点的后端集,此外它还调整子网安全列表以确保流量可以流动
  • 在 OCI 中创建网络负载均衡器并在 K8S 上创建 NodePort 并手动将 NLB 配置为与经典负载均衡器相同的设置

第一个工作得很好,但我想以最小的成本使用这个集群,所以我决定尝试选项 2,即 NLB,因为它更便宜(零成本)。

长话短说,一切正常,大多数时候我可以在 NLB 的 IP 上访问 NextJS 应用程序,但有时却无法访问。我决定查看到底发生了什么,结果发现我在集群中公开的 NodePort 并没有按照我的想象工作。

NodePort 背后的服务只能在 K8S 中运行 pod 的节点上访问。假设 NodeA 正在运行该服务,而 NodeB 正在那里运行。如果我尝试访问 NodeA 上的服务,一切都很好。但是当我尝试在 NodeB 上执行相同操作时,我根本没有得到任何响应。

这是我的问题,我无法弄清楚可能是什么问题。

到目前为止我尝试过的:

  • 从 ARM 机器切换到 AMD 机器 - 没有变化
  • 在公共子网中创建堡垒主机以测试哪些节点正在响应请求。结果只有正在运行 pod 的节点做出响应。
  • 在 K8S 中创建了一个常规的 LoadBalancer,其配置与 NodePort 相同(在本例中 OCI 将创建一个经典的负载均衡器),效果完美
  • 尝试升级到 K8S 节点的 Oracle 8.4 映像,但没有修复它
  • 在节点上运行 Node Doctor,一切都很好
  • 检查了kube-proxy、kube-flannel、core-dns的日志,没有错误
  • 由于集群由2个节点组成,我尝试了一下,又添加了一个节点,但新节点上的服务也无法访问
  • 从头开始重新创建集群

Edit:一些更新。我尝试使用 DaemonSet 而不是 pod 的常规部署,以确保作为临时解决方案,所有节点都运行至少一个 pod 实例,这令人惊讶。之前没有响应该特定端口上的请求的节点现在仍然没有响应,即使 Pod 正在其上运行。

Edit2:最初我运行的是集群的最新 K8S 版本 (v1.21.5),我尝试降级到 v1.20.11,不幸的是问题仍然存在。

Edit3:检查 NodePort 在没有响应的节点上是否打开,并且是,至少 kube-proxy 正在侦听它。

tcp        0      0 0.0.0.0:31600           0.0.0.0:*               LISTEN      16671/kube-proxy

Edit4::尝试添加白名单 iptables 规则但没有改变任何内容。

[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P FORWARD ACCEPT
[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P INPUT ACCEPT
[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P OUTPUT ACCEPT

Edit5:作为一次试验,我再次创建了一个 LoadBalancer 来验证我是否完全失去了理智,我只是在尝试时没有注意到这个错误或者它确实有效。有趣的是,它通过经典负载均衡器的 IP 运行得非常好。But当我尝试直接在为负载均衡器打开的端口(目前为 30679)上向节点发送请求时。我仅从运行 Pod 的节点获得响应。另一方面,仍然没有通过负载均衡器,我得到了 100% 成功的响应。

另外,这是来自未响应请求的节点的 iptables,不太确定要查找什么:

[opc@oke-cn44eyuqdoq-n3ewna4fqra-sx5p5dalkuq-1 ~]$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-NODEPORTS  all  --  anywhere             anywhere             /* kubernetes health check service ports */
KUBE-EXTERNAL-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes externally-visible service portals */
KUBE-FIREWALL  all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
KUBE-FORWARD  all  --  anywhere             anywhere             /* kubernetes forwarding rules */
KUBE-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes service portals */
KUBE-EXTERNAL-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes externally-visible service portals */
ACCEPT     all  --  10.244.0.0/16        anywhere
ACCEPT     all  --  anywhere             10.244.0.0/16

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes service portals */
KUBE-FIREWALL  all  --  anywhere             anywhere

Chain KUBE-EXTERNAL-SERVICES (2 references)
target     prot opt source               destination

Chain KUBE-FIREWALL (2 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000
DROP       all  -- !loopback/8           loopback/8           /* block incoming localnet connections */ ! ctstate RELATED,ESTABLISHED,DNAT

Chain KUBE-FORWARD (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             ctstate INVALID
ACCEPT     all  --  anywhere             anywhere             /* kubernetes forwarding rules */ mark match 0x4000/0x4000
ACCEPT     all  --  anywhere             anywhere             /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere             /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED

Chain KUBE-KUBELET-CANARY (0 references)
target     prot opt source               destination

Chain KUBE-NODEPORTS (1 references)
target     prot opt source               destination

Chain KUBE-PROXY-CANARY (0 references)
target     prot opt source               destination

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination

服务规范(正在运行的规范,因为它是使用 Terraform 生成的):

{
    "apiVersion": "v1",
    "kind": "Service",
    "metadata": {
        "creationTimestamp": "2022-01-28T09:13:33Z",
        "name": "web-staging-service",
        "namespace": "web-staging",
        "resourceVersion": "22542",
        "uid": "c092f99b-7c72-4c32-bf27-ccfa1fe92a79"
    },
    "spec": {
        "clusterIP": "10.96.99.112",
        "clusterIPs": [
            "10.96.99.112"
        ],
        "externalTrafficPolicy": "Cluster",
        "ipFamilies": [
            "IPv4"
        ],
        "ipFamilyPolicy": "SingleStack",
        "ports": [
            {
                "nodePort": 31600,
                "port": 3000,
                "protocol": "TCP",
                "targetPort": 3000
            }
        ],
        "selector": {
            "app": "frontend"
        },
        "sessionAffinity": "None",
        "type": "NodePort"
    },
    "status": {
        "loadBalancer": {}
    }
}

任何想法表示赞赏。 多谢你们。


可能不是理想的解决方案,但您可以尝试将 externalTrafficPolicy 更改为 Local。这将防止对不运行应用程序的节点进行健康检查失败。这样流量只会转发到应用所在的节点。将 externalTrafficPolicy 设置为 local 也是保留连接源 IP 的要求。另外,您能否分享您正在使用的 NLB 和 LB 的运行状况检查配置。当您更改 externalTrafficPolicy 时,请注意,LB 的运行状况检查将发生变化,并且需要将同样的情况应用于 NLB。

编辑:另请注意,您需要将安全列表/网络安全组添加到节点子网/节点池中,以允许来自工作节点子网的所有协议上的流量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kubernetes NodePort 并非在所有节点上都可用 - Oracle Cloud Infrastructure (OCI) 的相关文章

随机推荐