UnknownR

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

  •  
  •   UnknownR · Jul 30, 2020 · 6105 views
    This topic created in 2294 days ago, the information mentioned may be changed or developed.

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

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

    33 replies  •  2020-10-09 15:43:51 +08:00
    kaikai5601
    kaikai5601
    Jul 30, 2020 via iPhone
    1
    你就起一个 pod 不就好了
    wxsm
    wxsm
    Jul 30, 2020 via iPhone
    2
    就起 1 个,挂掉了会自动重启
    UnknownR
    UnknownR
    OP
    Jul 30, 2020
    3
    @kaikai5601 但是挂掉时就没法快速切换另一个上。。启动再快也需要时间
    wetist
    wetist
    Jul 30, 2020
    4
    让开发试试分布式锁?
    UnknownR
    UnknownR
    OP
    Jul 30, 2020
    5
    @wxsm 想要达到的效果是能无缝切换,自动重启的话用户的体验可能就会差,重启能被感知
    wxsm
    wxsm
    Jul 30, 2020 via iPhone❤️5
    6
    提供一个思路:利用 readinessProbe
    从节点定时检测主节点是否存活,存活的话该检测提供失败返回,就不会被 k8s 分配流量,同时也不会被杀死。
    UnknownR
    UnknownR
    OP
    Jul 30, 2020
    7
    @wetist 哎这个需求时间紧迫,开发这边的方案已经提了好几个了
    Reficul
    Reficul
    Jul 30, 2020❤️1
    8
    用 APIServer 里的资源对象来实现分布式锁,锁释放下一个顶上
    UnknownR
    UnknownR
    OP
    Jul 30, 2020
    9
    @wxsm 非常感谢!我去试试,就是为了确保故障不被感知,检测频率可能要非常高。。。
    jmperdev
    jmperdev
    Jul 30, 2020
    10
    可以在负载均衡层考虑
    derek80
    derek80
    Jul 30, 2020 via iPhone
    11
    上 istio
    derek80
    derek80
    Jul 31, 2020 via iPhone
    12
    或者在自定义的 ingress controller 层面控制。有已有的实现
    bwangel
    bwangel
    Jul 31, 2020
    13
    @UnknownR readinessProbe 每 10 秒检测一次,这个故障恢复时间应该很快了。
    gleymonkey
    gleymonkey
    Jul 31, 2020
    14
    单节点就是个坑
    yisaYisa
    yisaYisa
    Jul 31, 2020❤️2
    15
    这个需求其实非常简单也非常普遍。 比如 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
    wd
    Jul 31, 2020 via iPhone
    16
    又不要重复数据,也不要当机时间,数据库搞了那么多年你看他们实现了没?你可以掂量掂量自己可以做到什么程度。
    zliea
    zliea
    Jul 31, 2020
    17
    lb+有状态服务?
    yuaner
    yuaner
    Jul 31, 2020
    18
    用 istio
    haidii
    haidii
    Jul 31, 2020
    19
    多个 replica 下,可以通过 给 pod 添加标签的方式,根据标签值,让流量只流向其中一个 pod 。
    sampeng
    sampeng
    Jul 31, 2020 via iPhone
    20
    所以一个无服务状态是多么得重要。
    sampeng
    sampeng
    Jul 31, 2020 via iPhone
    21
    那你们上 k8s 的意义是什么?硬上么?不支持多节点就改称支持。哪里有状态就用 redis,数据库等稳定的服务分离状态。硬上 k8s 没收益还带来复杂度
    sampeng
    sampeng
    Jul 31, 2020 via iPhone
    22
    我们刚上 k8s 的时候也是这样,尤其是定时任务。我一个一个盯着全改成 xxl-job,可以支持了就切
    xuanbg
    xuanbg
    Jul 31, 2020
    23
    楼主你这个需求叫“热备”,主备热切换,非常古老的可用性方案了。现在流行的可用性方案是无状态的分布式,核心就是不管谁挂,反正流量都是活着的分摊,费效比比热备不知道高哪里去了……

    所以 k8s 在设计的时候根本就没有考虑热备这种古老的需求,这就比较僵硬。不过,办法还是有的。楼主你在 k8s 外面再做一套热备就是了。
    yushiwho
    yushiwho
    Jul 31, 2020 via Android
    24
    controller 都是这种机制 参考 kuberbuilder
    abowloflrf
    abowloflrf
    Jul 31, 2020 via iPhone
    25
    deployment 下的所有 pod 都是无差别对待的也就是无状态的,楼主的需求感觉应用还是有状态。解决办法想到有一个就是楼上所说,用一个锁,若是 golang,client-go 自带 leaderelection 的包,用了 apiserver 里一个唯一的资源做 leader 选举,非 leader 的 pod 在探针里返回失败就行这样 endpoint 就不会加入到 service 里。另外一个想法就是部署两个副本数为 1 的 deployment 再控制流量。
    rrfeng
    rrfeng
    Jul 31, 2020
    26
    你应该去看 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
    Illusionary
    Jul 31, 2020
    27
    单节点要求高可用? 你们的开发水平配不上在运维层面使用 k8s,建议用回单 docker 部署,或者 tomcat 也行嗷
    rushssss
    rushssss
    Jul 31, 2020
    28
    @yisaYisa 这个方案除了不满足 “应该让应用对 k8s 无感知" 这条最佳实践外,几乎是最好的方案,当然就算你不用 k8s 的 api, 也必须要有其他的分布式的,强一致的组件来做协调
    lostsquirrelX
    lostsquirrelX
    Jul 31, 2020
    29
    nginx 支持主备,但要注意解析缓存, 可以考虑 nginx + (service + pod x 1) x n
    UnknownR
    UnknownR
    OP
    Jul 31, 2020
    30
    @sampeng 没错。。。就是硬伤,我们是软件提供商,客户需要 linux 加容器,本来是 windows 软件,现在硬上 k8s,后续开发这边只能开任务做分布式或者无状态
    v2Geeker
    v2Geeker
    Jul 31, 2020
    31
    statefulset 搞定,用 headless service 指定就行了呀~
    dreamusername
    dreamusername
    Aug 7, 2020
    32
    最好的方式肯定是用通用的方式,不要去使用那些不常用的功能。
    流量层面考虑,你可以考虑使用 istio,借助 envoy 可以对流量进行精准的控制,缺点就是对运维的要求很高。
    kiddingU
    kiddingU
    Oct 9, 2020
    33
    上层挂一个 lb,指定节点跑流量
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1062 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 70ms · UTC 18:36 · PVG 02:36 · LAX 10:36 · JFK 13:36
    ♥ Do have faith in what you're doing.