DockOne微信分享(二三〇):Kubernetes在SHAREit的落地实战


【编者的话】SHAREit作为一个全球拥有18亿用户的互联网企业,为了支撑业务的高速发展,满足对降本增效的要求,我们选择了Kubernetes做为基础架构升级的一个重要方向。Kubernetes只是一个通用性的容器编排框架,真正在一个单位实战落地,尤其是大规模应用,需要结合公司实际情况和场景,做很多领域的探索实践。本文主要介绍了Kubernetes在SHAREit大规模落地的一些经验和思考。

SHAREi在全球用户超过18亿,服务人数接近世界五分之一人口,业务成绩登顶五大洲超过70多个国家和地区的下载榜单,单从用户规模上和市场广度来说,SHAREit在全球范围内已颇具实力。为了更好的保障公司业务高速发展,SHAREit服务保障团队从2018年开始小范围试落地kubernetes,到2019年9月,实现了公司无状态业务all in Kubernetes的目标。目前生产环境Kubernetes集群Node节点数 1000+(机型配置64c 250G),Pod数13000+,包括常规业务和大数据业务。本文聚焦于Kubernetes在SHAREit落地过程中,我们在以下4个方面所做的努力:

Kubernetes产品化和可视化

scmp是我们基于Kubernetes的一站式多云Kubernetes的管理平台。对Kubernetes提供的原生功能进行再度抽象,提供了简易的操作界面和向导式的操作,极大减轻开发、测试、运维的日常工作的复杂度。具体架构图如下:
1.jpg

避免被一家公有云锁定,我们IaaS层提供商包括AWS、华为云、阿里云等。为了屏蔽各家托管Kubernetes的差异性,我们中间加了一层适配层,把各家公有云当做一个个provider。这样做的结果是,我们随时可以部署一个应用到任意的云上,也可以随时迁移一个应用到其他的云上。

scmp与公司统一认证平台做了集成,未来将进一步解耦,支持LDAP和数据库认证。然后作为一个公司级别的平台,包含了用户管理,角色管理,资源管理等完善的权限管理体系,我们会根据角色QA、运维以及各个不同的研发Team作相关账号分组,每个相关部门的同学只能访问到指定的应用。同时提供了详细的操作审计,便于误操作恢复和故障追溯。

此外scmp包含了如下的功能:

集群管理

2.jpg

该功能模块纳管Kubernetes集群,同时提供了每个集群的总体预览功能,包括核心组件(kube-apiserver、kube-controller-manager、kube-scheduler、etcd)的监控状态,节点的监控状态,集群级别CPU和Memory申请,实际使用曲线图。
3.png

命名空间管理

4.jpg

该模块除了常规的新建和修改功能外,将命名空间增加了镜像拉取秘钥和标签两个元数据属性,统一在命名空间这个级别设置之后,然后在该命名空间里部署的资源对象,都会被拦截并注入到资源对象里,比如Deployment、ConfigMap、Service、Ingress等。这样的好处,一方面是便于后期的资源计费和审计,另外一方面是便于统一配置。后续我们会考虑将配额管理也加入到命名空间的管理当中,目前来看互联网企业对配额不是一个强需求。

同时我们也提供了命名空间级别的预览功能,包含了集群状态,Pod数,命名空间CPU和Memory申请,实际使用,利用率曲线图。
5.jpg

由于我们实际落地过程中,每个部门对应一个命名空间,所以部门技术leader会经常关注这块,查看部门资源利用率。

Node节点管理

6.jpg

该模块主要面向运维同学。比如有如下的实际场景:
  • 需要下线替换某些Node节点。此时需要调度控制功能,将该Node标记为不可调度,然后再驱赶该Node上的Pod,最后完成Node的替换。
  • 污点管理。例如Promethues这种高耗CPU和Memory的系统组件,如果和关键业务应用混跑到一台Node节点上,在高峰期容易影响关键应用响应时间。此时就可以使用污点管理功能,配合Pod级别的容忍来实现。
  • Webshell。在某些特殊情况下,需要快速SSH到指定主机上进行debug。
  • 标签管理。例如给不同的机型,根据特点打上不同的标签,例如:storage:ssd等,配合Pod的nodeSelector和亲和性,满足业务更复杂的调度要求。


在主机列表页,点击某个主机节点打开其详情页,可以看到当前主机更详细的信息,包括主机的CPU 、内存和容器组资源运行和使用状态,以及事件(Events)和更细粒度的监控信息。

