写点什么

经典案例复盘——运维专家讲述如何实现 K8S 落地

  • 2019-01-02
  • 本文字数:3625 字

    阅读完需:约 12 分钟

经典案例复盘——运维专家讲述如何实现K8S落地

背景介绍

运满满自开始微服务改造以来,线上线下已有数千个微服务的 Java 实例在运行中。这些 Java 实例部署在数百台云服务器或虚机上,除少数访问量较高的关键应用外,大部分实例均混合部署。


这些实例的管理,采用自研平台结合开源软件的方式,已实现通过平台页面按钮菜单执行打包、部署、启动、停止以及回滚指定的版本等基本功能,取得了不错的效果。但仍然存在如下几个痛点:


  1. 实例间资源隔离,尤其在高峰期或故障期间,单服务器上不同实例间 CPU 和内存资源的争抢特别明显。

  2. 线上某个应用实例异常时需要人工干预,导致较长的故障时间。

  3. 大批服务端应用新版上线后,如网站关键功能故障,需要针对每个应用,选择对应的版本,执行回滚操作,整个过程耗时较长。

  4. 线下 DEV/QA 环境频繁发布,每次发布都需要先停止老的版本再发布新的版本,会影响到日常测试。


运满满飞速发展的业务,对系统稳定性的要求越来越高,我们急需解决如上问题。

技术调研、选型

最初吸引我们的是容器技术良好的隔离和水平扩展等特性,而 Docker 的口碑以及几年前参与的一些 Docker 项目经验,使得采用 Docker 容器技术成了我们的不二选择。


但我们仍然需要一套容器编排系统,来实现自动化管理 Docker 容器,大致了解下来有 3 个选项:Kubetnetes(K8S)、swarm、mesos


这 3 个我们都不熟悉,而这个项目的节奏很紧迫,不允许我们对这 3 个系统深入了解后再做选择。好在 Github 有一个统计功能,我们在 Github 上查到了这 3 个开源项目的一些基本情况,如下图:





根据这份统计数据,以及拥有 Google 公司的光环,我们在很短的时间内确定了使用 K8S 作为容器编排管理系统。K8S,这个开源项目号称可以自动部署、扩展和管理容器应用,并且能解决如下核心问题:


负载均衡 - 一个应用运行多个同样的容器,内部 Service 提供了统一的访问定义,以负载均衡的方式来提供访问。


服务发现 - Service 和 Kube-DNS 结合,只需要通过固定的 Service 名称就可以访问到对应的容器,不需要独立寻找使用服务发现组件。


高可用 - K8S 会检查服务的健康状态,发现异常时会自动尝试重新启动服务,保障正常运行。


滚动升级 - 在升级过程中 K8S 会有规划的挨个容器滚动升级,把升级带来的影响降低到最小。


自动伸缩 - 可以配置策略当容器资源使用较高会自动增加新的容器来分担压力,当资源使用率降低会回收容器。


快速部署 - 编写好对应的编排脚本,可以在极短的时间部署一套环境。


资源限制 - 对程序限制最大资源使用量避免抢占资源遇到事故或压力也能从容保障基础服务不受影响。


进一步深入了解 K8S 之后,我们大致确定了会用到如下组件、相关技术和系统:


  • 应用部署 K8S Deployment,HPA;

  • 少量基础服务 K8S Daemonset, kube-dns;

  • 对外服务暴露 K8S Ingress, Traefik, Service;

  • 网络插件 Flannel;

  • 监控告警 Heapster, InfluxDB, Grafana, Prometheus;

  • 管理界面 Kubectl, Dashboard, 自研发布管理系统;

  • 制作镜像 Jenkins, Maven, Docker;

  • 镜像仓库 Harbor;

  • 日志收集 Filebeat, Kafka, ELK。

难点和基本原则

  1. 线上服务必须在不间断提供服务的情况下迁移,每个应用按比例切分流量,在确保稳定性的前提下迁移到 K8S 集群中。

  2. DEV 环境可批量上线,QA 和 Production 环境上线需要考虑各应用的版本依赖关系。

  3. 初期只上无状态的应用。

  4. 对研发/QA 的影响最小化(尽量不给繁忙的研发/QA 同学增加工作量)。

落地过程剖析

Docker 化前后应用发布流程对比

从下图中可以看到 2 个明显的变化:


  1. 之前部署的是 war 包、jar 包,之后部署的是 Docker 镜像(镜像中包含 war 包、jar 包)。

  2. 之前是先停止再启动应用进程,发布过程中服务会中断,之后是先启动新版本容器,再停止旧版本容器,发布过程中应用一直在提供服务。


迁移中的系统架构

当前业务应用主要分为 2 种,仅供内部应用调用的 RPC 服务(Pigeon 框架)和对外提供服务的 REST API,REST API 可进一步细分为 2 种,已接入 API 网关和未接入 API 网关。其中 RPC 服务和已接入 API 网关的应用均有自己的注册中心,迁移步骤相对简单,在 K8S 集群中启动对应的应用即可。未接入 API 网关的应用采用 K8S Ingress 插件提供对外服务入口,需要一些配置。系统架构如下图,最终目标是要实现将图中下方的两个框内的应用全部迁入 K8S 集群中。


