Influx-Proxy部署流程以及风险点分析
1. 背景描述
我们经过针对 influx-proxy
为期近一周的代码审计工作,解决了 influx-proxy
在审计工作中发现的:① influxdb
的 measurement
获取上出现获取到保留策略名的错误;②influx-proxy
发现已存在的 data race
警告性错误。同时,为满足公司对于微服务治理的使用需求,我们在原来的基础上增加了 UDP
的写入方式,并优化了 UDP
的 写入,经过测试,在不考虑时间精度的条件下,Proxy
的时序数据转发率达到 100%
。
我们需要根据当前的修改后的 influx-proxy
去构建部署镜像,并在新Site
中部署出来投入使用。
2. 风险点分析
2.1 风险点
- 打包镜像基础命令不支持
UDP
缓冲区大小修改;inlfux-proxy
挂载卷在多副本情况下的共享问题,不同的pod
是否可以读取 不同的pvc
目录;pod
挂了之后,当前 pod 所对应的 挂载卷 是否可以对应到新的pod
- 修改了当前镜像的 缓冲区大小后,是否需要修改物理机的缓冲区大小
2.2 风险点解决
2.2.1 缓冲区修改
目前在 Dockerfile
中不支持 针队系统层面的配置的修改,经过调研,我们发现在 docker
执行的时候 的 run 参数中存在 sysctl
的修改。随后在 K8S 的官方文档中我们寻找到如下的配置信息:
1 | apiVersion: v1 |
上述方案,经过本地实测,出现如下错误:
1 | Failed to create pod sandbox: rpc error: code = Unknown desc = failed to start sandbox container for pod "influx-proxy-0": Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"write sysctl key net.core.rmem_max: open /proc/sys/net/core/rmem_max: no such file or directory\"": unknown |
目前使用了ubuntu
, centos
等基础镜像,均出现了该问题。目前在网上找到的资料显示需要修改宿主机的内核参数。但是这个对于我们部署在K8S
集群中存在不合理性。目前还在进行相关的资料的查询。
我们做了如下的尝试:
- 寻找 满足
net.core.rmem_max
和net.core.rmem_default
的基础镜像,未果; - 用本地的
/proc/sys/net/core
替换 容器内的core
,发现无法替换,未果 - 执行
RUN echo 26214400 /proc/sys/net/core/rmem_default
执行尝试直接写入,未果 - 执行
RUN echo net.core.rmem_default=26214400 >> /etc/sysctl.d/00-alpine.conf
尝试写入sysctl.conf
配置文件,未果
经过与周淼的讨论,目前这个问题在:sysctl variables are not available to newly created namespace 中有提及到,在 2016 年之前,会有显示所有的 网络 namespace
下的内核参数,但是这一点被认为是一个BUG
,因此在此次修复调整后,只对外暴露显示了部分的namespace
下的内核参数,只对外提供部分的参数调整。因此,目前的方案是通过修改 当前 Pod 所在节点的内核值来满足我们的需求。
2.2.2 关于PVC挂载
influx-proxy
中目前是需要使用到 本地存储的没这就涉及到本地的挂载卷。现在有一个问题,就是 当 inlfux-proxy
存在多副本时,挂载卷 能否挂载到同一个pvc
里面,在进行文件的写入的时候,是否会存在无法写入的问题?当 Pod
宕机重启后,是否会从pvc
所对应的 data/
里面进行故障恢复。
我们经过调研,在 PVC 的配置中,我们找到:
1 | apiVersion: v1 |
可以看到这里的 accessModes
的支持的方式有:
ReadWriteOnce -- the volume can be mounted as read-write by a single node
ReadOnlyMany -- the volume can be mounted read-only by many nodes
ReadWriteMany -- the volume can be mounted as read-write by many nodes
目前的这个还是需要进行先一步的测试。
目前会存在两种方案,待测试:
- 使用
StatefulSet
的有状态的部署方式,这样可以保证到的是每一个 容器会对应一个自己的文件目录; - 继续使用
Deployment
的部署方式,但是我们从代码层面做修改,做到多实例访问同一个文件目录,但是当当前的文件目录在被使用的时候,禁止其他实例访问。
经过简单的推理,上述两种方案会存在如下问题:
- 有状态部署在后期的维护上以及在水平扩展上没有无状态的方便快捷;
- 无状态的部署方式,当后端
InfluxDB
实例出现问题,导致写入失败,所有的influx-proxy
均要写入 持久化目录,将导致可能存在只有一个inlfux-proxy
实例在进行写入,其他inlfux-proxy
将保持永远无法写入状态。
再和周淼讨论后,基本确定了使用 StatefulSet
的部署方式,来进行部署。后期,会在此基础上将本地文件方式持久化修改为远程的写入的持久化的方式,可以考虑Redis
/ MongoDB
等。
2.2.3 POD 宕机重启之后是否会读取原来的 持久化文件
当我们的 部署绑定了 PVC
之后,是可以直接读取 PVC
的。但是这里有一个新的问题,举个例子:
现在有 3 个副本 A
, B
, C
,对应着的 有会有 3 个 数据持久化文件目录,在 PVC
的根目录下,a
, b
, c
。从理论上来说,A-a
, B-b
, C-c
是保持一致的。但是现在 A
挂了,重启之后新的 副本为 D
, 那 D
是否能读取到 a
, 而不是 d
, 同时,如果 A,B,C
重启之后,是否能自动对应的读取到a,b,c
同 关于PVC挂载
2.2.4 修改了当前镜像的 缓冲区大小后,是否需要修改物理机的缓冲区大小
目前找到的资料,需要通过Pod SecurigyContext
配置。
同 缓冲区修改
3. 部署过程
3.1 部署前测试
3.1.1 测试环境
influx-proxy
部署环境 K8S
环境
NAME | VERSION | OS | KERNEL | DOCKER | CPU + MEM |
---|---|---|---|---|---|
master1 | v1.17.12 | Ubuntu 18.04.5 LTS | 4.15.0-117-generic | docker://19.3.12 | 4 + 8 |
worker1 | v1.17.12 | Ubuntu 18.04.5 LTS | 4.15.0-117-generic | docker://19.3.12 | 4 + 8 |
worker2 | v1.17.12 | Ubuntu 18.04.5 LTS | 4.15.0-117-generic | docker://19.3.12 | 4 + 8 |
InfluxDB
实例环境
机器名 | 操作系统版本 | Docker版本 | Influxdb镜像 |
---|---|---|---|
10.20.1.100 | Ubuntu 18.04.5 LTS | 19.03.12 | harbor.oneitfarm.com/cidata/influxdb:1.8.3-alpine |
10.20.4.132 | Ubuntu 18.04.5 LTS | 19.03.12 | harbor.oneitfarm.com/cidata/influxdb:1.8.3-alpine |
实例准备,默认数据库: msp
实例名 | 部署方式 | 实例镜像 | 所在机器 |
---|---|---|---|
inlfux-1 | 容器部署 | harbor.oneitfarm.com/cidata/influxdb:1.8.3-alpine | [100 132] |
inlfux-2 | 容器部署 | harbor.oneitfarm.com/cidata/influxdb:1.8.3-alpine | [100 132] |
inlfux-3 | 容器部署 | harbor.oneitfarm.com/cidata/influxdb:1.8.3-alpine | [100 132] |
3.1.2 测试内容
本次测试,我们均使用 双环单实例 进行测试。
3.1.2.1 UDP写入数据是否丢失
- 清空已存在的
InfluxDB
的数据库msp
中所有的表信息 - 按照我们在《influx-proxy无侵入式InfluxDB高可用方案测试》中的测试方式,写入数据,写
1w
条数据。
我们在写入 1w 条数据的时候发现,在我们的数据库中出现了test_udp_proxy_1
, test_udp_proxy_3
,test_udp_proxy_4
,推测原因是因为产生的数据中没有提供test_udp_proxy_2
的表,因此我们扩大测试的数据,在原来的基础上我们再一次写入 10w
的数据。最后我们查询到的表的数据为:
1 | > show measurements; |
可以看到,在我们的数据库中,存在共计:40299+17550+21311+30838 = 10998 的数据量,在时间精度允许的条件下,可以认为我们的influx-proxy
具备 100% 转发能力。同时:
1 | Concurrency Level: 20 |
3.1.2.2 故障恢复是否正常
我们现在删除 其中的一个实例,再次执行写入操作。经过测试,我们:
1 | Using database msp |
最后的数据量为:20998 。 成功恢复了数据。
现在我们调用/recovery
, 从本地的实例进行恢复:
1 | curl -X POST 'http://influx-proxy.ingress.sun-iot.xyz/recovery?from_circle_id=1&to_circle_id=0' |
表示从 circle-1
全量数据 恢复到 circle-0
1 | accepted |
表示成功
3.1.3 测试部署遇到的问题
在 Openstack 的测试部署中,我们有遇到以下问题:
我们在针对 influx-proxy 实现 UDP 负载均衡时发现,每一次真实工作的 副本 只有 存在的三个副本中的某一个,即 单实例工作。针对这一问题,我们调研查找了相关资料,后与周淼,陶圣的讨论中,基本确定了问题如下:
在:client -> service -> pod
的流程中,这里的Client 是指我们的数据源,Service
层在进行负载均衡时,只能将当次连接的数据写入到当次的连接中,且在测试过程中,当次连接并不会断开,导致 Service -> Pod
的连接没有断开,即只往 当前的 Pod
写入。
3.2 正式部署
3.2.1 InfluxDB 环境的准备
3.2.1.1 机器申请
InfluxDB
实例节点
为扩展目前InfluxDB
单实例,我们使用了 influx-proxy
实现 双环双实例,满足实现 InfluxDB 的双写,满足主备,以及故障恢复等需求。因此,需申请两台 4 核16G 机器。由于 InfluxDB
为时序数据库,需使用到存储,故每个实例申请 100G 的存储空间。
influx-proxy
节点
influx-proxy
部署在 K8S 集群中,但是由于 influx-proxy
涉及到 宿主机 的关于 网络空间下的内核参数的调整,为不影响当前 Site
下的其他服务,我们需要进行为 influx-proxy
调度到专属的机器上,并在当前的机器上进行相关的内核参数的调整。需申请 3 台 2C4G 的机器,搭载 3 个 influx-proxy
的副本。
3.2.1.2 部署流程整理
- 因我们数据组之前提供的
ansible
脚本暂没有针对某一个实例的部署方式,需要修改ansible
脚本,提供针对influxdb
的ansible
部署脚本(测试版),后期关于InfluxDB
的部署继续使用数据组提供的ansible
的正式脚本。 - 脚本镜像提供出来后,给到董逸飞进行
InfluxDB
的部署安装。 - 关于
influx-proxy
的K8S
的部署,需要修改influx-prxoy
的调度的策略,也就是需要 将influx-proxy
调度到指定的节点,目的是因为我们需要为influx-proxy
修改宿主机的网络空间下的内核参数,需要周淼协助下。 - 和陶圣,周淼讨论后,
influx-proxy
部署出来之后,需要将influx-proxy
的headless
的地址打入到环境变量,这个需要有人支持一下。
3.2.2 部署遇到的问题
3.2.2.1 Ansible 脚本
在执行 ansible
脚本的过程中,我们发现在登录到跳板机的过程中以及登录到实例所在的宿主机的时候,出现了秘钥的不匹配情况。该情况经过陶圣,洪清亮等人的分析,发现有效秘钥的大小与实际使用的秘钥大小相差了38 的字节,应该是因为本地Windows
系统与Linux
在复制秘钥的过程中出现了误差。具体原因暂不明确。
后经过了秘钥的修改,InfluxDB
成功部署。
3.2.2.2 K8S 部署
在使用当前中台的部署流程时,由于部署的时候将APP_NAME
设置到其他的名字,我们的 influx-proxy
是有三个 Pod
处于 RUNNING
状态,但是在删除了当前的部署后,设置了正确的 APP_NAME
后,发现 influx-proxy
部署后,一直出现 ContainerCreating
的状态,经过查看当前的 Pod 的状态信息,发现,influx-proxy
的 ConfigMap
无法创建。后通过使用渲染但不apply
的方式去查看当前的部署的渲染结果中是否正常渲染,即排查是否存在 ConfigMap
是否正常渲染。
经过排查,渲染正常渲染。说明从在执行 kubectl apply -f -
的过程中出现了 ConfigMap
无法被创建。查找了 MSP
的相关日志,并没找到与之相关的错误的日志信息。
我们经过了删除重试的操作,依旧无法定位到ConfigMap
无法创建的具体原因。最后的解决办法,是将正常渲染出来的 ConfigMap
进行了 kubectl apply -f -
,发现ConfigMap
是可以被正常创建的,说明了ConfigMap
是正常的。出现的这个问题的具体原因还不明确。
3.2.2.3 Msp_Backend
我们在使用 MSP
平台提供的 UDP
写入测试的时候发现,当前 MSP
以UDP
的形式连接的到 influx-proxy
时,如果 influx-proxy
出现了问题导致了宕机,Pod
重启之后,MSP
连接到 influx-proxy
地址依旧是上一个旧的 Pod
的IP
地址(由于 UDP
的特殊性,我们无法在连接时去做到流量的负载)。
建议:
- 开辟独立的协程,进行后端的感知
- 使用
HTTP
请求,目前在使用了proxy
之后,完全有信息可以抗住MSP
的数据量