配置中心

该模块主要包括ConfigMap和Secret的管理。此处重点讲下,我们对于ConfigMap的功能增强。原生ConfigMap不提供版本管理和回滚的功能,而实际使用场景中,作为一个配置中心需要具备版本管理的功能,具体配置管理如下:
7.jpg

我们提供的回滚操作如下:
8.jpg

Ingress管理

部署一个应用,很多时候需要被集群外访问,此时Ingress是一个很好的方式。

此处支持Ingress手动和自动两种创建方式。由于Ingress对应公有云资源的LB,所以当自动创建模式的时候,我们要求填写至少三个统计维度(env、group、project)的标签,方便账单系统进行分析。
9.jpg

存储管理

我们主要业务在公有云上,所以我们没有实现自己的存储。我们对接了共有云的存储,主要包括块存储,文件存储等。
10.jpg

目前除了Prometheus和部分MQ,我们没有做太多的有状态服务的尝试。

应用部署

应用部署是所有功能中最重要也是最丰富的一个模块。包含了新建(可视化和yaml两种方式)、修改、删除、重启、回滚、手动扩缩等功能。
11.jpg

点击应用,可以进入应用详情页。我们不仅将CronHPA,金丝雀等增强功能集成了到了应用详情当中,而且将监控和日志等DevOps内容集成进来,我们希望用户可以一站式操作应用,并且具备完善的可观察性。
12.jpg

同时,由于业务部署方式由传统的虚拟机转变为容器,出于安全和稳定性考虑,我们不可能继续让业务研发在debug的时候SSH到具体的主机上。所以我们开发了Pod的webshell,查看标准输出log,查看Pod事件等功能。
13.jpg

Kubernetes与DevOps的深度结合

从一开始,我们就坚持认为脱离了DevOps,Kubernetes将不具备可观察性。而且一个不合适的日志方案或是监控方案,会影响Kubernetes的稳定性。所以我们在落地Kubernetes之前,花费了大量时间完善公司的监控和日志系统。

业务日志收集方案

社区中关于Pod日志收集,有以下三种方式:
  • 将日志收集Agent打到业务容器镜像中。
  • 将日志收集Agent作为sidercar的方式与业务容器运行在同一个Pod中。
  • 宿主机Node层面统一收集:将宿主机的目录挂载为容器的日志目录,然后在宿主机上收集。


第一种方式,耦合性太高,收集日志Agent的问题会影响业务进程的正常运行。第二种方式,和最近流行的富容器思想有点类似。但是结合我们的日志量,我们选择了第三种日志收集方式,日志收集组件通过DaemonSet的形式运行在所有Node节点上。

为了稳定性和业务对于日志要求,我们做了如下的工作:
  • 我们会将一块1T大小的块存储挂载到Node节点上,作为数据盘(/data)。保证系统盘和数据盘分离。该数据盘主要用来存放业务日志和镜像。
  • 防止若干写日志比较多的Pod调度到同一个主机上,将数据盘写满,影响到其他的业务,以及防止日志收集系统有故障期间,日志丢失。我们编写了applog-cleaner组件,会定期清除旧日志数据。我们承诺保留最近两天的日志。
  • 容器本身的特点就是太多的不确定性,并且在弹性扩缩容的时候,你无法确定你的Pod调度到哪一个具体的计算节点,导致我们无法事先配置好日志收集路径。而我们规定业务日志的收集目录是/data/logs/命名空间名/应用名/poduid/下,所以我们自研了hostpathperpod volume组件。该组件通过flex volume实现,在Pod视角,业务依旧将日志写到了/data/logs下,实际上该目录挂载到了主机的/data/logs/命名空间名/应用名/poduid/ 。而在Pod的yaml中,如下配置即可:


volumes:
  - flexVolume:
      driver: sgt.shareit.com/hostpathperpod
      options:
        hostPath: /data/logs
    name: log-dir

我们日志收集的Agent选用Filebeat。

当业务跑在容器中,业务日志往往需要增加Pod的一些元数据,方便在出现问题的时候排查定位。为了配合上面的方案,我们fork了Filebeat的代码,增加了一种新的matchers——hostpath。在Filebeat的配置文件中如下:
- add_kubernetes_metadata:
in_cluster: true
host: ${NODE_NAME}
# namespace: ${POD_NAMESPACE}
default_indexers.enabled: false
default_matchers.enabled: false
indexers:
  - pod_uid:
matchers:
  - logs_path:
      logs_path: /data/logs/
      resource_type: hostpath

监控方案

SHAREit整个监控系统Hawkeye基于Prometheus和M3DB实现。没有使用Prometheus官方联邦的特性。引入M3DB, 可以实现采集和查询分离的架构,提升整个监控系统的稳定性,所以我们每个集群的Prometheus只是我们整个监控体系的一个采集端而已。
14.png

这样的架构好处在于:
  • 采集查询分离。我们严格规定不得从采集Prometheus查询数据。如果是单一的Prometheus,在实际使用中,大家在查询了一个较大时间维度后,Prometheus会OOM,这个时候,你在Grafana中看到,你的曲线是有中断的。同时查询端,可以多个Prometheus,前置一个LB,起到高可用的作用。
  • metrics,不仅仅是在监控领域发挥作用,而且对于资源的计费和审计也是极其重要的,将不同采集源的metrics汇聚到一个TSDB集群中,提供了一个全公司的维度。同时对于后续的AIOps也是非常重要的。


M3DB是一个分布式时间序列数据库,提供可扩展存储和时间序列的反向索引。它经过优化,具有成本效益,并且可以在较长的保留时间内可靠地存储大规模指标。
15.png

在生产环境,我们3个etcd节点单独部署,6个高配主机作为storage节点。

M3Coordinator作为sidecar的方式,与Prometheus部署到同一个Pod中。之所以这么部署,因为同一个Pod同一个network namespace,网络优势更大。

同时建议大家部署kube-state-metrics组件,将更详细的metrics采集到监控系统中。

具体Kubernetes集群中的关于监控的配置文件如下:
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: prometheus
name: prometheus
namespace: kube-admin
data:
prometheus.yml: |-
global:
  scrape_interval: 30s
  evaluation_interval: 30s
  # The labels to add to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
    cluster: 'SGT-eks-apse1-prod'
# Settings related to the remote write feature.
remote_write:
  - url: "http://localhost:7201/api/v1/prom/remote/write"
    queue_config:
      max_samples_per_send: 60000
scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets:
        - localhost:9090
  - job_name: kube-state-metrics
    static_configs:
      - targets:
        - kube-state-metrics.kube-system:8080  
  - job_name: kubernetes-apiservers
    kubernetes_sd_configs:
    - role: endpoints
    relabel_configs:
    - action: keep
      regex: default;kubernetes;https
      source_labels:
      - __meta_kubernetes_namespace
      - __meta_kubernetes_service_name
      - __meta_kubernetes_endpoint_port_name
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify: true
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token

  - job_name: kubernetes-nodes-kubelet
    kubernetes_sd_configs:
    - role: node
    relabel_configs:
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+)
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify: true
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token

  - job_name: kubernetes-nodes-cadvisor
    kubernetes_sd_configs:
    - role: node
    relabel_configs:
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+)
    - target_label: __metrics_path__
      replacement: /metrics/cadvisor
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify: true
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token

  - job_name: kubernetes-service-endpoints
    kubernetes_sd_configs:
    - role: endpoints
    relabel_configs:
    - action: keep
      regex: true
      source_labels:
      - __meta_kubernetes_service_annotation_prometheus_io_scrape
    - action: replace
      regex: (https?)
      source_labels:
      - __meta_kubernetes_service_annotation_prometheus_io_scheme
      target_label: __scheme__
    - action: replace
      regex: (.+)
      source_labels:
      - __meta_kubernetes_service_annotation_prometheus_io_path
      target_label: __metrics_path__
    - action: replace
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2
      source_labels:
      - __address__
      - __meta_kubernetes_service_annotation_prometheus_io_port
      target_label: __address__
    - action: labelmap
      regex: __meta_kubernetes_service_label_(.+)
    - action: replace
      source_labels:
      - __meta_kubernetes_namespace
      target_label: kubernetes_namespace
    - action: replace
      source_labels:
      - __meta_kubernetes_service_name
      target_label: kubernetes_name

  - job_name: kubernetes-services
    kubernetes_sd_configs:
    - role: service
    metrics_path: /probe
    params:
      module:
      - http_2xx
    relabel_configs:
    - action: keep
      regex: true
      source_labels:
      - __meta_kubernetes_service_annotation_prometheus_io_probe
    - source_labels:
      - __address__
      target_label: __param_target
    - replacement: blackbox
      target_label: __address__
    - source_labels:
      - __param_target
      target_label: instance
    - action: labelmap
      regex: __meta_kubernetes_service_label_(.+)
    - source_labels:
      - __meta_kubernetes_namespace
      target_label: kubernetes_namespace
    - source_labels:
      - __meta_kubernetes_service_name
      target_label: kubernetes_name

  - job_name: kubernetes-pods
    kubernetes_sd_configs:
    - role: pod
    relabel_configs:
    - action: keep
      regex: true
      source_labels:
      - __meta_kubernetes_pod_annotation_prometheus_io_scrape
    - action: replace
      regex: (.+)
      source_labels:
      - __meta_kubernetes_pod_annotation_prometheus_io_path
      target_label: __metrics_path__
    - action: replace
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2
      source_labels:
      - __address__
      - __meta_kubernetes_pod_annotation_prometheus_io_port
      target_label: __address__
    - action: labelmap
      regex: __meta_kubernetes_pod_label_(.+)
    - action: replace
      source_labels:
      - __meta_kubernetes_namespace
      target_label: kubernetes_namespace
    - action: replace
      source_labels:
      - __meta_kubernetes_pod_name
      target_label: kubernetes_pod_name

m3coordinator.yaml: |-
listenAddress:
  type: "config"
  value: "0.0.0.0:7201"

metrics:
  scope:
    prefix: "coordinator"
  prometheus:
    handlerPath: /metrics
    listenAddress: 0.0.0.0:7203 # until https://github.com/m3db/m3/issues/682 is resolved
  sanitization: prometheus
  samplingRate: 1.0
  extended: none

tagOptions:
  idScheme: quoted

clusters:
# Fill-out the following and un-comment before using, and
# make sure indent by two spaces is applied.
  - namespaces:
      - namespace: default
        retention: 48h
        type: unaggregated
      - namespace: metrics
        type: aggregated
        retention: 720h
        resolution: 5m
    client:
      config:
        service:
          env: default_env
          zone: embedded
          service: m3db
          cacheDir: /var/lib/m3kv
          etcdClusters:
            - zone: embedded
              endpoints:
                - 172.xx.61.23:2379
                - 172.xx.70.225:2379
                - 172.xx.77.220:2379
#                ... etc, list only M3DB seed nodes
      writeConsistencyLevel: majority
      readConsistencyLevel: unstrict_majority

CI/CD

该方案中,我们选用了Jenkins。Jenkins拥有几千种功能强大的插件,可以不需要太多的开发,就可以满足业务研发的需求。

底层我们封装了静态代码质量检测,单测,构建,打镜像等功能,以模块化的思想提供Pipeline,业务研发可以根据自己实际需求,类似搭积木的方式组建自己的CI/CD,比如,在测试环境,某些业务部门会把静态代码检测加到CI的环境中,而在Autotest环境中则不会这样做。我们集成了Jenkins的API,在UI上可视化操作,业务研发或是运维只需要拖拉具体的模块即可。

我们所有的镜像都会通过Clair镜像扫描,保证安全性。

在CI/CD这块,后续我们会将整个Jenkins系统容器化,利用Kubernetes动态扩缩的特点,进一步提升构建系统的资源利用率和减少构建高峰期的排队。

自研多种组件,满足业务更多需求

Kubernetes提供了CRD、Webhook、CSI、CNI、CRI等多种方式增加其可扩展性。在实际落地过程中,我们根据业务的需求以及我们对于Kubernetes的理解,我们开发了一系列的组件,进一步丰富Kubernetes的功能,加强应用容器化的规范,降低研发的工作量。

injector

该组件基于Kubernetes 中 ValidatingAdmissionWebhook和MutatingAdmissionWebhook两个功能实现。实现的功能包括:
  • 检查部署到生产环境中的应用,资源的limit和request是否相等,保证业务的稳定性。同时检查是否具有env,group,project等标签,方便后续的分析和审计。检查容器是否以特权容器模式运行。
  • 根据Pod的annotations,注入volume或环境变量或注入特定功能的init container或注入sidecar辅助容器。例如AKSK,之前我们的业务代码运行在虚机上,引用了公有云的SDK后,SDK会自动优先到某路径下查找credentials文件,获取访问对应资源的操作凭证。在容器化的过程中,我们为了让业务代码不做任何更改,所以会自动注入AKSK到指定路径下。同时也保证了AKSK的安全,避免了泄露的风险。


