官方表述是:基于HBase的分布式、可伸缩的时间序列数据库。
主要用途,做监控系统;譬如收集大规模集群(包括网络设备、操作系统、应用程序)的监控数据并进行存储、查询。
OpenTSDB是对外通信的无状态的服务器,在收到监控数据后,将数据写入到HBase。
如下图,部署了多个OpenTSDB节点组成集群,上层使用阿里云SLB封装了一个写IP:Port和一个读IP:Port。
所有业务都使用写IP:Port向OpenTSDB写入数据,而读IP:Port主要用在Grafana里为绘制图表取数,同时也在少量报表JOB中使用。
这种架构可以满足监控的基本需求,但是缺点也非常明显:
为了解决上述问题,首先想到的就是拆分OpenTSDB集群,并做业务分离。即让每个业务使用各自的OpenTSDB集群,可是还不够,还要做读写分离,这就变成每个业务要两套OpenTSDB集群。
于是我们面临以下问题:
如果我们将OpenTSDB进程容器化后 :
1.不再需要那么多机器。一个容器就是一个OpenTSDB进程,端口也不用变,CPU和Mem完全独立,能够通过K8S Configmap进行配置,我们默认配置为1Core 4GB Mem。
2.部署便捷快速。制定出OpenTSDB的Docker镜像后,通过K8S Deployment方式能迅速建起数套OpenTSDB容器集群,并且K8S命令就可以完成对每套容器集群的管理。
3.每套容器集群包含多个容器。我们默认为4个,这些容器又分部在多个K8S节点上,我们使用K8S Service在多个容器上提供HA,使用阿里云SLB在多个K8S Node间实现HA。
4.每套容器集群中的多个容器可以实现负载分摊。K8S Deployment可以实现容器数量动态增加,负载水平扩展问题完美解决。
5.K8S容器自带自愈功能。当检测到OpenTSDB进程无响应时,可自动重启容器,其他存活容器可继续提供服务,不影响业务。
于是我们有如下新的架构图:
Kubernetes是Google基于Borg开源的容器编排调度引擎,作为CNCF(Cloud Native Computing Foundation)最重要的组件之一,它的目标不仅仅是一个编排系统,而是提供一个规范,可以让你来描述集群的架构,定义服务的最终状态,Kubernetes可以帮你将系统自动地达到和维持在这个状态。作为云原生应用的基石,Kubernetes相当于一个云操作系统,其重要性不言而喻。
Pod
的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod
能够被 Service
访问到,通常是通过 Label Selector
(查看下面了解,为什么可能需要没有 selector 的 Service
)实现的。
PodDisruptionBudget
对象(PDB)。PDB 将限制在同一时间自愿中断的复制应用程序中宕机的 Pod 的数量。例如,基于定额的应用程序希望确保运行的副本数量永远不会低于仲裁所需的数量。Web 前端可能希望确保提供负载的副本的数量永远不会低于总数的某个百分比。
nodeSelector
将 pod 调度到具有匹配标签的节点上。Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有相应 taint 的节点上。
1.第一阶段,通过Taint(污点)、Toleration(容忍)、nodeSelector、nodeLabel、externalTrafficPolicy等k8s特性,将中间件节点与线上其他业务进行隔离。
a. Taint和Toleration,创建驱逐策略,将业务应用驱逐出该节点,集群内新生成pod不会调度到该节点,配合yaml中tolerations,实现该opentsdb pod不被该节点驱逐,命令举例如下:
$ kubectl taint nodes prod.op.k8s.mdnode-00.hz dedicated::NoSchedule-
$ kubectl taint nodes prod.op.k8s.mdnode-00.hz dedicated=opentsdb:NoSchedule
b.节点标签,创建节点标签,标示节点,用于筛选节点,配合yaml中nodeSelector,实现分配pod到指定节点,命令举例如下:
$ kubectl label nodes prod.op.k8s.mdnode-00.hz opentsdb=true
c. Deployment yaml配置,配合上面驱逐策略、节点标签,最终实现只有yaml中配置以下策略的应用能够在该节点启动,其他应用将不被调度到该节点,配置举例如下:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "opentsdb"
effect: "NoSchedule" nodeSelector:
opentsdb: "true"
2.第二阶段,容器化opentsdb,使用Deployment定义yaml,通过env标签自定义HeapSize大小,利用探针对opentsdb使用httpGet进行健康检查。
a. 健康检查,用于检测opentsdb是否正常运行,配置举例如下:
livenessProbe:
httpGet:
path: /
port: 4242
initialDelaySeconds: 600
periodSeconds:
failureThreshold: 3
b. 环境变量,用于往image中传递参数,实现自定义heap size,配置举例如下:
env:
- name: HBASE_HOME
value: "/opt/hbase/bin/"
- name: JVMXMX
value: "-Xmx4096m"
c. 滚动升级,滚动升级中,将先启动新pod再销毁老pod,配置举例如下:
strategy:
rollingUpdate:
maxSurge: 10%
maxUnavailable: 0
type: RollingUpdate
3.第三阶段,加入监控sidecar,将原有opentsdb监控脚本进行容器化,跟随opentsdb主进程启动,通过localhost访问opentsdb进程,传入监控数据。
a. 容器化监控脚本,容器化原有opentsdb监控脚本,配置举例如下:
#FROM python:2.7.15-alpine3.6
COPY requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY src /app
WORKDIR /app
CMD ["sh", "/app/start.sh"]
b. Deployment yaml添加sidecar,实现监控sidecar,监控进程跟随主进程启动,与主进程共享namespace,使用localhost直接访问主进程,配置举例如下:
- name: monitoring
image: harbor.ymmoa.com/monitoring/opentsdb-monitoring:v0.0.4
imagePullPolicy: Always
command: ["sh","/app/start.sh"]
1.Service 类型配置不当导致opentsdb crash
解决方法:起初service配置使用NodePort默认选项,进行压测pod状态一直正常,准备在node上面加一层SLB作为负载均衡,但是通过SLB压opentsdb就出现pod随机CRASH的现象。随后,调整Service 参数externalTrafficPolicy: Local,故障随后接触,通过SLB可以正常查询数据。
参数说明:service.spec.externalTrafficPolicy
的值为 Local
,请求就只会被代理到本地 endpoints 而不会被转发到其它节点。这样就保留了最初的源 IP 地址。如果没有本地 endpoints,发送到这个节点的数据包将会被丢弃。这样在应用到数据包的任何包处理规则下,你都能依赖这个正确的 source-ip 使数据包通过并到达 endpoint。
2.TSDB向后端HBase发送compaction请求,导致HBase执行该操作时跑满网卡 解决方法:对HBase配置了hbase.hstore.compaction.throughput.lower.bound和hbase.hstore.compaction.throughput.higher.bound参数后,限制HBase执行compacte操作时可用的带宽,以避免跑满网卡而影响正常的读写操作 参数说明:hbase.hstore.compaction.throughput.lower.bound, 合并占用吞吐量下限;hbase.hstore.compaction.throughput.higher.bound,合并占用吞吐量上限。
K8S节点监控
TSDB容器监控
TSDB监控
作者: 满帮集团技术保障部冷振国、朱慧君、王杰
领取专属 10元无门槛券
私享最新 技术干货