首页 > 其他分享 >Ack集群Pod独占EIP实践

Ack集群Pod独占EIP实践

时间:2024-05-17 10:45:20浏览次数:28  
标签:EIP eip Ack 绑定 公网 Pod com pod

1. 背景

某线上应用部署在ack集群内,用于根据用户定义的http请求项配置,周期性检查http接口的请求响应状态,接口地址为内网或公网,当接口地址为公网时,频繁出现请求超时的报警错误。经过排查发现,在公网请求发生超时的时刻,集群vpc NAT带宽达到上限200Mbps,也就是25MB/s

分析:由于集群占用vpcvpc内所有ip(node和pod的ip)都属于vpc内各子网地址,这些地址出公网的请求共用vpc绑定的公网NAT,在某时刻子网ip请求公网使用的EIP是随机的,无法控制,会产生和其他ip同时请求公网使用同一个EIP的情况,由此发生了带宽内拥挤,超限的情况,因此上述超时报警其实是客户端带宽不够产生的误报

2. 解决方案

为了避免发生上述情况,解决办法是避免这些特定的pod请求公网时和其他ip发生公网带宽的争抢,走独立的公网出口,有以下两种方案:

  • 方案一

将这些pod调度到特定的子网nodenodeippodip会使用特定的子网,这个特定的子网由于在特定的vSwitch虚拟交换机下,因此可以为这个子网单独指定路由条目,也就是将请求公网地址的请求的下一跳路由到特定的公网NAT,特定的公网NAT使用特定的EIP且不和其他子网共用

  • 方案二

ack集群的网络使用的是阿里云Terway,在此前提下,阿里云提供了为Terway网络中的Pod挂载独立的公网EIP的解决方案,具体可以查看文档说明,简单来说就是阿里云提供了集群内的控制器,实现了通过k8s原生的声明式配置,调用EIP产品相关api动态为pod绑定EIP的功能

3. 方案选取和实现

方案一,改动较大,需要将pod调度到特定的node上,且需要人工维护路由条目,维护性较差;
方案二,更为直接,在安装控制器插件后,通过给pod添加特定注解实现目的,主要分为两种方式:

  • 一种是根据声明式配置动态随机购买EIP
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example
  labels:
    app: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
      annotations:
        k8s.aliyun.com/pod-with-eip: "true"  # 自动创建并绑定EIP
        k8s.aliyun.com/eip-bandwidth: "200"  # EIP峰值带宽
        k8s.aliyun.com/eip-internet-charge-type: "PayByTraffic" # EIP的计量方式
        k8s.aliyun.com/eip-instance-charge-type: "PostPaid"  # EIP的计费方式
        k8s.aliyun.com/eip-name: "app-eip"  # EIP名称
        k8s.aliyun.com/eip-description: "app-eip"  # EIP描述
  • 一种是先购买EIP,pod注解中声明EIP的id
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example
  labels:
    app: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
      annotations:
        k8s.aliyun.com/pod-eip-instanceid: eip-2zeXXXXXx  # EIP ID

3.1 配置RAM策略并安装插件

按照文档操作,配置挂载EIP所需的RAM权限
安装插件ack-extend-network-controller,安装时启用插件pod eip的能力,一键安装即可

3.2 购买EIP

由于业务目前只有1pod,为了后续排查方便,选择通过先购买EIP再根据EIP id绑定的方式
购买EIP,按量付费,带宽上限为200Mbps

3.3 为pod添加注解

deploymentyaml中为pod添加注解,根据EIP id绑定这个EIP即可

spec:
  template:
    metadata:
      annotations:
        k8s.aliyun.com/pod-eip-instanceid: eip-xxx

绑定后效果

  • 集群cr

控制器会自动创建一个和pod名称相同的PodEIPcr,从这个crstatus中可以看到和上面购买的EIP相关的信息

~ kubectl get pods -o wide|grep app
app-79dcf755fb-ks2ld                                       1/1     Running             0                47h     10.245.36.4      ack-010245035222packets-spot       <none>           1/1
~ kubectl get podeips app-79dcf755fb-ks2ld -o yaml
apiVersion: alibabacloud.com/v1beta1
kind: PodEIP
metadata:
  creationTimestamp: "2024-04-01T07:55:46Z"
  finalizers:
  - podeip-controller.alibabacloud.com/finalizer
  generation: 1
  name: app-79dcf755fb-ks2ld
  namespace: dev
  resourceVersion: "2389078403"
  uid: 292773d3-80b4-4c88-b0ef-17f011a1530e