Master 集群的高可用

由于公有云的限制,我们主要结合服务商提供的 SLB 来实现,示意图如下:


K8S 集群内应用对外提供服务

由于集群内 POD 的 IP 地址动态变化,我们采用 Traefik+Ingress+Nginx+SLB 的方式,来提供一个对外服务的统一入口。Traefik 根据 HTTP 请求的域名和路径路由到不同的应用服务,Nginx 则执行一些复杂的诸如 rewrite 等操作,SLB 提供高可用。架构示意图如下:


容器内应用初始化

为了实现同一个镜像可以兼容运行在 DEV、QA、Production 等各种环境,必须编写一个初始化脚本,该脚本被存放在镜像中。当容器启动时,从 Env 变量中读取当前所在的环境,并创建一系列软链到各环境对应的配置文件以及设置日志目录等其他初始化操作,随后 fork 一个新进程用于检测和设置该容器内应用是否已完成正常启动(配合容器 readiness 探针使用),同时调用应用启动脚本。


下图为容器内通过软链指向不同的环境配置文件:



下图为容器内通过软链设置日志目录:


K8S 日志收集

当前应用日志均以文件形式存放,且单个实例对应多个日志文件,无法采用 K8S 官方推荐的日志方案。同时由于容器的无状态化,我们必须另想其他办法保存日志。目前采用的是将 Node 上的固定目录作为存储卷挂载到容器内,在容器启动时通过初始化脚本按照应用名+容器 IP 生成该容器特定的日志路径。为了便于查看日志,我们提供 3 种途径:


  1. 容器内启用 SSH 服务端,发布管理系统中实现 WEBSSH,正常情况下可通过 WEB 页面进入容器命令行查看日志,由于其便利性,推荐首选此方式。

  2. 有些情况下容器会启动失败,此时无法进入命令行,可在发布管理系统中找到日志的链接地址,下载到本机后再查看。

  3. 此外,我们在所有 Node 上各运行一个 Filebeat 容器,将 Node 上收集到的日志实时发送到 Kafka 集群中,经过处理后存储到 ES 集群,以便日后检索。


下图为 Node 服务器上的日志目录结构:



下图为 Node 服务器上共享的日志下载路径:


K8S 监控

采用 Heapster+InfluxDB+Grafana 组合,需要注意的是其中 InfluxDB 用于存放监控数据,需要将数据持久化。在 Grafana 上制作了不同维度的 dashboard,可根据 Namespace、Node、应用名进行检索,可按照 CPU、内存、网络带宽、硬盘使用量筛选应用,方便故障排查和日常优化。(当然,更好的监控系统是 Prometheus,已经在上线的路上。)


下图为监控大盘:



下图为监控菜单:



下图为某应用的监控图:


Harbor 镜像仓库

Harbor 我们目前采用的是一主多从结构,主库与打包 Jenkins 都在线下网络中,镜像上传到主库后会被自动同步到线下另一个从库以及线上的从库中,如下图所示:


镜像树

我们的规划是构建一颗镜像树,所有的应用都基于这颗树上的基础镜像来构建应用镜像,各应用构建时选择最相似的基础镜像,再增加应用的特殊需求即可。基于此镜像树,我们 95%以上的应用均无需在 Gitlab 里放置 Dockerfile,Dockerfile 在打包时根据变量自动生成即可,例如:


下图为脚本自动生成的某应用 Dockerfile:



镜像树结构示意图如下:


当前状态

容器化:DEV/QA 环境的应用已完成 Docker 化,产品环境中应用约 98%已完成 Docker 化。


系统自愈:应用 OOM 或其他 Crash 时,系统能够自动拉起新的节点以替换故障节点,高级健康检查暂未开启(需其他方面配合)。


弹性伸缩:关键应用全部开启弹性伸缩,访问量高峰期观察到的效果很好。


滚动发布:可按指定的比例分批次部署更新应用版本,先更新一批,成功后销毁一批,依次滚动。


快速回滚:当前仅支持单应用快速回滚,后期如需要增加事务级回滚能力,采用 K8S 的 rollout 功能可以方便实现。

一些踩过的坑和建议

  1. 底层操作系统采用 CentOS7.x 版本,会比较省事。

  2. 阿里云经典网络中的 ECS 无法访问容器 IP,需要先迁移到 VPC 环境,其他公有云情况类似,重点是能自主添加路由。

  3. 如果有应用级监控的话,从容器内部采集到的 Memory,Load Average 等信息是底层操作系统的,而不是容器的,这些指标可以依赖专门的容器监控系统。

  4. 要注意 ulimit 的限制,容器中并没有对它进行隔离,设置过小的话会遇到一些莫名其妙的问题。

  5. 容器中的 root 用户用 netstat 命令可能看不到其他用户所创建的进程的 owner,如果有一些老式的脚本可能会遇到类似问题。

  6. 如果有一些内部系统需要直接访问容器的特定端口,headless service 挺好用。

  7. Zookeeper 有一个单 IP 连接数 60 的默认限制,如果没修改过该参数的话应用迁移到 K8S 之后可能会遇到此问题。

  8. 产品环境中的某个访问量大的应用往 K8S 迁移时,可以先分配较多数量的容器,确保能吃下所有流量,之后再根据监控,用弹性伸缩功能来减掉多余的容器。

  9. 如果想提前知道 K8S 集群的性能,部署好应用之后做一次压测很有必要。




