目前业务遇到了比较蛋疼的问题,虽然要上 k8s 但是应用本身不支持 replica,不然会出重复数据 看了一圈发现好像 k8s 不管是 replicaset 还是 hpa 好像都只支持多个 pod 同时 active 然后随机接受流量,请问有什么方法能同时跑多个 pod 但是只让其中一个接受流量,剩下的只是运行状态?类似 DB 的 primary 和 secondary,只有 primary 接受流量,剩下的只要在 primary 挂掉时能及时接上就好。
数据是统一写入数据库的,所以不存在数据差异问题
1
kaikai5601 2020-07-30 20:37:59 +08:00 via iPhone
你就起一个 pod 不就好了
|
2
wxsm 2020-07-30 20:39:32 +08:00 via iPhone
就起 1 个,挂掉了会自动重启
|
3
UnknownR OP @kaikai5601 但是挂掉时就没法快速切换另一个上。。启动再快也需要时间
|
4
wetist 2020-07-30 20:42:11 +08:00
让开发试试分布式锁?
|
6
wxsm 2020-07-30 20:46:44 +08:00 via iPhone 5
提供一个思路:利用 readinessProbe
从节点定时检测主节点是否存活,存活的话该检测提供失败返回,就不会被 k8s 分配流量,同时也不会被杀死。 |
8
Reficul 2020-07-30 20:49:40 +08:00 1
用 APIServer 里的资源对象来实现分布式锁,锁释放下一个顶上
|
10
BigBrother1024 2020-07-30 21:00:24 +08:00
可以在负载均衡层考虑
|
11
derek80 2020-07-30 23:59:18 +08:00 via iPhone
上 istio
|
12
derek80 2020-07-31 00:00:29 +08:00 via iPhone
或者在自定义的 ingress controller 层面控制。有已有的实现
|
14
gleymonkey 2020-07-31 01:05:06 +08:00
单节点就是个坑
|
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 |
16
wd 2020-07-31 04:10:15 +08:00 via iPhone
又不要重复数据,也不要当机时间,数据库搞了那么多年你看他们实现了没?你可以掂量掂量自己可以做到什么程度。
|
17
zliea 2020-07-31 05:02:16 +08:00
lb+有状态服务?
|
18
yuaner 2020-07-31 07:31:21 +08:00
用 istio
|
19
haidii 2020-07-31 07:58:03 +08:00
多个 replica 下,可以通过 给 pod 添加标签的方式,根据标签值,让流量只流向其中一个 pod 。
|
20
sampeng 2020-07-31 08:34:25 +08:00 via iPhone
所以一个无服务状态是多么得重要。
|
21
sampeng 2020-07-31 08:36:04 +08:00 via iPhone
那你们上 k8s 的意义是什么?硬上么?不支持多节点就改称支持。哪里有状态就用 redis,数据库等稳定的服务分离状态。硬上 k8s 没收益还带来复杂度
|
22
sampeng 2020-07-31 08:37:06 +08:00 via iPhone
我们刚上 k8s 的时候也是这样,尤其是定时任务。我一个一个盯着全改成 xxl-job,可以支持了就切
|
23
xuanbg 2020-07-31 08:47:24 +08:00
楼主你这个需求叫“热备”,主备热切换,非常古老的可用性方案了。现在流行的可用性方案是无状态的分布式,核心就是不管谁挂,反正流量都是活着的分摊,费效比比热备不知道高哪里去了……
所以 k8s 在设计的时候根本就没有考虑热备这种古老的需求,这就比较僵硬。不过,办法还是有的。楼主你在 k8s 外面再做一套热备就是了。 |
24
yushiwho 2020-07-31 08:47:37 +08:00 via Android
controller 都是这种机制 参考 kuberbuilder
|
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 再控制流量。
|
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 代码里加竞争机制,只有一个可以提供服务。 |
27
Illusionary 2020-07-31 10:07:34 +08:00
单节点要求高可用? 你们的开发水平配不上在运维层面使用 k8s,建议用回单 docker 部署,或者 tomcat 也行嗷
|
28
rushssss 2020-07-31 10:08:11 +08:00
@yisaYisa 这个方案除了不满足 “应该让应用对 k8s 无感知" 这条最佳实践外,几乎是最好的方案,当然就算你不用 k8s 的 api, 也必须要有其他的分布式的,强一致的组件来做协调
|
29
lostsquirrelX 2020-07-31 14:30:58 +08:00
nginx 支持主备,但要注意解析缓存, 可以考虑 nginx + (service + pod x 1) x n
|
30
UnknownR OP @sampeng 没错。。。就是硬伤,我们是软件提供商,客户需要 linux 加容器,本来是 windows 软件,现在硬上 k8s,后续开发这边只能开任务做分布式或者无状态
|
31
v2Geeker 2020-07-31 19:45:21 +08:00
statefulset 搞定,用 headless service 指定就行了呀~
|
32
dreamusername 2020-08-07 00:36:06 +08:00
最好的方式肯定是用通用的方式,不要去使用那些不常用的功能。
流量层面考虑,你可以考虑使用 istio,借助 envoy 可以对流量进行精准的控制,缺点就是对运维的要求很高。 |
33
kiddingU 2020-10-09 15:43:51 +08:00
上层挂一个 lb,指定节点跑流量
|