spec:
  allocationID: eip-xxxxx
  allocationType:
    releaseStrategy: Follow
    type: Static
status:
  eipAddress: 101.xxx.xxx.5
  internetChargeType: PayByTraffic
  isp: BGP
  name: app独享
  networkInterfaceID: eni-2zexxxxxxxqvrrpxxx
  podLastSeen: "2024-04-01T07:39:39Z"
  privateIPAddress: 10.xxx.36.4
  resourceGroupID: rg-xxxxx5afyhf3xky
  status: InUse
  • EIP绑定情况,与从集群查看cr得到的状态一致

3.4 其他说明

以上实现了pod绑定特定EIP的功能,在此条件下,pod请求公网时会固定为此eip出公网,为了保障配置的稳定,经过测试,上面提到此业务pod只有一个副本,且通过deployment管理,属于无状态应用,只做上面为pod添加注解的方式会有以下问题

3.4.1 如何控制当pod状态变为ready后才绑定EIP?

控制器会在Pod IP分配后,为Pod配置EIP地址,Pod Ready状态可能早于EIP绑定成功时间。解决办法是为pod添加就绪前的检测

  • 一种方式是为Pod配置Readiness gates
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
...
  • 一种方式是为Pod配置init container,在init container中检查EIP是否已经分配成功
apiVersion: v1
kind: Pod
metadata:
  name: example
  annotations:
    k8s.aliyun.com/pod-with-eip: "true"
