全部产品
Search
文档中心

容器服务 Kubernetes 版 ACK:容器网络FAQ

更新时间:Mar 18, 2024

本文为您介绍使用网络插件Terway或Flannel遇到的常见问题,以及如何解决。例如,如何选择网络插件、集群是否支持安装第三方网络插件、如何规划集群网络等。

索引

Terway相关

Flannel相关

kube-proxy相关

IPv6相关

如何解决IPv6双栈的部分常见问题?

其他

Terway网络模式下增加了虚拟交换机后,集群无法访问公网怎么办?

问题现象

在Terway网络下,因Pod没有IP资源而手动增加虚拟交换机,在增加虚拟交换机后,发现集群不能正常访问公网。

问题原因

Pod IP所属的虚拟交换机不具备公网访问的能力。

解决方法

您可以通过NAT网关的SNAT功能,为Pod IP所属的虚拟交换机配置公网SNAT规则。更多信息,请参见为已有集群开启公网访问能力

手动升级了Flannel镜像版本后,如何解决无法兼容1.16以上版本集群的问题?

问题现象

集群版本升级到1.16之后,集群节点变成NotReady。

问题原因

手动升级了Flannel版本,而并没有升级Flannel的配置,导致Kubelet无法识别。

解决方法

  1. 执行以下命令,编辑Flannel,增加cniVersion字段。

    kubectl edit cm kube-flannel-cfg -n kube-system 

    返回结果中增加cniVersion字段。

    "name": "cb0",   
    "cniVersion":"0.3.0",
    "type": "flannel",
  2. 执行以下命令,重启Flannel。

    kubectl delete pod -n kube-system -l app=flannel

如何解决Pod启动后存在时延的问题?

问题现象

Pod启动后网络需要延迟一会才能通信。

问题原因

配置Network Policy会有一定的时延,关闭Network Policy后,就能解决该问题。

解决方法

  1. 执行以下命令,修改Terway的ConfigMap,增加禁用NetworkPolicy的配置。

    kubectl edit cm -n kube-system eni-config 

    在返回结果中增加以下字段。

    disable_network_policy: "true"
  2. 可选:如果Terway版本不是最新的,请在控制台升级Terway版本。

    1. 登录容器服务管理控制台,在左侧导航栏选择集群

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理

    3. 组件管理页面,单击网络页签,单击目标Terway组件区域的升级

    4. 提示对话框,单击确定

  3. 执行以下命令,重启所有Terway的Pod。

     kubectl delete pod -n kube-system -l app=terway-eniip

如何让Pod访问自己暴露的服务?

问题现象

Pod无法访问自己暴露的服务,存在时好时坏或者调度到自己就出问题的现象。

问题原因

Flannel集群可能未开启回环访问。

说明
  • 低于v0.15.1.4-e02c8f12-aliyun版本的Flannel不允许回环访问。升级版本后,仍默认不允许回环访问,但可以手动开启。

  • 只有全新部署的v0.15.1.4-e02c8f12-aliyun及以上版本的Flannel,才默认开启回环访问。

解决方法

  • 使用Headless Service暴露服务和访问,具体操作,请参见Headless Services

    说明

    推荐使用此方法。

  • 重建集群使用Terway的网络插件,具体操作,请参见使用Terway网络插件

  • 修改Flannel的配置,然后重建Flannel和Pod。

    说明

    不推荐此方法,可能会被后续升级覆盖。

    1. 执行以下命令编辑cni-config.json

      kubectl edit cm kube-flannel-cfg -n kube-system
    2. 在返回结果的delegate中增加hairpinMode: true

      示例如下:

      cni-conf.json: |
          {
            "name": "cb0",
            "cniVersion":"0.3.1",
            "type": "flannel",
            "delegate": {
              "isDefaultGateway": true,
              "hairpinMode": true
            }
          }
    3. 执行以下命令,重启Flannel。

      kubectl delete pod -n kube-system -l app=flannel   
    4. 删除并重新创建Pod。

如何选择Kubernetes集群Terway和Flannel网络插件?

下面为您详细介绍在ACK创建集群时使用的两种网络插件:Terway和Flannel。

在创建Kubernetes集群时,阿里云容器服务提供以下两种网络插件:

  • Flannel:使用的是简单稳定的社区的Flannel CNI插件,配合阿里云的VPC的高速网络,能给集群高性能和稳定的容器网络体验,但功能偏简单,支持的特性少,例如:不支持基于Kubernetes标准的Network Policy。

  • Terway:是阿里云容器服务自研的网络插件,功能上完全兼容Flannel,支持将阿里云的弹性网卡分配给容器,支持基于Kubernetes标准的NetworkPolicy来定义容器间的访问策略,支持对单个容器做带宽的限流。对于不需要使用Network Policy的用户,可以选择Flannel,其他情况建议选择Terway。了解更多Terway网络插件的相关内容,请参见使用Terway网络插件

如何规划集群网络?

在创建ACK集群时,需要指定专有网络VPC、虚拟交换机、Pod网络CIDR(地址段)和Service CIDR(地址段)。建议您提前规划ECS地址、Kubernetes Pod地址和Service地址。详情请参见Kubernetes集群网络规划

ACK是否支持hostPort的端口映射?

  • 只有Flannel插件支持hostPort,其他插件暂不支持hostPort。

  • 容器服务ACK的Pod地址是可以直接被VPC中其他资源访问的,不需要额外的端口映射。

  • 如果需要把服务暴露到外部,可以使用NodePort或者LoadBalancer类型的Service。

如何查看集群的网络类型及对应的虚拟交换机?

