iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
DevOps

那些文件沒告訴你的 AWS EKS系列 第 16

[16] 為什麼使用 security group for pod 使用 liveness/readiness probes 需要設定環境變數 DISABLE_TCP_EARLY_DEMUX

  • 分享至 

  • xImage
  •  

根據 EKS Security groups for pods [1] 文件,如果 Pod 使用 liveness/readiness probes 時,則需要設置 VPC CNI plugin DISABLE_TCP_EARLY_DEMUX=ture 環境變數。

環境變數 DISABLE_TCP_EARLY_DEMUX

VPC CNI plugin [2] 若在 DISABLE_TCP_EARLY_DEMUX=ture,則會在 initContainer [3]amazon-k8s-cni-init 設定對應的 kernel 參數 net.ipv4.tcp_early_demux

# Set DISABLE_TCP_EARLY_DEMUX to true to enable kubelet to pod-eni TCP communication
# https://lwn.net/Articles/503420/ and https://github.com/aws/amazon-vpc-cni-k8s/pull/1212 for background
if [ "${DISABLE_TCP_EARLY_DEMUX:-false}" == "true" ]; then
    sysctl -w "net.ipv4.tcp_early_demux=0"
else
    sysctl -e -w "net.ipv4.tcp_early_demux=1"
fi

不過提到此變數將會提高些微的本地端 TCP 連線延遲。

This will increase the local TCP connection latency slightly.

而根據 kernel 參數 [4]

tcp_early_demux - BOOLEAN
    Enable early demux for established TCP sockets.
    Default: 1

然而上述 kernel 參數文件並未完整解釋 tcp_early_demux 及為什麼可能影響本地端 TCP 延遲問題。

而在 VPC CNI plugin - Add support to toggle TCP early demux #1212 解釋為什麼需要啟用此 kernel 參數:

了解一下運作

可以確認 net->ipv4.sysctl_ip_early_demux 作為 kernel 參數使用於 ip_rcv_finish function:

static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
    const struct iphdr *iph = ip_hdr(skb);
    int (*edemux)(struct sk_buff *skb);
    struct net_device *dev = skb->dev;
    struct rtable *rt;
    int err;

    /* if ingress device is enslaved to an L3 master device pass the
    * skb to its handler for processing
    */
    skb = l3mdev_ip_rcv(skb);
    if (!skb)
        return NET_RX_SUCCESS;

    if (net->ipv4.sysctl_ip_early_demux &&                      ---> kernel parameter: sysctl_ip_early_demux
        !skb_dst(skb) &&
        !skb->sk &&
        !ip_is_fragment(iph)) {
        const struct net_protocol *ipprot;
        int protocol = iph->protocol;

        ipprot = rcu_dereference(inet_protos[protocol]);
        if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) {
            err = edemux(skb);
            if (unlikely(err))
                goto drop_error;
            /* must reload iph, skb->head might have changed */
            iph = ip_hdr(skb);
        }
    }

    /*
    *    Initialise the virtual path cache for the packet. It describes
    *    how the packet travels inside Linux networking.
    */
    if (!skb_valid_dst(skb)) {
        err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
                    iph->tos, dev);
        if (unlikely(err))
            goto drop_error;
    }

tcp_v4_early_demux() function

int tcp_v4_early_demux(struct sk_buff *skb)
{
....
....
    sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
                    iph->saddr, th->source,
                    iph->daddr, ntohs(th->dest),
                    skb->skb_iif, inet_sdif(skb));
    if (sk) {
        skb->sk = sk;
        skb->destructor = sock_edemux;
        if (sk_fullsock(sk)) {
            struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst);

            if (dst)
                dst = dst_check(dst, 0);
            if (dst &&
                inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
                skb_dst_set_noref(skb, dst);
        }
    }
    return 0;
}

由上述可以了解 tcp_v4_early_demux 檢查是否有建立連線的 socket,若有找到則將 dst 設定到 socket cache 中,因此可以節省尋找 routing 的過程。

問題

如前兩天討論 security group for pod 流程,是使用額外的 Trunk interface 介接設定 vlan 對接 Pod veth。因此使用 security group for pod 的 Pod,流量從 eth0 出去並經由 Trunk interface 回來,因此 Pod SYN-ACK 或 ACK 封包會因 tcp_early_demux 機制而被丟棄。

  1. 從 Kubelet 到 pod-eni:Kubelet 發送 SYN 封包,Pod 以 SYN-ACK 響應,但 kernel 在主機 veth dev 中接收到封包後丟棄了該封包。
  2. 從 pod-eni 到 kubelet:Pod-eni 發送 ACK 以響應來自 kubelet 的 SYN-ACK,但 ACK pkt 在主機 veth dev 後再次被 kernel 丟棄。

總結

tcp_v4_early_demux kernel 參數可以作為 kernel socket protocol stack 的 cache 機制,但是在使用 security group for pod 時,則會導致 kubelet 在進行 liveness/readiness probes 時被 kernel 機制判定而丟棄封包。因此需要啟用此 DISABLE_TCP_EARLY_DEMUX=ture 環境變數。


以上資訊透過 EKS 所提供 Logs 來驗證上游 Kubernetes 運作原理,倘若上述內文有所錯誤,隨時可以留言或是私訊我。

參考文件

  1. Security groups for pods - Configure the Amazon VPC CNI add-on for security groups for pods - https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html#security-groups-pods-deployment
  2. https://github.com/aws/amazon-vpc-cni-k8s#disable_tcp_early_demux-v173
  3. https://github.com/aws/amazon-vpc-cni-k8s/blob/master/scripts/init.sh#L53-L59
  4. https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  5. https://github.com/aws/amazon-vpc-cni-k8s/pull/1212#issuecomment-693540666

上一篇
[15] 為什麼 security group 可以關聯至單獨的 EKS Pod - Security groups for pods(二)
下一篇
[17] 為什麼 Fluent Bit/FluentD 可以收集 EKS cluster 上 Pod logs
系列文
那些文件沒告訴你的 AWS EKS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言