spec:
  containers:
  - name: example
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init
    image: busybox:1.28
    command: ['timeout', '-t' ,'60', 'sh','-c', "until grep -E '^k8s.aliyun.com\\/allocated-eipAddress=\\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

3.4.2 如何控制pod更新时,EIP始终只绑定了一个pod?

pod如果发生了滚动更新,且pod在配置有探针的情况下,可以保障始终只有一个pod接收流量,但是无法保证EIP的正常绑定,因为发布过程中有两个pod同时绑定了这个EIP,新pod启动后,老的pod下线调用了解绑EIP的动作,EIP绑定是需要调用接口到vpc去绑定,只有绑定了这个EIP pod的后续探针才会ready。在新pod滚动更新的过程中,会重新绑定EIP,但是旧pod的回收,又会卸载绑定这个EIP

这里EIP当做了创建pod所需的基础资源,实际上EIP并不是pod运行所必须的,解决办法:

  • A. 修改控制器实现支持在pod滚动更新结束后才将新的pod ipEIP绑定(下述C可以避免此问题)

  • B. 将pod的滚动更新模式修改为销毁重建Recreate,这样会损失一定流量

  • C. 控制器支持有状态应用的pod在一定时间内发生更新后仍然使用之前的EIP,因此把poddeployment改为statefulset,并声明pod在更新过程中仍然使用之前的EIP即可(固定EIP可以保证Pod重建后依然使用之前的EIP地址。该策略可与自动分配EIP能力结合,用于有状态应用的固定EIP

      annotations:
        k8s.aliyun.com/pod-with-eip: "true"
        k8s.aliyun.com/pod-eip-release-strategy: "10m"

结合现状,业务pod如果支持多副本模式,可以切换到statefulset并创建2个副本,有状态应用的滚动更新本身就是副本销毁和重新创建,在多副本的情况下不会有流量丢失。目前只有一个(暂不支持多副本模式),且可以接受在升级的过程中丢失一定的流量,在不改变原有的无状态应用属性的情况下,选择的解决办法为B

最终配置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      annotations:
        k8s.aliyun.com/pod-eip-instanceid: eip-XXXXXXXlus72fax
    spec:
      readinessGates:
      - conditionType: "k8s.aliyun.com/eip"

3.4.3 pod绑定EIP后pod本身监听的端口是否也就通过EIP暴露?

pod由于没有通过NAT请求公网,是EIPPod IP(ecs 弹性辅助网卡)直接绑定,因此默认情况下,通过pod ip(vpc内网):端口可以直接访问到pod暴露的接口,通过eip(公网):端口也可以访问到,但是由于EIP绑定的是ecs的弹性辅助网卡,因此和ecs共用了一个安全组,ecs是集群node,只开放了集群子网间互通,因此这个问题已经规避

原文链接https://www.ssgeek.com/post/ack-ji-qun-pod-du-zhan-eip-shi-jian/
关注公众号加群,更多原创干货与你分享 ~

标签:EIP,eip,Ack,绑定,公网,Pod,com,pod
From: https://www.cnblogs.com/ssgeek/p/18197422

相关文章

  • 部署freeipa中报错:Command '/bin/systemctl start certmonger.service' returned non-
    cat/etc/dbus-1/system.d/certmonger.conf<allowsend_destination="org.fedorahosted.certmonger"send_interface="org.fedorahosted.certmonger"/><allowsend_destination="org.fedorahosted.certmonger"......
  • webpack相关知识点
    一、webpack打包过程。首先读取配置文件,确定入口文件及其依赖关系,然后,从入口文件开始,递归解析所有模块,通过相应的加载器(loaders)处理不同类型的文件内容,如Javascript、css等。接着,使用插件(plugins)执行额外的任务,如代码压缩、环境变量注入等。最后,将处理后的模块按照指定的格式......
  • buffer/cach太高导致k8s无法新建pod分配内存
    1.使用hcache查看buff/cache占用情况执行下面的命令安装hcache,原hcache项目地址https://github.com/silenceshell/hcachewgethttps://silenceshell-1255345740.cos.ap-shanghai.myqcloud.com/hcachechmod+xhcachemvhcache/usr/local/bin/查看缓存排名前十的进程hc......
  • openGauss connection-rollback
    connection.rollback()功能描述此方法回滚当前挂起事务。注意:执行关闭连接“close()”而不先提交更改“commit()”将导致执行隐式回滚。原型connection.rollback()参数无。返回值无。示例请参见示例:常用操作。......
  • k8s中查看pod的yaml文件的案例
    在Kubernetes(K8s)中,Pod的YAML文件定义了Pod的配置和规格。当你想要查看Pod的YAML文件参数参考时,通常是为了了解可以配置哪些字段以及这些字段的含义。以下是一些方法来查看PodYAML文件的参数参考:官方文档:Kubernetes官方文档提供了关于所有资源的详细API参......
  • 在Kubernetes中,您可以通过几种方式来禁止某个Pod调度
    在Kubernetes中,您可以通过几种方式来禁止某个Pod调度到节点上。以下是一些方法:NodeSelector:您可以使用NodeSelector来限制Pod只能调度到带有特定标签的节点上。如果您希望完全禁止Pod调度到某些节点上,可以确保这些节点不拥有所需的标签,这将阻止Pod调度到这些节点。例如,要禁止P......
  • MySQL存储过程中如何使用ROLLBACK
    在MySQL存储过程中,可以使用ROLLBACK来撤销之前执行的所有未提交的更改。当与BEGIN和COMMIT结合使用时,ROLLBACK可以帮助您管理事务并确保数据的完整性。以下是一个示例存储过程,它使用TRY...CATCH块来捕获异常,并在需要时执行ROLLBACK。请注意,MySQL本身并不直接支持TRY...CATCH错误......
  • 说说webpack proxy工作原理?为什么能解决跨域?
    一、是什么webpackproxy,即webpack提供的代理服务基本行为就是接收客户端发送的请求后转发给其他服务器其目的是为了便于开发者在开发模式下解决跨域问题(浏览器安全策略限制)想要实现代理首先需要一个中间服务器,webpack中提供服务器的工具为webpack-dev-serverwebpack-dev-se......
  • Pod常用操作
    创建pod:要使用kubectl创建Pod,你需要提供一个YAML或JSON格式的配置文件,该文件定义了Pod的详细信息,包括容器镜像、端口等。以下是一个简单的Pod定义示例:apiVersion:v1kind:Podmetadata:name:my-podlabels:app:my-appspec:containers:-name:my-containe......
  • K8S之yaml 文件详解pod、deployment、service(转)
    原文:https://blog.csdn.net/footless_bird/article/details/125946101作者:墨鸦_Cormorant来源:CSDN K8S中的yaml文件yaml语法学习 Kubernetes支持YAML和JSON格式管理资源对象 JSON格式:主要用于api接口之间消息的传递 YAML格式:用于配置和管理,YAML是一种简......