文档

为Pod挂载独立公网EIP

更新时间:

在ACS集群中,Pod的IP地址一般是私网的IP地址。但在某些场景下,Pod可能需要一个独立的公网IP地址,使得Pod可以独立地与外部网络通信。本文介绍如何为ACS集群中的Pod挂载独立的公网EIP。

前提条件

已创建ACS集群。具体操作,请参见创建ACS集群

背景信息

一般情况下,Pod访问公网的流量是通过“外部SNAT+EIP”的方式实现,详情请参见为已有集群开启公网访问能力。对于Pod的公网入口流量,一般是通过LoadBalancer类型的Service流入。在一些特殊场景中Pod需要独立的公网地址,例如:

  • Pod的对外映射端口是随机的,一般常见于UDP(User Datagram Protocol)的游戏服务器或电话会议等。例如RTSP协议,对不同的客户端使用不同的端口。

  • 公网流量存在出口资源争抢,Pod需要独立的公网出口。

使用限制

  • 在使用弹性公网IP(Elastic IP Address,简称EIP)前,请先了解EIP的使用限制。详细信息,请参见使用限制

  • 如果您使用自动分配EIP能力,在Pod重建、CNI执行失败等情况下,可能会反复申请、释放EIP资源,这种情况下,可能会触发EIP使用限制。如果您想避免这种情况,可以通过配置Pod Annotationnetwork.alibabacloud.com/allocated-eip-id为Pod指定EIP。

步骤一:配置挂载EIP所需的RAM权限

对于ACS集群,请为RAM用户生成访问密钥(AccessKey)。具体操作,请参见创建RAM用户创建自定义权限策略

步骤二:为集群安装或升级插件

要使用ack-extend-network-controller插件,请在ACK应用市场或ACS集群内应用入口中安装ack-extend-network-controller插件,并开启EIP控制器。

说明

ACS集群可以在ACK控制台中查看和管理。详细信息,请参见产品简介

通过ACS集群内Helm入口安装

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

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > Helm

  3. Helm页面,单击创建。参考如下信息完成基本信息配置。

    参数

    示例值

    应用名

    ack-extend-network-controller

    命名空间

    kube-system

    来源

    默认为应用目录

    Chart

    搜索框:搜索ack-extend-network-controller

    单击下一步

  4. 参数配置页面,选择Chart 版本。参考如下表格,配置必填参数,然后单击确定

    说明

    ACS集群仅支持安装和使用版本>=v0.9.3组件。

    参数说明如下所示:

    配置参数

    类型

    必填

    描述

    enableControllers

    []string

    删除eip的默认注释以启用EIP功能。

    vpcid

    string

    EIP 关联的VPC ID。

    credential.accessKey

    string

    挂载EIP所需权限账户的AK。

    credential.accessSecret

    string

    挂载EIP所需权限账户的SK。

    networkController.eipController.maxConcurrentReconciles

    int

    EIP控制器并发数量。

    networkController.eipController.garbageCollectionPeriodInMinutes

    int

    EIP控制器清理固定EIP的周期。

    customStatefulWorkloadKinds

    []string

    自定义有状态控制器Kind。

  5. 返回Helm页面,可以看到新的ack-extend-network-controller组件已经成功部署。

通过ACK应用市场安装

  1. 登录容器服务管理控制台,在左侧导航栏选择市场 > 应用市场

  2. 应用市场页面的搜索栏中输入ack-extend-network-controller,然后单击目标应用。

  3. 在应用详情页面,单击右上角的一键部署

  4. 创建面板中,选择集群和命名空间,然后单击下一步

    1. 在参数配置页面,选择版本号并设置相应的参数,然后单击确定

      说明

      ACS集群仅支持安装和使用版本>=v0.9.2组件。

      参数说明如下所示:

      配置参数

      类型

      必填

      描述

      enableControllers

      []string

      配置eip以启用EIP功能。

      vpcid

      string

      EIP 关联的VPC ID

      credential.accessKey

      string

      挂载EIP所需权限账户的AK。

      credential.accessSecret

      string

      挂载EIP所需权限账户的SK。

      networkController.eipController.maxConcurrentReconciles

      int

      EIP控制器并发数量。

      networkController.eipController.garbageCollectionPeriodInMinutes

      int

      EIP控制器清理固定EIP的周期。

      customStatefulWorkloadKinds

      []string

      自定义有状态控制器Kind。

      参数示例如下:

      clusterID: "c11ba338192xxxxxxx"  
      regionID: "cn-hangzhou"      
      vpcID: "vpc-bp1rkq0zxxxxxx" 
      enableVirtualNode: true
      affinity: null
      enableControllers:
        - eip              
      networkController:
        eipController:
          maxConcurrentReconciles: 10   
          garbageCollectionPeriodInMinutes: 1  
        customStatefulWorkloadKinds:           
        - foo
      credential:                             
        accessKey: "xxxxxxxxxxxx"
        accessSecret: "xxxxxxxxxxxxxx"

      如需更新ack-extend-network-controller插件的版本和参数,请参见应用市场

步骤三:启用EIP功能

ACS支持使用Annotation的方式启用EIP功能,通过指定Pod中的annotations可以创建或者关联EIP到Pod中。关于启用EIP功能注解的详细内容,请参见启用EIP的Annotation介绍

说明

您可以按需选择自动分配EIP或者指定EIP实例的方式。这两种方式除了使用的Annotation不同之外,在EIP回收策略上也有不同。对于指定EIP实例的方式,删除Pod不会释放EIP实例,而自动分配EIP的方式则默认释放EIP实例。EIP回收策略的详细信息,请参见设置EIP回收策略的Annotation介绍

自动分配EIP

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

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

  3. 在页面右上方,单击使用YAML创建资源

  4. 使用如下YAML示例创建一个名为example的Deployment控制器。

    展开查看Deployment YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example
      labels:
        app: example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: example
      template:
        metadata:
          labels:
            app: example
          annotations:
            network.alibabacloud.com/pod-with-eip: "true"
            network.alibabacloud.com/eip-bandwidth: "5"
        spec:
          containers:
          - name: example
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginx:latest
            ports:
            - containerPort: 80

    其中的annotations部分表示为每个Pod自动分配一个EIP实例,并且实例带宽为5 Mbps。

  5. 创建成功后,进入名为example的Deployment。点击Pod名称(例如:example-78d17b7xxx-adxxx)进入Pod详情页面,在页面右侧注解部分查看创建出的EIP信息。您也可以点击编辑,在Pod YAML中查看创建出的EIP信息。

    展开查看Pod YAML

    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
        ...
        network.alibabacloud.com/allocated-eip-id: eip-xxxxx0y884ucrevoxxxxx
        network.alibabacloud.com/allocated-eipAddress: xxx.xxx.xxx.xxx
        network.alibabacloud.com/allocated-eni-id: eni-xxxxx563trofuhaxxxxx
        network.alibabacloud.com/eip-bandwidth: '5'
        network.alibabacloud.com/pod-with-eip: 'true'
        ...
      labels:
        alibabacloud.com/compute-class: general-purpose
        app: example
      name: example-78d17b7xxx-adxxx
      namespace: default
    spec:
      ...
  6. 完成示例后,删除名为example的Deployment。由于在没有指定Pod EIP实例ID的情况下,Pod EIP的默认回收策略是跟随Pod生命周期。因此当Pod被删除后,EIP会自动释放。

指定EIP实例

  1. 准备示例使用的EIP实例,请先申请EIP

  2. 登录容器计算服务控制台,在左侧导航栏选择集群

  3. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 无状态

  4. 在页面右上方,单击使用YAML创建资源

  5. 使用如下YAML示例创建一个名为example的StatefulSet控制器。

    展开查看Deployment YAML

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      labels:
        app: example
      name: example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: example
      template:
        metadata:
          labels:
            app: example
          annotations:
            network.alibabacloud.com/pod-eip-instanceid: eip-xxxxx66wjkj16lf9xxxxx
        spec:
          containers:
          - name: example
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginx:latest
            ports:
            - containerPort: 80

    其中的annotations部分表示为Pod指定一个实例ID为eip-xxxxx66wjkj16lf9xxxxx的EIP实例,该实例ID需要替换成实际的值。

  6. 创建成功后,进入名为example的StatefulSet。点击Pod名称(例如:example-0)进入Pod详情页面,在页面右侧注解部分查看已绑定的EIP实例信息。您也可以点击编辑,在Pod YAML中查看已绑定的EIP实例信息。

    展开查看Pod YAML

    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
        ...
        network.alibabacloud.com/allocated-eip-id: eip-xxxxx66wjkj16lf9xxxxx
        network.alibabacloud.com/allocated-eipAddress: xxx.xxx.xxx.xxx
        network.alibabacloud.com/allocated-eni-id: eni-xxxxx612ub33hunxxxxx
        network.alibabacloud.com/pod-eip-instanceid: eip-xxxxx66wjkj16lf9xxxxx
        ...
      labels:
        alibabacloud.com/compute-class: general-purpose
        app: example
      name: example-0
      namespace: default
    spec:
      ...
  7. 完成示例后,删除名为example的StatefulSet。由于在指定Pod EIP实例ID的情况下,Pod EIP的回收策略是不释放EIP实例。因此当Pod被删除后,EIP不会自动释放。

相关操作

控制器会在Pod IP分配后,为Pod配置EIP地址,在这个过程中Pod可能在EIP绑定成功前进入Ready状态。您可以尝试使用以下方式来解决这类问题,确保Pod在进入服务可用状态之前已完成EIP的绑定,避免可能出现的服务中断或者连接超时等情况。

使用Readiness gates检查EIP绑定状态

当在Pod中配置readinessGates,并且绑定EIP成功后,控制器会设置Podconditions。在EIP未绑定前,Pod不会处于Ready状态。

kind: Pod
...
spec:
  readinessGates:
  - conditionType: "k8s.aliyun.com/eip"
status:
  conditions:
  - lastProbeTime: "2022-12-12T03:45:48Z"
    lastTransitionTime: "2022-12-12T03:45:48Z"
    reason: Associate eip succeed
    status: "True"
    type: k8s.aliyun.com/eip
...

使用initContainers检查EIP绑定状态

为Pod配置initContainers,在initContainers中检查EIP是否已经分配成功。您可以参考以下示例配置initContainers

apiVersion: v1
kind: Pod
metadata:
  name: example
  annotations:
    network.alibabacloud.com/pod-with-eip: "true"
spec:
  containers:
  - name: example
    image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init
    image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/busybox:1.28
    command: ['timeout', '-t' ,'60', 'sh','-c', "until grep -E '^k8s.aliyun.com\\/pod-ips=\\S?[0-9]+\\S?' /etc/podinfo/annotations; do echo waiting for annotations; sleep 2; done"]
    volumeMounts:
    - name: podinfo
      mountPath: /etc/podinfo
  volumes:
  - name: podinfo
    downwardAPI:
      items:
      - path: "labels"
        fieldRef:
          fieldPath: metadata.labels
      - path: "annotations"
        fieldRef:
          fieldPath: metadata.annotations