ACK支持两种容器网络类型,分别是Flannel网络类型和Terway网络类型。

通过以下步骤查看您创建集群时所选择的网络类型

  1. 登录容器服务管理控制台,在左侧导航栏单击集群

  2. 在集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情

  3. 单击基本信息页签,在集群信息区域查看集群的容器网络类型,即网络插件右侧的值。

    • 如果网络插件右侧显示terway-eniip ,则容器的网络类型为Terway网络。

    • 如果网络插件右侧显示Flannel,则容器的网络类型为Flannel网络。

通过以下步骤查看对应网络类型使用的节点虚拟交换机

  1. 登录容器服务管理控制台,在左侧导航栏单击集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择节点管理 > 节点池

  3. 节点池页面,单击目标节点池右侧操作列下的详情

    节点配置区域查看节点虚拟交换机ID。

通过以下步骤查询Terway网络类型使用的Pod虚拟交换机ID

说明

只有Terway网络类型使用Pod虚拟交换机,Flannel网络类型无需使用Pod虚拟交换机。

  1. 登录容器服务管理控制台,在左侧导航栏单击集群

  2. 在集群列表中单击目标集群名称或目标集群右侧操作列下的详情

  3. 在集群信息页面,单击集群资源页签,然后查看Pod虚拟交换机ID。

如何查看集群中使用的云资源?

通过以下步骤查看集群中使用的云资源信息,包括虚拟机、虚拟专有网络VPC、Worker RAM角色等。

  1. 登录容器服务管理控制台,在左侧导航栏单击集群

  2. 在集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情

  3. 单击集群资源页签,查看集群中使用的云资源信息。

如何修改kube-proxy配置?

ACK托管版默认部署kube-proxy-worker DaemonSet作为负载均衡,可通过其同名配置项kube-proxy-worker ConfigMap控制其参数。如果您使用的是ACK专有版,您在集群中会额外部署kube-proxy-master DaemonSet和同名配置项,其会运行于Master节点上。

kube-proxy配置项均兼容社区KubeProxyConfiguration标准,您可以参考社区KubeProxyConfiguration标准进行自定义配置,更多信息,请参见kube-proxy Configuration。kube-proxy配置文件对格式要求严格,请勿漏填冒号和空格。修改kube-proxy配置操作如下:

  • 如果您使用的是托管版集群,您需要修改kube-proxy-worker的配置。

    1. 登录容器服务管理控制台,在左侧导航栏单击集群

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择配置管理 > 配置项

    3. 在顶部选择kube-system命名空间,然后单击配置项kube-proxy-worker右侧的YAML编辑

    4. 查看YAML面板上修改参数,然后单击确定

    5. 重建所有名为kube-proxy-worker的容器,使配置生效。

      重要

      kube-proxy的重启不会导致已有运行业务中断,如果有并发业务发布,新启动的业务在kube-proxy的生效时间会略有延迟,请尽量于业务低峰期操作。

      1. 在集群管理页左侧导航栏中,选择工作负载 > 守护进程集

      2. 在守护进程集列表中,找到并单击kube-proxy-worker

      3. kube-proxy-worker页面的容器组页签下,选择更多 > 删除,然后单击确定

        重复操作删除所有容器组。删除容器组后,系统会自动重建所有容器。

  • 如果您使用的是专有版集群,您需要修改kube-proxy-worker和kube-proxy-master的配置,然后删除kube-proxy-worker和kube-proxy-master Pod,该Pod自动重新创建后会使配置生效。具体操作,请参见上文。

如何提升Linux连接跟踪Conntrack数量限制?

内核日志(dmesg)中出现conntrack full的报错日志,说明Conntrack数量已经达到conntrack_max数量限制。您需要提升Linux连接跟踪Conntrack数量限制。

  1. 执行conntrack -L命令,确认目前Conntrack中的各协议占用情况。

    • 如果出现大量TCP协议的占用,您需要确认具体业务,如果是短连接型应用可以考虑整改成长连接型。

    • 如果出现大量DNS的占用,您需要在ACK集群中使用NodeLocal DNSCache,提高DNS的性能,具体操作,请参见使用NodeLocal DNSCache

  2. 如果Conntrack实际占用情况合理,或者您不希望对业务进行整改,您可以通过配置kube-proxy增加maxPerCore参数,调整连接跟踪数量限制。

    • 如果您使用的是托管版集群,您需要在kube-proxy-worker中增加maxPerCore参数,并设置其值为65536或更高的数值,然后删除kube-proxy-worker Pod,该Pod自动重新创建后会使配置生效。关于如何修改并删除kube-proxy-worker,请参见如何修改kube-proxy配置?

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: kube-proxy-worker
        namespace: kube-system
      data:
        config.conf: |
          apiVersion: kubeproxy.config.k8s.io/v1alpha1
          kind: KubeProxyConfiguration
          featureGates:
            IPv6DualStack: true
          clusterCIDR: 172.20.0.0/16
          clientConnection:
            kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
          conntrack:
            maxPerCore: 65536 # 需设置maxPerCore至合理值,此处65536为默认设置。
          mode: ipvs
      # 其它略
    • 如果您使用的是专有版集群,您需要在kube-proxy-worker和kube-proxy-master中增加maxPerCore参数,并设置其值为65536或更高的数值,然后删除kube-proxy-worker和kube-proxy-master Pod,该Pod自动重新创建后会使配置生效。关于如何修改并删除kube-proxy-worker和kube-proxy-master,请参见如何修改kube-proxy配置?

如何修改kube-proxy中IPVS负载均衡模式?