add-resource-tags

在公有云的环境中,例如LB和块存储等IaaS层资源,需要打各种标签,方便账单分析。但是大多数的托管Kubernetes并没有提供类似的功能,尤其是一些自动创建的资源,比如Ingress、PVC等。所以我们研发了add-resource-tags组件,该组件监听了Service、Ingress、PVC等资源对象,当发现以上三种对象创建或是修改后,会将对应的标签通过调用公有云的SDK,给对应的IaaS层资源打上标签。

eventer

该组件source为Kubernetes的event。然后设计了类似于日志收集的Pipeline的方式,包括print,drop or add metadata,周期内merge等filter,通过yaml配置文件的方式针对某种类型的event或是针对某种插件做各种设置,从而满足不同环境,不同集群,不同业务团队对于event报警的差异性需求。该组件sink到公司统一的报警平台,然后分发给不同的团队,目前支持DingTalk和邮件两种方式。

prophet

该组件主要包含了cron hpa, custom hpa, canary部署等功能。主要利用CRD的扩展方式实现。

在业务实际使用的场景中,官方HPA并不能完全满足业务,所以我们开发了cron hpa和custom hpa。

cron hpa主要用于有着明确高峰期和低峰期的业务类型,比如我司的push业务,每天在固定的时间进行全量push,所以我们完全利用cron hpa在push前自动增加Pod数目,在push 后,降低Pod数目。

原生的HPA,冷却时间是针对controller全局设置的,而Pod扩缩的比例和数目是硬编码在代码中的。而实际中不同的应用程序,其对扩缩容的要求也不同。例如:
  • 关键流量处理应用:该类应用希望在流量到来时快速的扩容,在流量高峰过去后,希望慢慢的缩容,以避免流量反弹。
  • 关键数据处理应用:该类应用希望当大量数据到达时希望快速扩容,在数据减少时,希望快速的缩容,以节省成本。
  • 一些不重要的业务,我们希望缓慢的扩缩,避免抖动,尤其是频繁的扩缩,可能导致Node节点的频繁的扩缩。


所以我们定义了自己的HPA,可以允许研发针对具体的应用设置自己的扩展冷却时间,收缩冷却时间,metrcis计算周期,以及每次伸缩的比例或是固定的个数。

在实际落地过程中,基于CPU和Memory的HPA,并不能很好的满足扩缩要求。所以我们正在开发基于外部metrics的HPA,对接监控系统和公有云厂商的云监控。比如消息队列积压数和QPS。

最后我们知道Kubernetes提供了recreate和rollup两种升级方式。在核心业务上线的过程中,研发更希望通过金丝雀的方式发版。所以我们开发了canary部署。具体思路是,研发开启某个deployment的金丝雀发版,控制器会自动启动指定数目的canary版本Pod,然后研发通过监控和log等方式判断canary的功能是否正常来决定是否对此次金丝雀发版提交或失败回退。

spark-ui-controller

为了落地Spark on Kubernetes,基于Kubernetes watch机制,我们开发了spark-ui-controller,结合泛域名解析,实现查看spark driver的管理UI。

容器及基础设施优化

  • 操作系统优化:单机支持百万TCP并发,/etc/sysctl.conf,/etc/security/limits.conf。传统的虚拟机基本上运行一个业务,很多内核参数不需要过多更改,即可满足业务。但是在Kubernetes中,一个Node节点会混跑,此时必须优化一些内核参数,从而满足混跑业务。
  • 基础镜像的优化和把控。一方面,容器镜像的内核参数并不是全部继承了Node主机,所以对于核心高并发业务,必须在镜像内核级再次调优。另外一方面,出于安全的考虑,所以我们专门定制了基础镜像,供业务研发使用。
  • CoreDNS。在实际大集群中,DNS实例数目需要根据集群规模或是Pod数目进行扩缩。但是传统的PHA存在诸多问题,并不适合用于CoreDNS的扩缩。我们选择了dns-horizontal-autoscaler,进行梯度扩缩。此外CoreDNS耗费资源非常小,尤其是在集群规模比较小的时候,及其容易被调度到同一台主机,假如恰好调度到一台上,当由于物理故障,Node节点需要下线的时候,会引起大面积DNS解析失败。所以需要加上Pod的硬反亲和。
  • 修改Docker存储目录和kubelet存储目录到数据盘,做到数据盘和系统盘分离。
  • 配置Node节点的系统预留资源和Kubernetes预留资源,防止雪崩。
  • 对于一些高并发业务,使用Kubernetes svc spec external TrafficPolicy: Local方式,不对客户端IP做SNAT。Local模式性能最优最稳定。
  • 业务优化,主要是容器感知容器分配资源。例如Java程序,我们选择了OpenJDK 8u212版本。对于Go程序,我们设置了CPUs环境变量,而代码中在init函数中根据环境变量值设置GOMAXPROCS。


