55

DockOne微信分享(二一九):跨境时尚电商SHEIN基于Kubernetes的DevOps实践

 4 years ago
source link: https://www.tuicool.com/articles/2y6VFbr
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【编者的话】SHEIN PaaS参考了很多优秀的社区实践方案,最终使用了基于GitLab + Jenkins + Kubernetes + Harbor 的一套CI/CD工具集,一年多以来,总结开发出了一套公司自己的持续集成和发布的方案。本次分享着重介绍DevOps实践中几个比较值得分享的经验总结。

PaaS 平台介绍

PaaS 平台主要围绕 Dockerfile 和 DeployYml 这两个核心元数据,实现应用管理和流程管理等功能,目前完成了代码扫描,镜像构建,发布单审核,应用发布,流量控制,应用回滚,日志查看,运行状态查看,多集群管理 等功能。(Kubernetes 高可用集群搭建参考了优秀的社区项目: https://github.com/easzlab/kubeasz

bEfYv2M.png!web

PaaS

对发布到PaaS的项目代码没有额外的限制(不需要在代码的指定路径包含 Dockerfile、Jenkinsfile 等构建依赖)。充分利用 Dockerfile 的多阶段构建功能,在 Dockerfile 中包含三个阶段:克隆、编译、运行(运行环境只包含构建结果,实现了镜像的最小化)。同时借助 PaaS 提供的基础镜像构建功能,开发人员可以将项目依赖添加到编译镜像中进行缓存,实现镜像构建加速。这样在保证构建灵活性的同时又保证了构建效率。

NnmiYrA.png!web

应用 Dockerfile 示例

因为 Dockerfile 多阶段构建功能的使用,很多构建逻辑不需要在 Jenkinsfile 实现,复杂度降低,为提高可扩展性,减少因为逻辑变更带来的维护成本,PaaS 支持传参触发构建,也支持更新 job xml 配置增加参数等,更重要的是使用 jenkins library 功能,项目构建 job 中只包含传参和函数入口调用等极少的代码,真正的处理逻辑在 jenkins library 中实现,这样在保证了可扩展性的同时又减少了维护成本。

bUR77zA.png!web

jenkins-library 示例

通过图形化配置生成的 Deployment 等 yaml, 没有在 Jenkins 中发布,而是存储在数据库并直接调用 Kubernetes 接口部署,这样构建和发布分离,有很多使用方式上的考虑,比如,构建一次修改发布多次;只有构建没有发布(借助 Dockerfile 的多阶段构建,将编译结果发布到仓库,用于后续物理部署[特例]);快速回滚(从数据库中直接取出历史版本直接发布即可实现);蓝绿发布、流量控制等复杂逻辑(在平台代码中实现,比使用 Jenkinsfile 增加了复杂度更合适)。

3YRBBfY.png!web

配置应用

jIfIbia.png!web

应用回滚

发布到 PaaS 上的应用,可以使用多种方式去了解服务状态,比如:查看重启次数及上一次失败原因(error或者oom),查看启动事件(了解应用为什么 pending 或者启动失败),查看控制台日志,查看落盘日志(即使服务没有成功也可以看异常日志),进入容器查看进程状状态及配置(用于测试外部依赖的连通性等)。

famaIfZ.png!web

启动次数原因

uiYVzua.png!web

启动事件

uq2eymN.png!web

控制台日志查看

JFjINfv.png!web

落盘日志查看

iI3ayeR.png!web

进入容器

因为集群的差异性,目前还需要用户在不同集群单独创建应用,才可以构建发布到不同的集群。当然,理想的状态是,更抽象的定义应用,屏蔽集群差异,任意指定集群发布。这方面还有很长的路要走。

BfUJvqm.png!web

多集群管理(参考 Wayne)

告警管理平台介绍

告警管理平台:主要围绕告警规则和告警群组进行开发。支持添加企业微信、电话、短信告警群;告警规则和抓取规则的图形化配置;支持多集群。

aUbqQnz.png!web

告警规则配置

7bMZBfa.png!web

抓取规则导入

nQv6bej.png!web

企业微信告警

如下是集群管理员和用户日常查看的监控图:(后续将用户常看的服务指标在 PaaS 中直接展示)

zYZNZjv.png!web

集群视角

qmMvi2e.png!web

节点视角

zy6N7fY.png!web

Pod 视角

提升集群稳定性实践

在集群搭建运行一年多以来,目前已趋于稳定,期间遇到了很多问题,这里做了些能够增加集群稳定性的总结。

1、配置资源限额可以有效的提高节点和集群稳定性,需要创建应用时为每个服务添加默认资源限额。同时创建 limit-range,为每个没有指定资源配额的服务增加默认限制。

2、低版本内核存在诸多已知问题,比如,3.10 内核集群, calico node 频繁重启解决:sysctl -w net.ipv4.tcp_tw_recycle=0,目前使用内核 4.18.16 版本,稳定运行半年未发现内核相关异常。

3、Pod 长时间 terminating 状态,可能导致 kubelet 状态异常,登陆宿主机,kill -9 对应容器进程临时解决。需要添加 terminating 状态监控,并使用 my_init 改造 Dockerfile,解决因为僵尸进程等进程回收失败导致的无法删除问题。

4、真正做到平滑升级,需要服务:配置就绪探针、配置存活探针、配置 sleep 10 的终止前钩子(如果注入了 istio sidecar,sidecar 也需要配置终止前钩子)、代码处理 SIGTERM 信号主动中断连接。另外如果使用执行命令进行健康检查,所执行的命令不能太耗资源性能,否则可能导致服务异常时,节点负载过高。

5、设置 kubelet 资源预留时,谨慎配置系统资源预留,发现在 Master 节点为 kubelet 配置资源预留导致 Master 组件频繁重启故障。

6、添加节点线程数,打开文件句柄数监控,提前发现异常服务,防止主机资源耗尽。

查看进程子进程数:

find /proc/*/task -maxdepth 0 -type d |while read dir; do count=$(ls "$dir" | wc -l); echo "$dir : $count"; done

查看进程打开文件句柄数:

find /proc/*/fd -maxdepth 1 -type d | while read dir; do count=$(find "$dir" | wc -l); echo "$dir : $count"; done

Q & A

Q:请问 CI/CD 中发布镜像是以 Master 分支吗,平时开发与 Master 分支是怎么样进行管理的。如何保证镜像是从测试到生产是使用同一个镜像,保持环境的一致性?

A:项目中创建多个应用,每个应用跟分支绑定,构建时可以选择指定的 CommitID 或者 tag 版本。测试,预发布,生产环境网络是隔离的,没有做到镜像统一,但实现了测试单和发布单功能,由测试人员和项目管理员保证发布代码的规范性。

Q:这样怎么保证上线的功能是正常测试过的呢?还是通过代码比对后,保证代码一致性,预发布,生产环境重新测试?

A: 因为我们多个环境网络是强制隔离的,代码一致性目前只能通过测试人员去保证,在测试环境会生成测试单,并且构建时是可以指定构建的代码版本的,测试单和代码版本进行关联,在生产环境发布时会有发布单,这个也是要测试和项目。

Q:CI/CD 在发布时再管理 Dockerfile,还是由开发进行维护 Dockerfile 文件?需要制定哪些规范?有没有可供大家参考的?

A:Dockerfile 有 PaaS 平台统一管理,和应用关联,不和代码关联。使用多阶段构建,目前还在开发图形化编写 Dockerfile 功能,限制使用的克隆镜像,编译镜像和运行镜像,只允许在给定的基础镜像基础上进行自定义,并使用 my_init 作为启动命令,以解决僵尸进程等异常进程导致的 Pod 无法删除问题。

Q:不好意思,不太明白后面限制和删除是什么意思,能详细讲解一下吗?

A: "限制"是使用运维提供的编译和允许镜像作为基础镜像。"删除"是通过规范 Dockerfile,引入 init 系统,规避多进程容器带来的容器支持的不是太好的多进程问题。

Q:Kubernetes 的网络是采用的什么架构,有做策略吗?

A:网络目前使用的是开源项目 Calico,目前没有做网络策略限制,只是每个项目有相对独立的一组机器,简单的物理隔离。

Q:日志处理方面有没有什么好的经验,踩过哪些坑?

A:日志使用 EFK ,统一落盘到指定 cephfs storageclass,由运维配置 fluentd 配置文件,但这种方式增加了很多运维工作量,目前还在开发 fluentd-operator,实现动态配置数据源和过滤规则等。

Q:Jenkins 是使用的 Kubernetes 的组件部署,还是在用脚本或者pipeline方式进行发布的呢?怎么做的金丝雀呢?

A:Jenkins Master 部署在 Kubernetes 中,发布在 PaaS 上做,和 Jenkins 没有关联,Jenkins 只负责代码扫描和镜像构建。

Q:问一下上预生产时,代码是否已合并到 Master 了?如果是合并后上预生产时失败了,是在 Master 拉 hotfix 分支进行修复还是回滚 Mastar?

A:分支是研发自己管控,是否合并 Master 是研发自己决定,回滚也是研发自己定,分支不切。

Q: 你们应用发布到生产环境是一个应用单独发布么,如果有多个应用一起发布怎么处理?

A:目前是每个应用单独发布,已经有反馈应用关联发布,暂未实现,还在需求收集中。

Q:如何通过 EFK 监控服务的错误日志?当有错误日志时是否有相关的告警?

A: 目前监控了 Kubernetes 各组件的错误日志,在 Grafana 中做告警和展示,还未做到服务错误日志告警,另外,公司有日志中心,部分服务会将日志接到日志中心处理。

Q:请问如果基于 GitLab + Jenkins + Rancher 封装一套 CI/CD 系统这个方案可信度怎么样?需要注意啥问题?或者说有没有更好的方案?

A:前端组目前使用 GitLab Runner 做构建,如果不考虑自研的话,可以借鉴下 GitLab 的 CI 功能。

Q:集群是 kubeam 搭建的还是二进制部署?etcd 和 Master 分开的么?

A:Kubernetes 搭建参考了 https://github.com/easzlab/kubeasz ,二进制部署,可以关注下这个项目 :),三个 etcd 节点和 Master 共用。

Q:Prometheus 这边有和其它数据库结合存储么?是只使用它自带的存储么?你们一般存多久数据?

A:Prometheus 使用的是 Ceph 存储,使用联邦模式,联邦节点存 14 天,子节点存两天。

Q:磁盘 IO,网络 IO 的资源配额怎么设置?

A:磁盘 IO 有测试过修改 cgroup 实现,但目前线上还没有做。网络带宽限制 Calico 已经支持,通过配置 Annotation 就可以实现。

Q:请问服务发现怎么做的?

A:除了一些 Java 服务使用了 Consul,其他服务还是使用的 Kubernetes 的 Service 直接互相调用。

Q:请问一下,解决 Pod terminating 的具体方法是什么:

A:可以参考下: https://www.jianshu.com/p/159d34e93d42

Q:集群内外的服务交互怎么做的,谢谢。

A:因为使用的是开源的 Calico 网络方案,暂时没有自研,集群外部访问 Pod IP 需要在网关节点配置路由才能实现,目前还是通过 Ingress 统一出口。也还在调研其他网络方案。

Q:请问配置中心这块是如何做的?

A: ConfigMap 加 Nacos(测试环境),另外运维在开发自己的配置中心。

以上内容根据2019年8月6日晚微信群分享内容整理。分享人 王国庆,南京希音电子商务有限公司PaaS平台工程师,负责PaaS平台的搭建及维护 。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK