一、微服务容器化实践
一)为什么微服务要容器化
参考:https://mp.weixin.qq.com/s/l_OnkhekHNDS30YlPEv5fQ
kubernetes可以非常方便的进行集中管理,高效的对容器服务进行编排、调度、扩容、升级、回滚、监控、集中收集日志等。基本上把传统运维架构需要考虑的问题全部解决了。
1、传统运维架构的缺点
- 将业务部署到物理机或者虚拟机上,管理脚本分散,日志分散难于集中收集管理,监控不统一,CPU、内存、磁盘使用率低,运维效率低,无法集中管理。
- 各种定时任务,管理不变;CI/CD 配置繁琐(jenkins)。
2、使用kubernetes容器化的优势
- 利用kubernetes容器编排工具的namespace对不同环境进行区分:建立dev、test、pre、pro环境,实现环境分离
- 通过容器化集中布署所有业务,实现一键布署所需环境业务。
- 统一集中监控报警所有容器服务异常状态。
- 统一集中收集所有服务日志至ELK集群,利用Kibana面板进行分类,方便开发查日志。
- 基于Kubernetes命令行二次开发,相关开发、测试人员直接操作容器。
- 基于RBAC对不同的环境授于不同的开发、测试访问Kubernetes权限,防止越权。
- 通过Jenkins统一CI/CD编译发布过程。
- 项目容器化后,整体服务器CPU、内存、磁盘、资源利用减少50%,运维效率提高60%,原来需要N个运维做的事,现在一个人即可搞定。
二)网络解决方案选择
三)DevOps、传统业务迁移至kubernetes遇到的问题
1、遇到的问题
使用Kubernetes会建立两套网络,服务之间调用通过service域名,默认网络、域名和现有物理网络是隔离的,开发,测试,运维无法像以前一样使用虚拟机,postman IP+端口调试服务, 网络都不通,这些都是问题。
- Pod网络和物理网络不通,办公电脑、Linux虚拟机上现有的业务和Kubernetes是隔离的。
- SVC网络和物理网络不通,办公电脑、Linux虚拟机上现有的业务和Kubernetes是隔离的。
- SVC域名和物理网络不通,办公电脑、Linux虚拟机上现有的业务和Kubernetes是隔离的。
- 原有Nginx配置太多的location路由规则,有的有几百层,不好迁移到ingress-nginx,ingress只支持简单的规则。
- SVC-NodePort访问,在所有Node上开启端口监听,占用Node节点端口资源,需要记住端口号。
- ingress-nginx http 80端口, 必需通过域名引入,http 80端口必需通过域名引入,原来简单nginx的location可以通过ingress引入。
- ingress-nginx tcp udp端口访问需要配置一个lb,很麻烦,要先规划好lb节点同样也需要访问lb端口。
- 原有业务不能停,继续运行,同时要能兼容Kubernetes环境,和Kubernetes集群内服务互相通讯调用,网络需要通。
2、解决方案
传统虚拟机上布署服务我们只需要一个地址+端口直接访问调试各种服务,Kubernetes是否能做到不用改变用户使用习惯,无感知使用呢?
答案是打通DevOps全链路,像虚拟机一样访部Kubernetes集群服务 , 我们打通Kubernetes网络和物理网络直通,物理网络的DNS域名调用Kubernetes DNS域名服务直接互访,所有服务互通。公司原有业务和现有Kubernetes集群无障碍互访。
1、配置路由转发,部署成路由器模式
2、根据location的复杂度接入方案
- client-------ingress-nginx-----upstream----podip,对于ingress-nginx官方使用的原始方案,先配置ingress规则路由,ingress对接不同的service-dns域名,ingress自动发现后端podip,通过upstream负载不同的后端podip,不同的域名路由到不同的Kubernetes后端podip,用户客户端访问流量会负载到不同的Pod上。
- client------nginx-------upstream------svc-----podip改造现有nginx兼容Kubernetes,对接Kubernetes service服务。对于nginx location规则过多,不能很好的兼容nginx-ingress导致使用Kubernetes非常困难,难以普及,在不变更现有nginx配置的情况下如何对接Kubernetes这是一个问题,经过前面网络打通的步骤我们所有网络的问题都已解决。现在只需改动很小部分即可兼容,由于Kubernetes podip是漂移的,IP总是会变的,nginx只能是对接SVC域名才能持久,但是nginx解析域名有个bug,只解析一次,如果在此期间删除了yaml,nginx会找不到后端svcip,所以这里要设置代理变量set $backend,设置resolver的DNS为代理DNS地址,设置解析域名时间和变量解决该问题。
location /tomcat/ {
resolver 192.168.1.97 valid=3600s;
set $backend "tomcat.dac-prod.svc.cluster.local";
error_log logs/dac_error.log error;
access_log logs/dac_access.log main;
proxy_set_header X-real-ip $remote_addr;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
client_max_body_size 100M;
proxy_pass http://${backend}:9090;
}
四)监控方案
五)kubernetes集群yaml文件编排管理
六)存储方案
读写要求不高的可以配置NFS,要求比较高的用的Ceph,如MySQL、Kafka之类的就需要Ceph支撑,对于需要持久化的DB类型存储的管理用StorageClass存储类对接管理,很方便自动建立存储卷PV-PVC对接,共享卷类型可以直接挂载卷。
七)jenkins CI/CD编译发布阶段
八)kubernetes日志解决方案
1、方案概述
- 应用打到docker stdout前台输出,Docker输出到/var/lib/containers,通过Filebeat、Fluentd、DaemonSet组件收集,这种对于小量日志还可以,大量日志性能很差,写入很慢。
- Pod挂载host-path把日志打到宿主机,宿主机启动Filebeat、Fluentd、DaemonSet收集,无法判断来自哪个容器,哪个Pod和namespace空间。
- Pod的yml中定义两个container,同时启动一个附加的Filebeat,两个container挂载一个共享卷来收集日志。
九)RBAC权限控制