您可以通过修改kube-proxy中IPVS负载均衡模式来解决大量长连接的负载不均问题,具体操作如下:

  1. 选择合适的调度算法。关于如何选择合适的调度算法,请参见K8s官方文档parameter-changes

  2. 早于2022年10月创建的集群节点可能未默认启用所有IPVS调度算法,您需要手动在所有集群节点上启用IPVS调度算法内核模块(以最小连接数调度算法lc为例,如果选用其他算法,请替换lc关键字),逐台登录每个节点,并运行lsmod | grep ip_vs_lc查看是否有输出。

    • 如果命令输出ip_vs_lc,则说明调度算法内核模块已经加载,可以跳过本步骤。

    • 如果没有加载,运行modprobe ip_vs_lc使节点立即生效,并运行echo "ip_vs_lc" >> /etc/modules-load.d/ack-ipvs-modules.conf使机器重启后生效。

  3. 设置kube-proxy中的ipvs scheduler参数值为合理的调度算法。

    • 如果您使用的是托管版集群,您需要修改kube-proxy-worker的ipvs scheduler参数值为合理的调度算法,然后删除kube-proxy-worker Pod,该Pod自动重新创建后会使配置生效。关于如何修改并删除kube-proxy-worker,请参见如何修改kube-proxy配置?

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: kube-proxy-worker
        namespace: kube-system
      data:
        config.conf: |
          apiVersion: kubeproxy.config.k8s.io/v1alpha1
          kind: KubeProxyConfiguration
          featureGates:
            IPv6DualStack: true
          clusterCIDR: 172.20.0.0/16
          clientConnection:
            kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
          conntrack:
            maxPerCore: 65536
          mode: ipvs
          ipvs:
            scheduler: lc # 需设置scheduler成合理的调度算法。
      # 其它略
    • 如果您使用的是专有版集群,您需要修改kube-proxy-worker和kube-proxy-master中的ipvs scheduler参数值为合理的调度算法,然后删除kube-proxy-worker和kube-proxy-master Pod,该Pod自动重新创建后会使配置生效。关于如何修改并删除kube-proxy-worker和kube-proxy-master,请参见如何修改kube-proxy配置?

  4. 查看kube-proxy运行日志。

    • 通过kubectl get pods命令查看kube-system命名空间下新建的kube-proxy-worker容器(如果您使用专有版集群,还需查看kube-proxy-master)是否为Running状态。

    • 通过kubectl logs命令查看新建容器的日志。

      • 如果出现Can't use the IPVS proxier: IPVS proxier will not be used because the following required kernel modules are not loaded: [ip_vs_lc]则说明IPVS调度算法内核模块未成功加载,您需要检查上述步骤是否已经正确执行,并尝试重试。

      • 如果出现Using iptables Proxier.说明kube-proxy无法启用IPVS模块,开始自动回退使用iptables模式,此时建议先回滚kube-proxy配置,再对机器进行重启操作。

      • 如果未出现上述日志,并显示Using ipvs Proxier.说明IPVS模块成功启用。

    • 如果上述检查均返回正常,说明变更成功。

如何修改kube-proxy中IPVS UDP会话保持的超时时间?

如果您的ACK集群使用了kube-proxy IPVS模式,IPVS的默认会话保持策略会使UDP协议后端在摘除后五分钟内出现概率性丢包的问题。如果您业务依赖于CoreDNS,当CoreDNS组件升级或所在节点重启时,您可能会在五分钟内遇到业务接口延迟、请求超时等现象。

若您在ACK集群中的业务没有使用UDP协议,您可以通过降低IPVS UDP协议的会话保持的超时时间来减少解析延迟或失败的影响时间。具体操作如下:

说明

若您的自有业务使用了UDP协议,请提交工单咨询。

  • K8s 1.18及以上版本集群

    • 如果您使用的是托管版集群,您需要在kube-proxy-worker中修改udpTimeout参数值。然后删除kube-proxy-worker Pod,该Pod自动重新创建后会使配置生效。关于如何修改并删除kube-proxy-worker,请参见如何修改kube-proxy配置?

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: kube-proxy-worker
        namespace: kube-system
      data:
        config.conf: |
          apiVersion: kubeproxy.config.k8s.io/v1alpha1
          kind: KubeProxyConfiguration
          # 其它不相关字段已省略。
          mode: ipvs
          # 如果ipvs键不存在,需要添加此键。
          ipvs:
            udpTimeout: 10s # 此处默认为300秒,调整成10秒可以将IPVS UDP类型后端摘除后丢包问题的影响时间缩短到10秒。
    • 如果您使用的是专有版集群,您需要在kube-proxy-worker和kube-proxy-master中修改udpTimeout参数值。然后删除kube-proxy-worker和kube-proxy-master Pod,该Pod自动重新创建后会使配置生效。关于如何修改并删除kube-proxy-worker,请参见如何修改kube-proxy配置?

  • K8s 1.16及以下版本集群

    此类版本集群的kube-proxy不支持udpTimeout参数,推荐使用系统运维管理 OOS(CloudOps Orchestration Service)批量在所有集群机器上执行ipvsadm命令以调整UDP超时时间配置。命令如下:

    yum install -y ipvsadm
    ipvsadm -L --timeout > /tmp/ipvsadm_timeout_old
    ipvsadm --set 900 120 10
    ipvsadm -L --timeout > /tmp/ipvsadm_timeout_new
    diff /tmp/ipvsadm_timeout_old /tmp/ipvsadm_timeout_new

    关于OOS的批量操作实例介绍,请参见批量操作实例

