V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
UnknownR
V2EX  ›  Kubernetes

k8s 该怎么在多个 replica 的情况下只让其中一个接受流量

  •  
  •   UnknownR · 2020-07-30 20:36:48 +08:00 · 4568 次点击
    这是一个创建于 1575 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前业务遇到了比较蛋疼的问题,虽然要上 k8s 但是应用本身不支持 replica,不然会出重复数据 看了一圈发现好像 k8s 不管是 replicaset 还是 hpa 好像都只支持多个 pod 同时 active 然后随机接受流量,请问有什么方法能同时跑多个 pod 但是只让其中一个接受流量,剩下的只是运行状态?类似 DB 的 primary 和 secondary,只有 primary 接受流量,剩下的只要在 primary 挂掉时能及时接上就好。

    数据是统一写入数据库的,所以不存在数据差异问题

    33 条回复    2020-10-09 15:43:51 +08:00
    kaikai5601
        1
    kaikai5601  
       2020-07-30 20:37:59 +08:00 via iPhone
    你就起一个 pod 不就好了
    wxsm
        2
    wxsm  
       2020-07-30 20:39:32 +08:00 via iPhone
    就起 1 个,挂掉了会自动重启
    UnknownR
        3
    UnknownR  
    OP
       2020-07-30 20:40:03 +08:00
    @kaikai5601 但是挂掉时就没法快速切换另一个上。。启动再快也需要时间
    wetist
        4
    wetist  
       2020-07-30 20:42:11 +08:00
    让开发试试分布式锁?
    UnknownR
        5
    UnknownR  
    OP
       2020-07-30 20:42:33 +08:00
    @wxsm 想要达到的效果是能无缝切换,自动重启的话用户的体验可能就会差,重启能被感知
    wxsm
        6
    wxsm  
       2020-07-30 20:46:44 +08:00 via iPhone   ❤️ 5
    提供一个思路:利用 readinessProbe
    从节点定时检测主节点是否存活,存活的话该检测提供失败返回,就不会被 k8s 分配流量,同时也不会被杀死。
    UnknownR
        7
    UnknownR  
    OP
       2020-07-30 20:47:41 +08:00
    @wetist 哎这个需求时间紧迫,开发这边的方案已经提了好几个了
    Reficul
        8
    Reficul  
       2020-07-30 20:49:40 +08:00   ❤️ 1
    用 APIServer 里的资源对象来实现分布式锁,锁释放下一个顶上
    UnknownR
        9
    UnknownR  
    OP
       2020-07-30 20:49:52 +08:00
    @wxsm 非常感谢!我去试试,就是为了确保故障不被感知,检测频率可能要非常高。。。
    BigBrother1024
        10
    BigBrother1024  
       2020-07-30 21:00:24 +08:00
    可以在负载均衡层考虑
    derek80
        11
    derek80  
       2020-07-30 23:59:18 +08:00 via iPhone
    上 istio
    derek80
        12
    derek80  
       2020-07-31 00:00:29 +08:00 via iPhone
    或者在自定义的 ingress controller 层面控制。有已有的实现
    bwangel
        13
    bwangel  
       2020-07-31 00:07:40 +08:00
    @UnknownR readinessProbe 每 10 秒检测一次,这个故障恢复时间应该很快了。
    gleymonkey
        14
    gleymonkey  
       2020-07-31 01:05:06 +08:00
    单节点就是个坑
    yisaYisa
        15
    yisaYisa  
       2020-07-31 01:18:48 +08:00   ❤️ 2
    这个需求其实非常简单也非常普遍。 比如 kubernetes 的 controller-manager 是怎么做 HA 的?常用的 k8s 上的 operator 的 controller 组件是怎么做 HA 的? 其实上面已经有人给出答案了就是用分布式锁。当然这个分布式锁的轮子也不需要你重复造,kubernetes 早就帮你搞好了。k8s project 里 client-go 中就有 "leaderelection" 可以直接用。具体例子可以参考这个项目。

    https://github.com/pingcap/tidb-operator/blob/8a86f9a661aa30393ce8f087aa388d107e57e72b/cmd/controller-manager/main.go#L241-L253
    wd
        16
    wd  
       2020-07-31 04:10:15 +08:00 via iPhone
    又不要重复数据,也不要当机时间,数据库搞了那么多年你看他们实现了没?你可以掂量掂量自己可以做到什么程度。
    zliea
        17
    zliea  
       2020-07-31 05:02:16 +08:00
    lb+有状态服务?
    yuaner
        18
    yuaner  
       2020-07-31 07:31:21 +08:00
    用 istio
    haidii
        19
    haidii  
       2020-07-31 07:58:03 +08:00
    多个 replica 下,可以通过 给 pod 添加标签的方式,根据标签值,让流量只流向其中一个 pod 。
    sampeng
        20
    sampeng  
       2020-07-31 08:34:25 +08:00 via iPhone
    所以一个无服务状态是多么得重要。
    sampeng
        21
    sampeng  
       2020-07-31 08:36:04 +08:00 via iPhone
    那你们上 k8s 的意义是什么?硬上么?不支持多节点就改称支持。哪里有状态就用 redis,数据库等稳定的服务分离状态。硬上 k8s 没收益还带来复杂度
    sampeng
        22
    sampeng  
       2020-07-31 08:37:06 +08:00 via iPhone
    我们刚上 k8s 的时候也是这样,尤其是定时任务。我一个一个盯着全改成 xxl-job,可以支持了就切
    xuanbg
        23
    xuanbg  
       2020-07-31 08:47:24 +08:00
    楼主你这个需求叫“热备”,主备热切换,非常古老的可用性方案了。现在流行的可用性方案是无状态的分布式,核心就是不管谁挂,反正流量都是活着的分摊,费效比比热备不知道高哪里去了……

    所以 k8s 在设计的时候根本就没有考虑热备这种古老的需求,这就比较僵硬。不过,办法还是有的。楼主你在 k8s 外面再做一套热备就是了。
    yushiwho
        24
    yushiwho  
       2020-07-31 08:47:37 +08:00 via Android
    controller 都是这种机制 参考 kuberbuilder
    abowloflrf
        25
    abowloflrf  
       2020-07-31 09:00:40 +08:00 via iPhone
    deployment 下的所有 pod 都是无差别对待的也就是无状态的,楼主的需求感觉应用还是有状态。解决办法想到有一个就是楼上所说,用一个锁,若是 golang,client-go 自带 leaderelection 的包,用了 apiserver 里一个唯一的资源做 leader 选举,非 leader 的 pod 在探针里返回失败就行这样 endpoint 就不会加入到 service 里。另外一个想法就是部署两个副本数为 1 的 deployment 再控制流量。
    rrfeng
        26
    rrfeng  
       2020-07-31 09:57:49 +08:00
    你应该去看 service 的实现。

    这个需求不在 k8s 上加功能的前提下自己实现的思路有以下几种:
    1. 用 statefulset,这样每个 pod 有独立的 service name,然后 client 去搞切换
    2. 继续用 deployment ( replicaset ),然后 client 不直接调用 service,而是去拿 service 对应的 endpoint 对应的 pod,还是 client 去搞切换
    3. 继续用 deployment,然后自己搞个额外小程序跑起来,选主然后注册成一个 service
    4. 加个 proxy,proxy 帮你做切换
    5. server 代码里加竞争机制,只有一个可以提供服务。
    Illusionary
        27
    Illusionary  
       2020-07-31 10:07:34 +08:00
    单节点要求高可用? 你们的开发水平配不上在运维层面使用 k8s,建议用回单 docker 部署,或者 tomcat 也行嗷
    rushssss
        28
    rushssss  
       2020-07-31 10:08:11 +08:00
    @yisaYisa 这个方案除了不满足 “应该让应用对 k8s 无感知" 这条最佳实践外,几乎是最好的方案,当然就算你不用 k8s 的 api, 也必须要有其他的分布式的,强一致的组件来做协调
    lostsquirrelX
        29
    lostsquirrelX  
       2020-07-31 14:30:58 +08:00
    nginx 支持主备,但要注意解析缓存, 可以考虑 nginx + (service + pod x 1) x n
    UnknownR
        30
    UnknownR  
    OP
       2020-07-31 16:11:30 +08:00
    @sampeng 没错。。。就是硬伤,我们是软件提供商,客户需要 linux 加容器,本来是 windows 软件,现在硬上 k8s,后续开发这边只能开任务做分布式或者无状态
    v2Geeker
        31
    v2Geeker  
       2020-07-31 19:45:21 +08:00
    statefulset 搞定,用 headless service 指定就行了呀~
    dreamusername
        32
    dreamusername  
       2020-08-07 00:36:06 +08:00
    最好的方式肯定是用通用的方式,不要去使用那些不常用的功能。
    流量层面考虑,你可以考虑使用 istio,借助 envoy 可以对流量进行精准的控制,缺点就是对运维的要求很高。
    kiddingU
        33
    kiddingU  
       2020-10-09 15:43:51 +08:00
    上层挂一个 lb,指定节点跑流量
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2509 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:02 · PVG 08:02 · LAX 16:02 · JFK 19:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.