K8S实战基础篇:⼀⽂带你深⼊了解K8S实战部署SpringBoot项⽬
K8S实战基础篇:⼀⽂带你深⼊了解K8S实战部署SpringBoot项⽬
1.前⾔
云原⽣可以说是当下互联⽹⾏业最⽕爆的概念和技术,云原⽣从字⾯意思上来看可以分成云和原⽣两个部分。 云是和本地相对的,传统的应⽤必须跑在本地服务器上,现在流⾏的应⽤都跑在云端,云包含了IaaS,、PaaS和SaaS。 原⽣就是⼟⽣⼟长的意思,我们在开始设计应⽤的时候就考虑到应⽤将来是运⾏云环境⾥⾯的,要充分利⽤云资源的优点,⽐如 云服务的弹性和分布式优势。 聊到云原⽣,避不开的就是容器技术,⽽docker作为最流⾏的容器技术,已经经过很多年的线上实战。今天我们不深⼊聊云原⽣,docker这些技术概念,今天我们聊⼀聊时下最⽕的容器编排技术:K8S-实战部署SpringBoot项⽬。
2.简介
2.1.为什么写这篇⽂章
前⾔中提到云原⽣、docker、K8S,我是18年第⼀次docker,也是在18年接触K8S,相对这门技术来说,我接触的时候已经有些晚了,因为在之后的⾯试中,已经感受到这些技术在⼤⼚已经⽤的很成熟了,之前都在⼩公司,并不了解这些技术是什么,⼲什么⽤,加上国内这⽅⾯的资料⼜⽐较少,学起来
是相当吃⼒。⽽到⼤⼚之后,发现这些技术⽆处不在,并且基础设施建设已经很完备,⼀键部署云端的骚操作,让开发只需要关⼼业务⽽⽆需关⼼安装部署等繁琐的⼯作。祸兮福之所倚;福兮祸之所伏,⼤⼚的技术设施完备的同时,另⼀⽅⾯也消弱了你去了解基础设施背后的技术原理能⼒。正是认识到这⼀点,今天才写这篇⽂章,为迷途中的孩⼦到回家的路。废话不多,撸起袖⼦,⼲就完了!
这⾥没有任何马后炮套话,只有粗暴的⼲货。写⼤家看得懂、⽤得着、赚得到的⽂章是唯⼀宗旨!
2.2.需求描述
我有⼀个简单的Springboot项⽬,想部署在K8S集中,能够实现扩缩容,负载均衡,同时我有⼀个互联⽹域名,我想把这个域名绑定在这个服务上,能够在有⽹络的地⽅访问。
2.3.需求分析
这个需求我想在很多刚开始接触docker,k8s等技术的⽼铁⾝上都会遇到过,真正实现起来,并不是那么容易,听我⼀⼀道来:
1. image—Springboot项⽬⼀般是以jar包的形式跑在像centos等服务器上,运⾏nohup java -jar xxx.jar &命令就能启动起来。但是
在k8s中,运⾏起来的的并不是jar,⽽是image,因此我们需要把jar打包成image;
2. ⾃动扩缩—最基础的image有了,接下来就要考虑的是⾃动扩缩:顾名思义,⽐如说就是在服务访问量⼤的时候,我可以添加实例,
来减少每个服务实例的压⼒,在访问量⼩的时候,我可以删除⼀部分实例,来实现资源的⾼效利⽤。
3. 负载均衡—当我们的实例越来越多,我并不希望把所有的请求都落在⼀个实例上,如若不然,我们⾃动扩缩也就没了意义,传统⽅法
我们可以⽤Nginx等实现负载均衡,待会来看看K8S能做些什么
4. 域名绑定—这个就没什么好说的了。
3. 部署实战
3.1 环境准备
⼯欲善其事,必先利其器:
1. Springboot jar包
2. K8S集环境
K8S集环境部署我就不在这⾥展开讲了,我们准备⼀个最简单的Springboot项⽬,⾥⾯只有⼀个接⼝,访问localhost:8088,返回服务器的hostname ,当整个部署⼯作完成之后,我们通过域名访问这个接⼝,返回的应该是不同的container 的hostname ,那我们的任务就完成了。3.2 image 准备我们都知道,所有image的⽣成都离不开Dockerfile 技术,我们有了⼀个jar包,要利⽤Dockerfile技术⽣成⼀个image。废话不多,上代码:Dockerfile⽂件⾥⾯有注释,具体的每⼀⾏代码什么意思我就不展开多讲了,这不是今天的重点,接下来,我们把
docker-demo-0.0.1-SNAPSHOT.jar ,Dockerfile ⽂件放在同⼀个⽬录,上传到K8S的master 节点上,在⽬录内执⾏如下命令⽣成images
我们可以看到⽣成image的过程,通过docker images 查看镜像
⽣成⼀个 docker-demo:latest的image镜像。
注意:我们部署的是集,要想K8S集中都能拉到这个镜像,那我们有以下两种⽅式:
1. ⽅法⼀:我们把这个docker-demo:latest上传到远端仓库,这个仓库可以是我们⾃⼰的,或者是像我⼀样注册⼀个阿⾥云的账号,上
传到阿⾥云⾃⼰的容器镜像服务仓库,如下图: 具体步骤: 1.1 docker登陆阿⾥云容器镜像服务,需要输⼊密码 @GetMapping("/") public String sayHello () throws UnknownHostException { String hostname = "Unknown"; InetAddress address = InetAddress .getLocalHost (); hostname = address .getHostName (); return hostname ; }
1
2
3
4
5
6
7#使⽤jdk8作为基础镜像FROM java:8#指定作者MAINTAINER ***#暴漏容器的8088端⼝#EXPOSE 8088#将复制指定的docker-demo-0.0.1-SNAPSHOT.jar 为容器中的job.jar ,相当于拷贝到容器中取了个别名ADD docker-demo-0.0.1-SNAPSHOT.jar /job.jar #创建⼀个新的容器并在新的容器中运⾏命令
RUN bash -c 'touch /job.jar'#设置时区ENV TZ=PRC RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone #相当于在容器中⽤cmd 命令执⾏jar 包 指定外部配置⽂件ENTRYPOINT ["java","-jar","/job.jar"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$ docker build .
1$ docker login --username =24k 不怕(写⾃⼰的⽤户名) registry -hangzhou .aliyuncs
1
1.2 在阿⾥云上创建命名空间:例:cuixhao-docker-demo
1.3 镜像打标签
1.4 push到阿⾥云
1.5 删除掉docker-demo:latest
2. ⽅法⼆ 把刚才创建image的过程,在集中每⼀台节点上都执⾏⼀遍,保证集中每⼀台都有这个镜像。我采⽤的是⼆者的结合:先
在master上把镜像⽣成,上传到阿⾥云,然后在另外的节点上,通过docker pull registry-hangzhou.aliyuncs/cuixhao-docker-demo/docker-demo:latest 命令,从阿⾥云上拉到本地,然后在通过 docer tag registry-
hangzhou.aliyuncs/cuixhao-docker-demo/docker-demo:latest docker-demo:latest命令打标签,然后删掉拉取到的镜像:docker rmi registry-hangzhou.aliyuncs/cuixhao-docker-demo/docker-demo:latest, 为什么这么做?因为我阿⾥云建的命名空间中的image都是私有,K8S拉取image的时候是需要集中都配置ca证书的,如果设置为公开则不存在这个问题。所以我⽤docker-demo:latest这个镜像,直接⽤本地的,部署的时候不⽤再去阿⾥云拉取。
3.3 部署2个实例
3.3.1 编写yaml ⽂件基础镜像准备好了,那我们就开始部署吧。我们知道,k8s有deployment ,service 等概念,这⾥不详细讲,简单描述⼀下:deployment,管理pod集,service,管理pod中的服务。我们在master 节点编辑⼀个 ingress-docker-docker-deployment.yaml ⽂件
键⼊以下内容$ docker tag docker-demo:latest registry-hangzhou.aliyuncs/cuixhao-docker-demo/docker-demo:latest
1$ docker push registry-hangzhou.aliyuncs/cuixhao-docker-demo/docker-demo:latest
1$ docker rmi docker-demo:latest
1$ vi ingress-docker-docker-deployment.yaml
1
由yaml⽂件内容我们可以读出:我们创建了⼀个 名字我为ingress-docker-demo-deployment的deployment,⾥⾯有2个 docker-demo 的pod (replicas: 2),和⼀个名字为ingress-docker-demo-service的service,管理名字为ingress-docker-demo的pod服务,⽬标端⼝8088,即我们的springboot服务所⽤端⼝,对外提供80端⼝。
3.3.2 启动
在master执⾏如下命令启动deployment 和service:
查看启动结果:apiVersion : apps/v1kind : Deployment metadata : name : ingress -docker -demo -deployment labels : app : ingress -docker -demo spec : replicas : 2 selector : matchLabels : app : ingress -docker -demo template : metadata : labels : app : ingress -docker -demo spec : containers : - name : docker -demo image : docker -demo imagePullPolicy : Never ports : - containerPort : 8088---apiVersion : v1kind : Service metadata : name : ingress -docker -demo -service spec : ports : - port : 80 protocol : TCP targetPort : 8088 selector : app : ingress -docker -demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
curl是什么命令17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34$ kubectl apply -f ingress-docker-docker-deployment.yaml
1$ kubectl get pod -o wide
1
我们可以看到启动结果,两个container 分别在 worker01,worker02这两个节点上,可以看到,K8S集给我们分配了两个
IP:192.168.14.11,192.168.221.73。我们思考以下三个问题:
a. 在集中,我们通过以上访问这两个服务,能访问通吗,是通过8088端⼝还是80端⼝? 我们不妨尝试⼀下,在集中任何⼀个节点执⾏如下命令:我们可以看到,接⼝返回了各⾃container的hostname,说明我们的服务是部署启动成功了,访问80端⼝是不通的,有兴趣的⽼铁可以试⼀下,因为80是我们对外的端⼝,所以⽤container ip是访问不通的。
b. 在集内部访问,我们如何做到负载均衡? 有⽼铁可能会考虑⼀个问题,K8S集中的pod有可能销毁或者重启,每次重启之后的ip不能保证⼀致,那以上访问⽅式肯定是不可采⽤的。想法很对,我们想访问⼀个固定的地址,不管pod如何重启,ip如何变化,我只访问这⼀个ip,这岂不美哉?那我们能不能做到呢?且看如下骚操作:
通过以上命令,我们到了ingress-docker-docker-deployment.yaml 中定义的名字为 ingress-docker-demo-service 的service,它有⼀个CLUSTER-IP ,PORT 为80,那我们根据K8S中的service的作⽤,做⼀个⼤胆的猜测:我们是不是可以固定的通过 10.103.19.71 (省略默认80端⼝)或者 10.103.19.71:80 来永久访问这两个服务呢?
答案是肯定的!,它给我们做了负载均衡!
c. 在集外部我们如何访问这两个服务并且负载均衡? 集内访问服务,负载均衡都已经做好了。有的⽼铁会问:集外服想访问集内的服务,该如何做呢?别急,还没完!
3.3.3 引⼊Ingress $ curl 192.168.1
4.11:8088$ curl 192.168.221.73:8088
1
2$ kubectl get svc
1$ curl 10.103.19.71$ curl 10.103.19.71:80
1
2
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论