如何解决IPv6双栈的部分常见问题?

  • 问题现象:在kubectl中显示的Pod IP仍然是IPv4地址。

    解决方法:执行以下命令,展示Pod IPs字段,预期输出IPv6地址。

    kubectl get pods -A -o jsonpath='{range .items[*]}{@.metadata.namespace} {@.metadata.name} {@.status.podIPs[*].ip} {"\n"}{end}'
  • 问题现象:在kubectl中显示的Cluster IP仍然是IPv4地址。

    解决方法:

    1. 请确认spec.ipFamilyPolicy配置的不是SingleStack。

    2. 执行以下命令,展示Cluster IPs字段,预期输出IPv6地址。

      kubectl get svc -A -o jsonpath='{range .items[*]}{@.metadata.namespace} {@.metadata.name} {@.spec.ipFamilyPolicy} {@.spec.clusterIPs[*]} {"\n"}{end}'
  • 问题现象:无法通过IPv6地址访问Pod。

    问题原因:部分应用默认不监听IPv6地址,例如Nginx容器。

    解决方法:执行netstat -anp命令,确认Pod已监听IPv6地址。

    预期输出:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 127.0.XX.XX:10248         0.0.0.0:*               LISTEN      8196/kubelet
    tcp        0      0 127.0.XX.XX:41935         0.0.0.0:*               LISTEN      8196/kubelet
    tcp        0      0 0.0.XX.XX:111             0.0.0.0:*               LISTEN      598/rpcbind
    tcp        0      0 0.0.XX.XX:22              0.0.0.0:*               LISTEN      3577/sshd
    tcp6       0      0 :::30500                :::*                    LISTEN      1916680/kube-proxy
    tcp6       0      0 :::10250                :::*                    LISTEN      8196/kubelet
    tcp6       0      0 :::31183                :::*                    LISTEN      1916680/kube-proxy
    tcp6       0      0 :::10255                :::*                    LISTEN      8196/kubelet
    tcp6       0      0 :::111                  :::*                    LISTEN      598/rpcbind
    tcp6       0      0 :::10256                :::*                    LISTEN      1916680/kube-proxy
    tcp6       0      0 :::31641                :::*                    LISTEN      1916680/kube-proxy
    udp        0      0 0.0.0.0:68              0.0.0.0:*                           4892/dhclient
    udp        0      0 0.0.0.0:111             0.0.0.0:*                           598/rpcbind
    udp        0      0 47.100.XX.XX:323           0.0.0.0:*                           6750/chronyd
    udp        0      0 0.0.0.0:720             0.0.0.0:*                           598/rpcbind
    udp6       0      0 :::111                  :::*                                598/rpcbind
    udp6       0      0 ::1:323                 :::*                                6750/chronyd
    udp6       0      0 fe80::216:XXXX:fe03:546 :::*                                6673/dhclient
    udp6       0      0 :::720                  :::*                                598/rpcbind

    Proto显示为tcp即监听IPv4地址,显示为tcp6即监听IPv6地址。

  • 问题现象:通过IPv6地址可以在集群内访问Pod,但无法从公网访问。

    问题原因:该IPv6地址可能未配置公网带宽。

    解决方法:配置该IPv6地址的公网带宽。具体操作,请参见开通和管理IPv6公网带宽

  • 问题现象:无法通过IPv6 Cluster IP访问Pod。

    解决方法:

    1. 请确认spec.ipFamilyPolicy配置的不是SingleStack。

    2. 执行netstat -anp命令,确认Pod已监听IPv6地址。

      预期输出:

      Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
      tcp        0      0 127.0.XX.XX:10248         0.0.0.0:*               LISTEN      8196/kubelet
      tcp        0      0 127.0.XX.XX:41935         0.0.0.0:*               LISTEN      8196/kubelet
      tcp        0      0 0.0.XX.XX:111             0.0.0.0:*               LISTEN      598/rpcbind
      tcp        0      0 0.0.XX.XX:22              0.0.0.0:*               LISTEN      3577/sshd
      tcp6       0      0 :::30500                :::*                    LISTEN      1916680/kube-proxy
      tcp6       0      0 :::10250                :::*                    LISTEN      8196/kubelet
      tcp6       0      0 :::31183                :::*                    LISTEN      1916680/kube-proxy
      tcp6       0      0 :::10255                :::*                    LISTEN      8196/kubelet
      tcp6       0      0 :::111                  :::*                    LISTEN      598/rpcbind
      tcp6       0      0 :::10256                :::*                    LISTEN      1916680/kube-proxy
      tcp6       0      0 :::31641                :::*                    LISTEN      1916680/kube-proxy
      udp        0      0 0.0.0.0:68              0.0.0.0:*                           4892/dhclient
      udp        0      0 0.0.0.0:111             0.0.0.0:*                           598/rpcbind
      udp        0      0 47.100.XX.XX:323           0.0.0.0:*                           6750/chronyd
      udp        0      0 0.0.0.0:720             0.0.0.0:*                           598/rpcbind
      udp6       0      0 :::111                  :::*                                598/rpcbind
      udp6       0      0 ::1:323                 :::*                                6750/chronyd
      udp6       0      0 fe80::216:XXXX:fe03:546 :::*                                6673/dhclient
      udp6       0      0 :::720                  :::*                                598/rpcbind

      Proto显示为tcp即监听IPv4地址,显示为tcp6即监听IPv6地址。

    3. 问题现象:Pod无法通过IPv6访问公网。

      解决方法:对IPv6使用公网,需要开通IPv6网关,并对IPv6地址配置公网带宽。详细信息,请参见创建和管理IPv6网关开通和管理IPv6公网带宽