未来的工作

  • 加强应用容灾能力,增加备份和一键恢复功能。
  • 将自研插件和集群管理采用cluster-operator的模式,方便集群管理。进一步提高集群管理者的工作效率。
  • 扩展Kuberntes调度器,增加更丰富的调度方式,比如组调度。
  • Service Mesh试落地和产品化。
  • 我们已经配合大数据团队做了Spark on Kubernetes的实践工作。接着我们将配合基础架构和推荐团队,做好AI on Kubernetes和Flink on Kubernetes等。


Q&A

Q:直接采用物理机还是有先做IaaS层虚拟化?
A:我们做的是出海业务,基本上考虑到合规等问题,我们主要项目全部运行在公有云上。

Q:有没有碰到调度的问题,某台服务器CPU或内存高了仍调度到这台上?
A:遇到过,一般情况下,需要考虑你的应用是否加了很多亲和性或是nodeSelector。正常的调度器,是会优先考虑资源平衡的。

Q:请问一下CoreDNS如何反解析Pod的IP地址?不用SVC的情况下,是否可以解析Pod的名字?是否有用CoreDNS的rewrite插件。
A:这个不清楚,我们没有这样的场景。但是CoreDNS,支持编写自己的插件。

Q:请问下,不同云之间的延时怎么解决?你们是一朵云就部署一个完整的业务么?
A:我们会在不同云之间通过专线打通。基本上相关联的业务会部署在一家云上。但是我们会尽量保证同一个业务部署在不同的AZ。

Q:告警策略上有没有最佳实践分享?
A:我们的统一报警平台基于Alertmanager实现,基本上用到了它提供的静默、分组、抑制等特性。只不过我们对接了它的API,也集成到SCMP当中。

Q:配置管理是怎么做到不同环境,不同配置?
A:我们的配置是在ConfigMap结合数据库来实现版本管理,本质上每个集群都需要单独设置。所以不同的环境,设置不同的ConfigMap即可。

Q:业务的数据库是在Kubernetes里面运行,还是单独搭集群?
A:我们除了Prometheus和一些MQ,我们目前还没有尝试有状态应用。

Q:Linux内核参数优化具体你们碰到过哪些坑呢,怎么优化的呢?线上使用的CentOS版本和内核如何选择的?
A:我们使用的是公有云,内核版本一般公有云提供版本中最新的。其实不同的主机类型,相应的参数不一样,需要在选型主机的时候,做大规模测试。比如net.netfiletr下的参数。我们会基于公有云镜像,做优化,然后利用pakcer打成新的镜像使用。

Q:自研组件,可以开源吗,比如日志的那个?
A:SHAREit是一个技术非常open的单位。我们从上到下,鼓励技术人员去分享。所以如果大家有需要,我们会做一下内部的整理,开源出去。同时,我也会写一些具体的文章,来讲具体的细节。

Q:Alertmanager报警,我使用的Prometheus Operator安装的,使用默认的微信报警,这个报警时区问题,是修改源码解决,还是使用一个webhook?报警的模板文件是如何管理的?
A:我觉得你应该需要重新定制Alertmanager的镜像,在Dockerfile中修改时区。其实我们这边也fork了Alertmanager,做了一些优化和功能增强,比如直接将DingTalk集成进来,避免引入webhook组件,所以我们也是自己打的镜像。至于报警模板,我们这边先把报警模板数据存放到数据库当中,然后结合confd来实现Alertmanager 配置文件刷新的。

以上内容根据2019年10月15日晚微信群分享内容整理。 分享人iyacontrol,SHAREit Kubernetes和DevOps技术负责人。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册