作者简介


王春林,就职于运满满技术保障部,关注容器、DevOPS 等领域。


2019-01-02 14:179496

评论 4 条评论

发布
用户头像
请问一下, 有状态服务如mysql, redis, rocketmq是如何部署的。直接通过stateset部署在k8s里么?
2020-04-16 14:11
回复
用户头像
想问了一下不算业务系统,用了多少台机器,什么配置,多少个服务实例,每个服务多少个副本
2019-01-02 15:27
回复
建议的配置:
Master:2台~3台,每台8核16G,量少4核8G
ETCD:3台或5台(保持奇数),每台8核16G,量少4核8G
应用:每个服务至少2个副本
2019-01-25 14:34
回复
没有更多了
发现更多内容

度量BGP监测源数量对AS可见性的影响

郑州埃文科技

AS IP地址 BGP数据源

一个宁静祥和没有bug的下午和SqlSession的故事

京东科技开发者

mybatis sql Spring Boot CLI SQLSession

【Ajax】如何通过axios发起Ajax请求

坚毅的小解同志

ajax 11月月更

基于鸿蒙系统的ArkUI框架的公共剪切类属性和多态样式在前后端分离项目中的表现

恒山其若陋兮

11月月更

传输线路动态巡检探索

鲸品堂

网络 传输网络

Bigkey问题的解决思路与方式探索

vivo互联网技术

redis dba bigkey

旺链科技肖慧荣登超级账本2022年第三季度中国贡献榜

旺链科技

区块链 产业区块链 VoneBaaS 企业号十月PK榜

数维图智慧化工园区三维系统 助力危化企业安全生产

2D3D前端可视化开发

物联网 数据可视化 数字孪生 智慧化工园区 化工园区三维可视化

字节跳动基于数据湖技术的近实时场景实践

字节跳动数据平台

数据湖 火山引擎

LR低代码快速开发平台 高效调整企业组织架构

力软低代码开发平台

不懂Hybird开发,感觉错过一个亿~

FinFish

小程序 前端框架 APP开发 APP软件开发、 混合开发

深度解析KubeEdge EdgeMesh 高可用架构

华为云开发者联盟

云计算 云原生 后端 华为云

“如何实现高效的应用交付”鲁班会开发者训练营厦门站进行时

华为云开发者联盟

云计算 软件开发 华为云 应用集成

OpenHarmony 3.2 Beta多媒体系列——音视频播放框架

OpenHarmony开发者

OpenHarmony

Go定时任务源码 - robfig/cron

人生如梦

Go 定时任务 cron

5分钟搭建图片压缩应用

华为云开发者联盟

云计算 后端 华为云 函数工作流

通过实战总结的 使用Go的小技巧

王中阳Go

Go golang 高效工作 学习方法 11月月更

【jquery ajax】实现文件上传提交

坚毅的小解同志

ajax 11月月更

元器件科普|变压器的分类及形状构造

元器件秋姐

元器件采购 华秋商城 变压器 电感器 电压

【Ajax进阶】跨域和JSONP的学习

坚毅的小解同志

ajax 11月月更

【Ajax】如何通过axios发起Ajax请求

坚毅的小解同志

ajax 11月月更

4.0体验站|OceanBase 4.0 我回来给你点个赞

OceanBase 数据库

提升80%上云集成效率, TA是如何做到的

华为云开发者联盟

云计算 后端 华为云 云集成

基于Spring-AOP的自定义分片工具

京东科技开发者

aop 数据分片 spring aop 配置文件

SAP UI5 应用和 Angular 应用视图里控件 id 生成逻辑的异同比较

汪子熙

前端开发 angular SAP SAP UI5 11月月更

ArkUI框架基于鸿蒙系统的Scroll和Scroller和自定义组件之插槽的实战案例心得

恒山其若陋兮

前端 11月月更

【web 开发基础】PHP 变量的作用范围 (29)

迷彩

作用域 静态变量 全局变量 局部变量 11月月更

大模型狂欢背后:AI基础设施的“老化”与改造工程

OneFlow

人工智能 深度学习 大模型

【Ajax】全面了解http协议

坚毅的小解同志

HTTP 11月月更

【原生Ajax】全面了解xhr的概念与使用。

坚毅的小解同志

ajax 11月月更

计算机网络:数据链路层设备

timerring

计算机网络 11月月更 网桥

经典案例复盘——运维专家讲述如何实现K8S落地
_软件工程_王春林_InfoQ精选文章