容器服务Kubernetes的Terway网络场景中交换机的IP资源不足

  • 问题描述

在创建Pod时发现无法创建,登录VPC控制台,选择目标地域,在左侧导航栏单击交换机,查看集群使用的交换机(vSwitch)信息,发现该vSwitch可用IP数为0。如何进一步确认问题请参见更多信息

  • 问题原因

该节点的Terway所使用的vSwitch没有空余IP地址,导致Pod会因为没有IP资源而一直处于ContainerCreating状态。

  • 解决方案

    您可以参考以下内容,扩容vSwitch,即添加新的vSwitch,扩容集群的IP资源:

    1. 登录VPC控制台,选择目标地域,创建新的vSwitch。

      说明

      该vSwitch必须与IP资源不足的vSwitch在同一个地域和可用区。如果Pod密度越来越大,建议给Pod使用的vSwitch网段的网络位小于等于19,也就是网段至少包含8192个IP地址。

    2. 参考以下命令,删除全部Terway Pod,删除后Terway Pod会重新创建。

      说明

      如果您在创建集群时,使用Terway并勾选了Pod独占弹性网卡以获得最佳性能,说明您是ENI单IP;没有勾选则是ENI多IP,详细信息请参见Terway网络插件

      • 针对ENI多IP场景:kubectl delete -n kube-system pod -l app=terway-eniip

      • 针对ENI单IP场景:kubectl delete -n kube-system pod -l app=terway-eni

    3. 然后执行kubectl get pod命令,确认全部Terway Pod重建成功。

    4. 创建新的Pod,确认Pod创建成功且可以重新vSwitch成功分配获得IP。

  • 更多信息

    连接Kubernetes集群,如何连接请参见通过kubectl连接Kubernetes集群,执行kubectl get pod命令,发现Pod状态为ContainerCreating。执行以下命令,查看Pod所在节点上的Terway容器的日志。

    kubectl get pod -l app=terway-eniip -n kube-system | grep [$Node_Name] # [$Node_Name] 为Pod所在节点的节点名,用来找出该节点上的Terway Pod的名称
    kubectl logs --tail=100 -f [$Pod_Name] -n kube-system -c terway # [$Pod_Name]为Pod所在节点上的Terway Pod的名称。

    系统显示类似如下,出现类似InvalidVSwitchId.IpNotEnough错误信息,表明存在交换机IP不足的情况。

    time="2020-03-17T07:03:40Z" level=warning msg="Assign private ip address failed: Aliyun API Error: RequestId: 2095E971-E473-4BA0-853F-0C41CF52651D Status Code: 403 Code: InvalidVSwitchId.IpNotEnough Message: The specified VSwitch \"vsw-AAA\" has not enough IpAddress., retrying"

Terway网络模式下,Pod分配的IP不在虚拟交换机网段中怎么办?

问题现象

在Terway网络下,创建的Pod IP不在配置的虚拟交换机网段内。

问题原因

Pod IP来源于VPC地址,并且通过ENI分配给容器使用。只有在新建ENI时,才可以配置虚拟交换机。如果ENI已经创建,则Pod IP将继续从该ENI对应的虚拟交换机中分配。

通常以下两个使用场景会遇到该问题:

  • 纳管一个节点到集群内,但这个节点之前在其他集群使用,且删除节点时没有排空节点Pod。这种情况下节点上可能残留之前集群使用的ENI资源。

  • 手动增加、修改Terway使用的虚拟交换机配置,由于节点上可能还存在原有配置的ENI,则新建的Pod将可能继续使用原有ENI上的IP。

解决方法

您可以通过新建节点、轮转老节点的方式来确保配置文件在新节点上生效。

Terway网络模式扩容vSwitch后,依然无法分配Pod IP怎么办?

问题现象

在Terway网络下,Terway网络模式扩容vSwitch后依然无法分配Pod IP。

问题原因

Pod IP来源于VPC地址,并且通过ENI分配给容器使用。只有在新建ENI时,才可以配置虚拟交换机。如果ENI已经创建,则Pod IP将继续从该ENI对应的虚拟交换机中分配。由于节点上ENI配额已经用完,无法新建ENI,也就无法让新配置生效。关于ENI配额的具体信息,请参见弹性网卡概述

解决方法

您可以通过新建节点、轮转老节点的方式来确保配置文件在新节点上生效。

如何为Terway IPvlan集群开启集群内负载均衡?

问题现象

在IPvlan模式下,v1.2.0及以上版本的Terway,新建的集群默认开启集群内负载均衡功能。在集群内访问ExternalIP,LoadBalancer流量将被负载到Service网络。如何为已创建的Terway IPvlan集群开启集群内负载均衡?

问题原因

Kube-Proxy会短路集群内访问ExternalIP、LoadBalancer的流量,即集群内访问这些外部地址,实际流量不会到外部,而会被转为对应后端的Endpoint直接访问。在Terway IPvlan模式下,Pod访问这些地址流量由Cilium而不是kube-proxy进行处理, 在Terway v1.2.0之前版本并不支持这种链路的短路。在Terway v1.2.0版本发布后,新建集群将默认开启该功能,已创建的集群不会开启。

解决方法

说明
  • Terway需要v1.2.0及以上版本,且使用IPvlan模式。

  • 如果集群未启用IPvlan模式,则该配置无效,无需配置。

  • 新建集群此功能默认开启,无需配置。

  1. 执行以下命令,修改Terway的配置ConfigMap。

    kubectl edit cm eni-config -n kube-system
  2. eni_conf中增加以下内容。

    in_cluster_loadbalance: "true"
    说明

    请保持in_cluster_loadbalanceeni_conf在同级别。

  3. 执行以下命令,重建Terway Pod,使集群内负载均衡配置生效。

    kubectl delete pod -n kube-system -l app=terway-eniip

    验证配置

    执行以下命令,检查terway-ennippolicy日志,如果显示enable-in-cluster-loadbalance=true则配置生效。

    kubectl logs -n kube-system <terway pod name> policy | grep enable-in-cluster-loadbalance

如何在ACK中对Terway网络下的Pod指定网段加白?

问题现象

您通常需要在一些类似数据库之类的服务设置白名单,以此来给服务提供更安全的访问控制能力。在容器网络下同样有此需求,需要在容器中给动态变化的Pod IP设置白名单。

问题原因

ACK的容器网络主要有Flannel和Terway两种:

  • 在Flannel网络下,因为Pod是通过节点访问其他服务,所以在Flannel网络下的数据库设置白名单时,首先可以将客户端Pod通过节点绑定的方式调度到固定的少数节点上去,然后在数据库侧直接对节点的IP地址做加白操作即可。

  • 在Terway网络下,Pod IP是通过ENI提供。Pod通过ENI访问外部服务,外部服务得到的客户端IP是ENI提供的IP地址,即使把Pod和节点设置了亲和性绑定,Pod访问外部服务的客户端IP仍然是ENI提供的IP而不是节点的IP。Pod IP还是会从Terway指定的vSwitch中随机分配IP地址,而且客户端Pod通常都会有自动伸缩之类的配置,那即使能固定Pod IP也很难满足弹性伸缩的场景,建议直接给客户端指定一个网段来分配IP,然后在数据库侧对这个网段来做加白操作。

解决方法

通过给指定节点添加标签来指定Pod使用的vSwitch,从而当Pod调度到有固定标签的节点上时,该Pod就可以通过自定义的vSwitch去创建Pod IP。

  1. 在kube-system命名空间下单独创建一个名称为eni-config-fixed的ConfigMap ,其中需要指定专门的vSwitch。

    本示例以vsw-2zem796p76viir02c****,10.2.1.0/24为例。

    apiVersion: v1
    data:
      eni_conf: |
        {
           "vswitches": {"cn-beijing-h":["vsw-2zem796p76viir02c****"]},
           "security_group": "sg-bp19k3sj8dk3dcd7****",
           "security_groups": ["sg-bp1b39sjf3v49c33****","sg-bp1bpdfg35tg****"]
        }
    kind: ConfigMap
    metadata:
      name: eni-config-fixed
      namespace: kube-system
    
                            
  2. 创建节点池,为节点打上标签terway-config:eni-config-fixed。关于创建节点池的具体操作,请参见操作步骤

    为了保证该节点池内的节点上不会出现其他Pod,可以给该节点池同时配置上污点,例如fixed=true:NoSchedule节点标签.png

  3. 扩容该节点池。具体操作,请参见扩缩容ACK集群的节点

    通过该节点池扩容出来的节点默认会带有上一步设置的节点标签和污点。

  4. 创建Pod,调度到已有terway-config:eni-config-fixed标签的节点上,需要添加容忍。

    apiVersion: apps/v1 # 1.8.0以前的版本请使用apps/v1beta1。
    kind: Deployment
    metadata:
      name: nginx-fixed
      labels:
        app: nginx-fixed
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx-fixed
      template:
        metadata:
          labels:
            app: nginx-fixed
        spec:
          tolerations:        # 添加容忍。
          - key: "fixed"
            operator: "Equal"
            value: "true"
            effect: "NoSchedule"
          nodeSelector:
            terway-config: eni-config-fixed
          containers:
          - name: nginx
            image: nginx:1.9.0 #替换成您实际的镜像<image_name:tags>。
            ports:
            - containerPort: 80

    结果验证

    1. 执行以下命令,查看Pod IP。

      kubectl get po -o wide | grep fixed

      预期输出:

      nginx-fixed-57d4c9bd97-l****                   1/1     Running             0          39s    10.2.1.124    bj-tw.062149.aliyun.com   <none>           <none>
      nginx-fixed-57d4c9bd97-t****                   1/1     Running             0          39s    10.2.1.125    bj-tw.062148.aliyun.com   <none>           <none>

      可以看到Pod IP已经从指定的vSwitch分配。

    2. 执行以下命令,将Pod扩容到30个。

      kubectl scale deployment nginx-fixed --replicas=30

      预期输出:

      nginx-fixed-57d4c9bd97-2****                   1/1     Running     0          60s     10.2.1.132    bj-tw.062148.aliyun.com   <none>           <none>
      nginx-fixed-57d4c9bd97-4****                   1/1     Running     0          60s     10.2.1.144    bj-tw.062149.aliyun.com   <none>           <none>
      nginx-fixed-57d4c9bd97-5****                   1/1     Running     0          60s     10.2.1.143    bj-tw.062148.aliyun.com   <none>           <none>
      ...

      可以看到生成的Pod IP全部在指定的vSwitch下,然后在数据库侧直接对此vSwitch做加白操作,从而实现给动态Pod IP做访问控制。

