这是我们K8s快速入门与实践的最后一篇啦,上一个实践篇里我们讲了怎么从写第一行代码开始到把 Go 服务部署到 K8s 上都有哪些步骤,每一步该怎么做。
今天这篇我们再更新一个怎么把 SpringBoot 应用部署到 K8s 上,本来我是想偷偷懒、照猫画虎把上节课的改改镜像名不就行了,没想到,居然翻车咧,真的是想偷点懒都不行啊。具体怎么翻车,咱们先往后看,在总结里再说说,我对 Go 相比于 Java 在云原生里的优势。
好了,咱们还是先假装自己都是是小白哈,让我带大家再次从零开始把一个 SpringBoot 应用部署到 K8s 上运行。
怎么把一个 SpringBoot 开发的 Web 应用部署到 K8s 集群上运行,有哪几个步骤要完成的呢,这里我们先归纳一下,后面依次对每一步进行演示。
这里会把我们上面理论部分的知识点再串一遍,主要有这么几个步骤:
好了,这六步大家一定要记住,下面我们逐一展开,详细说说。
这一步咱们为了演示,就简单来搞一个 HelloWorld 级别的代码就行了,没必要搞太复杂,再复杂的项目后面几步的操作也是一样。
首先,咱们建一个 Maven 管理的项目,POM 文件里引入这几个依赖
POM 文件里的依赖
POM里的依赖很简单,首先是 Spring Boot 程序都要先引入的spring-boot-starter-parent
,其次我们演示的是 Web 应用,所以在项目依赖里再引入 Spring MVC 的starter 即可。
至于应用的代码,也非常简单
应用代码
可以看到,仅就 HelloWorld 级别的代码来说,并没有比咱们演示的 Go 程序代码多多少,主要原因是很多工作 SpringBoot 都已经帮我们做好了。
代码写好了,接下来我们把这个 SpringBoot 应用打成 Docker 镜像。
首先咱们准备一下打包镜像的 Dockerfile
FROM openjdk:8-jre
ADD target/*.jar /application.jar
ENTRYPOINT ["java", "-jar","/application.jar"]
把这个放在项目的根目录里,具体 Dockerfile 里的命令咱们就不讲了,就三个命令,可以在网管叨bi叨公众号里回复docker,拿到一个 docker 命令的手册,里面常用 Docker 命令的解释都有。
下面把应用打包成镜像:
docker build -t registry.cn-hangzhou.aliyuncs.com/docker-study-lab/simple-app-java:v0.1
把镜像上传到远程仓库:
docker push registry.cn-hangzhou.aliyuncs.com/docker-study-lab/simple-app-java:v0.1
这次,咱们还是把镜像传到,某位老好人创建的镜像仓库里,大家练习的时候也可以往里传,不过首先要在阿里云申请个免费的镜像云账号,然后用docker login 命令配置一下你的客户端就行啦,阿里云的页面上都有指示,实在不行了也可以在公众号里问我。
还记得我在之前的文章 -- K8s 面向对象里说过
Deployment 是一个复合型的控制器,它包装了一个叫做 ReplicaSet -- 副本集的控制器。ReplicaSet 管理正在运行的Pod数量,Deployment 在其之上实现 Pod 滚动更新,对Pod的运行状况进行健康检查以及回滚更新的能力
所以,这里我们直接把步骤2、3合起来一起说。其实也没啥好说的,毕竟 Go 实践那篇文章里我们已经讲过一次了,直接上这次用的 YAML 配置
Deployment YAML
诶,我就是在这翻车的,一开始我完全拷贝的 Go 实践篇里的 Deployment 配置,部署后,服务不停的重启,排查了一下,是在不停的OOM。
翻车截图
因为咱们只给 Go 的那个应用容器分配了 50M 内存,这次用 SpringBoot 虽然也只是个 HelloWorld 程序,但是却跑不起来,一请求容器就挂。这里就凸显出 Go 在云原生下的第一个好处啦:占内存小。
排查 K8s 问题的方法,可参考之前的文章:想在研发群里装?先学会这几个排查K8s问题的办法
上面我直接把容器可用的内存调成了 500M,不是说 Java 应用占的内存是Go应用的 10倍,是我懒得一点点去试,直接设置成了 500M,反正 100 M,试过是不行的,哭!
创建好上面这几个对象后,我们的应用只能在 K8s 集群的内部使用,想能从外部访问就得把应用暴露出来,这个时候就需要 Service 这个对象了。Service 对象具体的概念解释,咱们还是看上一篇文章,这里不再赘述了。
下面是一个默认的 Cluster IP 型的 Service,为啥只在集群内暴露呢?因为下面我们还会给 Service 加一层 Ingress,所以就不必再用 NodePort 型的 Service 单独在节点上开端口再向外暴露服务啦。
Service YAML
使用 Ingress 前咱们应该干什么呢?对,需要先安装 Ingress Controller ,这里我们使用开源的 Ingress-Nginx ,它本质上就是个 Nginx,也好理解,Ingress 是代理 Service 对象的,要想代理先得有个基础设施的支持,只不过 K8s 里任何东西都是面向对象方式管理的,所以就有了 Ingress Controller,它支持不同类型的 Ingress Controller,咱们用的这个是免费的。
安装参考下面这个链接,非常简单,上次发文章后,不安装就跑过来问我为啥运行不了的,自己去面壁会儿。
https://kubernetes.github.io/ingress-nginx/deploy/
接下来就是声明代理我们的 Web 应用的 Ingress 对象
Ingress YAML
通过 kubctl apply -f 命令把它提交给 K8s 集群,创建 Ingress 对象。
Ingress 对象创建好后,我们就能通过 java-app.example.com 访问咱们的服务啦,当然前提是在电脑上配置一下咱们的 hosts 文件,添加一下这个域名到127.0.0.1 的绑定。
看一下咱们的访问效果
K8s 运行应用的效果
最近这两天的实践篇,我一直在给你们讲 K8s 的各种资源对象怎么声明、怎么配合着使用,操作时执行的命令就提了一嘴,没有展开说。主要的原因还是它的命令非常简单,自始至终我就用了一个 kubectl apply 命令,下面我把 K8s 常用的命令组合放这里,供大家操作的时候参考。
讲完这篇 SpringBoot 应用上 K8s 的过程,咱们快速入门和实践这个短系列就算完结了。
这里总结了一下 K8s 常用的入门知识以及相关的实践操作,只能算是一个非常初级的入门,还有其他很多非常高级的特性能让我们控制 K8s 对应用的各种调度动作。
本文使用的源码、YAML配置、和操作步骤都可以给公众号 「网管叨bi叨」发私信【k8s】获得我整理好的在线资料,具体步骤都在这里:
给公众号-网管叨叨,发送 k8s 领取
最后再说说我这次体验到的 Go 在云原生里边的优势,第一个就是上文咱们翻车的地方提到的,Go 开发的应用占内存比 Java 的应用更小,说的是正经应用哈,如果代码写的不好 Go 的一样 OOM。
再一个就是 Java 开发的程序在镜像尺寸上也比 Go 的大很多。虽然只是个 Hello World 级别的程序但也占到了 280M 的空间,主要原因是 Java 的程序编译好了也必须运行在JVM上,光这一项这部分就占了很多空间。
而 Go 因为编译后的二进制能直接运行在系统上,所以一般的应用镜像只要个十几M,像我们上篇里演示的程序,用了多阶段打包构建出来的镜像只要 2M。
这两点优势加起来 Go 对设施的成本确实更亲民一些,尤其对动辄上百个服务的公司来说,能节省不少成本。不过咱也不能太迷信这个,毕竟对公司来说,成本更大的可能是人员成本和风险成本这些。在这里我对这两个语言就不点评了,理性看待吧,都有优缺点。