/app/log
目录(如果没有会自动创建)挂载到容器的 /usr/share/log
中 。这样服务在将日志写入该文件夹时,就能持久化存储在宿主机上,不随着 docker 的销毁而丢失了 。
当然,当部署集群变多后,物理宿主机上的日志也会变得难以管理 。此时就需要一个服务编排系统来统一管理了 。从单纯管理日志的角度出发,我们可以进行网络上报,给到云日志服务(如腾讯云 CLS)托管 。或者干脆将容器进行批量管理,例如Kubernetes
这样的容器编排系统,这样日志作为其中的一个模块自然也能得到妥善保管了 。这样的方法很多,就不多加赘述了 。
k8s 服务控制器的选择镜像优化之外,服务编排以及控制部署的负载形式对性能的影响也很大 。这里以最流行的Kubernetes
的两种控制器(Controller):Deployment
与 StatefulSet
为例,简要比较一下这两类组织形式,帮助选择出最适合服务的 Controller 。
StatefulSet
是 K8S 在 1.5 版本后引入的 Controller,主要特点为:能够实现 pod 间的有序部署、更新和销毁 。那么我们的制品是否需要使用 StatefulSet
做 pod 管理呢?官方简要概括为一句话:
Deployment 用于部署无状态服务,StatefulSet 用来部署有状态服务 。这句话十分精确,但不易于理解 。那么,什么是无状态呢?在我看来,
StatefulSet
的特点可以从如下几个步骤进行理解:StatefulSet
管理的多个 pod 之间进行部署,更新,删除操作时能够按照固定顺序依次进行 。适用于多服务之间有依赖的情况,如先启动数据库服务再开启查询服务 。
- 由于 pod 之间有依赖关系,因此每个 pod 提供的服务必定不同,所以
StatefulSet
管理的 pod 之间没有负载均衡的能力 。
- 又因为 pod 提供的服务不同,所以每个 pod 都会有自己独立的存储空间,pod 间不共享 。
- 为了保证 pod 部署更新时顺序,必须固定 pod 的名称,因此不像
Deployment
那样生成的 pod 名称后会带一串随机数 。
- 而由于 pod 名称固定,因此跟
StatefulSet
对接的Service
中可以直接以 pod 名称作为访问域名,而不需要提供Cluster IP
,因此跟StatefulSet
对接的Service
被称为Headless Service
。
Deployment
一定是简单而又效果最佳的选择,自动调度,自动负载均衡 。而如果服务的启停必须满足一定顺序,或者每一个 pod 所挂载的数据 volume 需要在销毁后依然存在,那么建议选择 StatefulSet
。本着如无必要,勿增实体的原则,强烈建议所有运行单个服务工作负载采用
Deployment
作为 Controller 。写在结尾一通研究下来,差点把一开始的目标忘了,赶紧将 Docker 重新构建一遍,看看优化成果 。
文章插图
可以看到,对于镜像体积的优化效果还是不错的,达到了 10 倍左右 。当然,如果项目中不需要如此高版本的 node 支持,还能进一步缩小大约一半的镜像体积 。
之后镜像仓库会对存放的镜像文件做一次压缩,以 node14 打包的镜像版本最终被压缩到了 50M 以内 。
文章插图
当然,除了看得到的体积数据之外,更重要的优化其实在于,从面向物理机的服务向容器化云服务在架构设计层面上的转变 。
经验总结扩展阅读
- 记一次 .NET 某企业OA后端服务 卡死分析
- Docker | 使用dockerfile生成镜像,清理docker空间
- 配置DNS域名解析服务
- CRESDA 陆地观测卫星数据服务订单ftp地址错误—已解决不能下载问题
- 服务员上鱼的正确方法
- Docker | 数据持久化与数据共享
- 泰到位服务3个小时干什么了
- Docker | Compose创建mysql容器
- 糟了,线上服务出现OOM了
- 物业服务不到位物业费可以不交吗