说明
  • 建议您使用新创建的节点,如果使用已有节点,需要在节点添加进集群之前先将ENI和ECS实例解绑,再添加进集群。添加方式要选用自动添加已有节点(替换系统盘)。具体操作,请参见解绑辅助弹性网卡自动添加节点

  • 注意给特定的节点池打上标签和污点,尽可能保证不需要加白的业务不会调度到这部分节点上。

  • 这个设置白名单的方法其实是配置覆盖,ACK会用现在指定的ConfigMap里的配置来覆盖之前的eni-config的配置,关于配置参数的具体信息,请参见Terway节点动态配置

  • 指定vSwitch的IP个数建议为预计Pod个数的2倍(或更多),一方面可以给将来的扩容多一些余量,另外也可以避免当发生故障导致Pod IP无法及时回收时,出现没有IP可分配的情况。

为什么Pod无法ping通部分ECS节点?

问题现象

Flannel网络模式下,检查VPN路由正常,进入Pod,发现部分ECS节点无法ping通。

问题原因

Pod无法ping通部分ECS节点的原因分为两种。

  • 原因一:Pod访问的ECS和集群在同一个VPC下,但不在同一个安全组。

  • 原因二:Pod访问的ECS和集群不在同一个VPC下。

解决方法

根据不同的原因,提供不同的解决方法。

  • 针对原因一,需要将ECS加入到集群的安全组中。具体操作,请参见配置安全组

  • 针对原因二,需要通过ECS的公网入口访问,需要在ECS的安全组中加入集群的公网出口IP地址。

为什么集群节点有NodeNetworkUnavailable污点?

问题现象

Flannel网络模式下,新增的集群节点上有NodeNetworkUnavailable污点,导致Pod无法调度。

问题原因

Cloud Controller Manager没有及时删除该节点污点,可能原因是路由表满、VPC存在多路由表等情况。

解决方法

使用kubectl describe node命令查看节点的Event事件信息,根据实际输出的报错进行处理。

为什么Pod无法正常启动,且报错no IP addresses available in range?

问题现象

Flannel网络模式下,Pod无法正常启动,查看Pod事件时显示类似于failed to allocate for range 0: no IP addresses available in range set: 172.30.34.129-172.30.34.190的错误信息。

问题原因

Flannel网络模式下,每个集群节点会被分配到一个指定的容器IP段。容器调度到节点上时,Flannel会从节点所属的容器IP段中获取一个未被占用的IP分配给容器。当Pod提示failed to allocate for range 0: no IP addresses available in range set: 172.30.34.129-172.30.34.190错误信息时,说明没有IP可以分配给Pod。该种情况有可能是发生了IP地址泄露,存在以下两个原因:

  • ACK低于1.20版本时,如果发生Pod反复重启、CronJob中Pod短时间内退出等事件,可能会导致IP地址泄漏。详情请参见Issues 75665Issues 92614

  • Flannel低于v0.15.1.11-7e95fe23-aliyun版本时,如果发生节点重启或突然关机的事件,可能会导致Pod直接销毁,从而导致IP地址泄漏。详情请参见Issues 332

解决方案

  • 针对低版本ACK导致的IP地址泄露,您可以升级集群至1.20及以上版本。具体操作,请参见升级ACK集群

  • 针对低版本Fannel导致的IP地址泄露,您可以升级Flannel至v0.15.1.11-7e95fe23-aliyun及以上版本。操作如下:

    Flannel只要在v0.15.1.11-7e95fe23-aliyun及以上版本,ACK会在Flannel中将默认IP段分配数据库迁移至临时目录 /var/run中,重启时系统会自动清空,避免IP地址泄露。

    1. 升级Flannel组件至v0.15.1.11-7e95fe23-aliyun及以上版本。具体操作,请参见管理组件

    2. 执行以下命令,编辑kube-flannel-cfg文件,然后在kube-flannel-cfg文件中新增dataDiripam参数。

      kubectl -n kube-system edit cm kube-flannel-cfg

      kube-flannel-cfg文件示例如下。

      # 修改前
          {
            "name": "cb0",
            "cniVersion":"0.3.1",
            "plugins": [
              {
                "type": "flannel",
                "delegate": {
                  "isDefaultGateway": true,
                  "hairpinMode": true
                 },
              },
              # portmap # 低版本可能没有,如不使用请忽略。
              {
                "type": "portmap",
                "capabilities": {
                  "portMappings": true
                },
                "externalSetMarkChain": "KUBE-MARK-MASQ"
              }
            ]
          }
      
      # 修改后
          {
            "name": "cb0",
            "cniVersion":"0.3.1",
            "plugins": [
              {
                "type": "flannel",
                "delegate": {
                  "isDefaultGateway": true,
                  "hairpinMode": true
                 },
                # 注意逗号。
                "dataDir": "/var/run/cni/flannel",
                "ipam": {
                  "type": "host-local",
                  "dataDir": "/var/run/cni/networks"
                 }
              },
              {
                "type": "portmap",
                "capabilities": {
                  "portMappings": true
                },
                "externalSetMarkChain": "KUBE-MARK-MASQ"
              }
            ]
          }
    3. 执行以下命令,重启Flannel Pod。

      重启Flannel Pod不会影响运行中的业务。

      kubectl -n kube-system delete pod -l app=flannel
    4. 删除节点上的IP目录,重启节点。

      1. 排空节点上的已有Pod。具体操作,请参见设置节点调度状态

      2. 登录节点,执行以下命令,删除IP目录。

        rm -rf /etc/cni/
        rm -rf /var/lib/cni/
      3. 重启节点。具体操作,请参见重启实例

      4. 重复执行以上步骤,删除所有节点上的IP目录。

    5. 在节点上执行以下命令,验证节点是否启用临时目录。

      if [ -d /var/lib/cni/networks/cb0 ]; then echo "not using tmpfs"; fi
      if [ -d /var/run/cni/networks/cb0 ]; then echo "using tmpfs"; fi
      cat /etc/cni/net.d/10-flannel.conf*

      返回using tmpfs,说明当前节点已经启用临时目录/var/run作为IP段分配数据库,变更成功。

  • 如果短时间内无法升级ACK或Flannel,您可以按照以下方法临时紧急处理。临时紧急处理适用于以上两种原因导致的泄漏。

    临时紧急处理操作只是帮助您清理泄露的IP地址,IP地址泄露的情况仍然有可能发生,因此您还是需要升级Flannel或集群的版本。

    说明
    • 以下命令不适用于v0.15.1.11-7e95fe23-aliyun及以上版本的Flannel,并且已经切换使用/var/run存储IP地址分配信息的节点。

    • 以下脚本仅供参考,如果节点曾有过自定义修改,脚本可能无法正常工作。

    1. 将问题节点设置为不可调度状态。具体操作,请参见设置节点调度状态

    2. 使用以下脚本,按照运行时引擎清理节点。

      • 如果您使用的是Docker运行时,请使用以下脚本清理节点。

        #!/bin/bash
        cd /var/lib/cni/networks/cb0;
        docker ps -q > /tmp/running_container_ids
        find /var/lib/cni/networks/cb0 -regex ".*/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" -printf '%f\n' > /tmp/allocated_ips
        for ip in $(cat /tmp/allocated_ips); do
          cid=$(head -1 $ip | sed 's/\r#g' | cut -c-12)
          grep $cid /tmp/running_container_ids > /dev/null || (echo removing leaked ip $ip && rm $ip)
        done
      • 如果您使用的是Containerd运行时,请使用以下脚本清理节点。

        #!/bin/bash
        # install jq
        yum install -y jq
        
        # export all running pod's configs
        crictl -r /run/containerd/containerd.sock pods -s ready -q | xargs -n1 crictl -r /run/containerd/containerd.sock inspectp > /tmp/flannel_ip_gc_all_pods
        
        # export and sort pod ip
        cat /tmp/flannel_ip_gc_all_pods | jq -r '.info.cniResult.Interfaces.eth0.IPConfigs[0].IP' | sort > /tmp/flannel_ip_gc_all_pods_ips
        
        # export flannel's all allocated pod ip
        ls -alh /var/lib/cni/networks/cb0/1* | cut -f7 -d"/" | sort > /tmp/flannel_ip_gc_all_allocated_pod_ips
        
        # print leaked pod ip
        comm -13 /tmp/flannel_ip_gc_all_pods_ips /tmp/flannel_ip_gc_all_allocated_pod_ips > /tmp/flannel_ip_gc_leaked_pod_ip
        
        # clean leaked pod ip
        echo "Found $(cat /tmp/flannel_ip_gc_leaked_pod_ip | wc -l) leaked Pod IP, press <Enter> to clean."
        read sure
        
        # delete leaked pod ip
        for pod_ip in $(cat /tmp/flannel_ip_gc_leaked_pod_ip); do
            rm /var/lib/cni/networks/cb0/${pod_ip}
        done
        
        echo "Leaked Pod IP cleaned, removing temp file."
        rm /tmp/flannel_ip_gc_all_pods_ips /tmp/flannel_ip_gc_all_pods /tmp/flannel_ip_gc_leaked_pod_ip /tmp/flannel_ip_gc_all_allocated_pod_ips
    3. 将问题节点设置为可调度状态。具体操作,请参见设置节点调度状态

如何修改节点IP数量、Pod IP网段、Service IP网段?

节点IP数量、Pod IP网段、Service IP网段在集群创建后一律不支持修改,请在创建集群时合理规划您的网段。

是否支持安装和配置第三方网络插件?

ACK集群不支持安装和配置第三方网络插件,如果安装了可能会导致集群网络不可用。

为什么会报no IP addresses available in range set

可能您的ACK集群使用的是早期版本的Terway网络插件或者Flannel网络插件,这两种情况定义了Pod网络CIDR,即为每个节点提供一组有限的IP地址用于分配给Pod。一旦这个范围内的IP地址都被用完,新的Pod就不能被创建在这个节点上,除非释放一些IP地址或对集群的网络进行重构或扩展。Terway网络模式下您可能需要考虑升级Terway到最新版本以解决该问题。

Terway网络模式支持的Pod数量是多少?

Terway网络模式的集群支持的Pod数量是ECS支持的IP数量。详细信息,请参见Terway各种模式对比

Terway DataPathV2数据面模式

  • 从Terway v1.8.0版本起,新建集群时选择IPvlan选项将默认启用DataPathV2模式。对于已经启用 IPvlan功能的现有集群,数据面维持原有的IPvlan方式。

  • DataPathV2是新一代的数据面路径,与原有的IPvlan模式相比,DataPathV2模式具有更好的兼容性。详细信息,请参见使用Terway网络插件

如何查看Terway网络Pod生命周期?

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 守护进程集

  3. 守护进程集页面顶部,单击image选择kube-system命名空间。

  4. 守护进程集页面搜索terway-eniip,单击名称列表下的terway-eniip

    以下为容器组现状详情的说明:

    类型

    说明

    Ready

    Pod内的所有容器都已经启动并运行正常。

    Pending

    Pod正在等待Terway为其配置网络资源。

    Pod因节点资源不足未调度到节点上。详细信息,请参见Pod状态为Pending

    ContainerCreating

    Pod已调度至节点,表明Pod正在等待网络初始化完成。

    更多信息,请参见Pod的生命周期