如何在kubernete集群上部署springboot应用

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 如何在kubernete集群上部署springboot应用
  • 1.打包springboot镜像
  • 2.在kubernete上发布镜像
  • 3.测试

微信图片_20221212111108.png在之前的文章中,我讲了使用kubeadm从0到1搭建kubernete集群,今天我们来聊一下如何在这套k8s集群上部署springboot应用。首先说明一下,我们这次集群的网络使用flannel网络,master节点启动命令如下:

kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=v1.17.3 --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address 192.168.59.132

上面的参数 --pod-network-cidr=10.244.0.0/16

就是指明集群使用flannel网络,切记,不然部署springboot后,容器访问外面网络会有问题。

再来看一下这次实验使用的集群环境,如下图,我在个人笔记本上安装了mysql数据库,ip地址是192.168.59.1,同时安装了2个vmware虚拟机,ip地址分别是192.168.59.132和192.168.59.138,kubernete集群就部署在这2个虚机上,192.168.59.132部署着master节点,192.168.59.138部署着worker1节点

微信图片_20221212111143.png这次使用的springboot源码地址:


https://github.com/jinjunzhu/spring-boot-mybatis


1.打包springboot镜像

1.打包springboot镜像


这儿遇到问题可以查看我之前的文章Linux下docker制作springboot应用镜像


编译jar包


mvn clean -Dmaven.test.skip=true install

编译后上传到虚机,编写DockerFile文件

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD spring-boot-mybatis-1.0-SNAPSHOT.jar springboot-mybatis.jar
ENTRYPOINT ["java","-jar","springboot-mybatis.jar"]

执行打包镜像命令,这里我打包的版本号是1.2,每次修改代码后都要升级版本号,不然上传dockerhub不会更新


docker build -t zjj2006forever/springboot-mybatis:1.2 .

之后下面2个命令登录dockerhub并且上传

docker login
docker push zjj2006forever/springboot-mybatis:1.2
[root@master k8s]# docker push zjj2006forever/springboot-mybatis:1.2
The push refers to a repository [docker.io/zjj2006forever/springboot-mybatis]
a3ce9cf52624: Pushed 
ceaf9e1ebef5: Pushed 
9b9b7f3d56a0: Pushed 
f1b5933fe4b5: Pushed 
1.0: digest: sha256:8d37516e910515b0e336ecc29befaa0f9240ebd92a3c22af8b90846476644420 size: 1159

2.在kubernete上发布镜像


编写yaml文件,如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot-mybatis-deployment
spec:
  selector:
    matchLabels:
      app: springboot-mybatis
  replicas: 2
  template:
    metadata:
      labels:
        app: springboot-mybatis
    spec:
      containers:
      - name: spingboot-mybatis
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Never
        image: zjj2006forever/springboot-mybatis:1.2
        ports:
        - containerPort: 8300

上面的yaml文件中,我指定了镜像名称是我刚刚打包的镜像:image: zjj2006forever/springboot-mybatis:1.2,副本数量是2(replicas: 2),

这样部署的时候会生成2个pod,如果提供服务的时候如果一个pod挂了,集群会再创建一个新的出来,一直保持有2个pod。


kubectl apply -f springboot-mybatis.yaml

输出下面提示后我们看一下pod状态

deployment.apps/springboot-mybatis-deployment created

[root@master k8s]# kubectl get pods --all-namespaces
NAMESPACE     NAME                                            READY   STATUS    RESTARTS   AGE
default       springboot-mybatis-deployment-9f5b78b76-2qtfg   1/1     Running   0          9s
default       springboot-mybatis-deployment-9f5b78b76-tzf4x   1/1     Running   0          9s
kube-system   coredns-9d85f5447-7k44c                         1/1     Running   0          30m
kube-system   coredns-9d85f5447-sh24j                         1/1     Running   0          30m
kube-system   etcd-master                                     1/1     Running   0          30m
kube-system   kube-apiserver-master                           1/1     Running   0          30m
kube-system   kube-controller-manager-master                  1/1     Running   0          30m
kube-system   kube-flannel-ds-amd64-rd842                     1/1     Running   0          16m
kube-system   kube-flannel-ds-amd64-tdkwx                     1/1     Running   0          16m
kube-system   kube-proxy-d6qqg                                1/1     Running   0          25m
kube-system   kube-proxy-pm7cc                                1/1     Running   0          30m
kube-system   kube-scheduler-master                           1/1     Running   0          30m

再看一下pod启动日志

[root@master k8s]# kubectl logs -f springboot-mybatis-deployment-9f5b78b76-2qtfg
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)
2020-06-13 08:25:15,002 [main] [INFO] boot.Application - Starting Application v1.0-SNAPSHOT on springboot-mybatis-deployment-9f5b78b76-2qtfg with PID 1 (/springboot-mybatis.jar started by root in /)
2020-06-13 08:25:15,006 [main] [INFO] boot.Application - The following profiles are active: dev
2020-06-13 08:25:20,545 [main] [INFO] org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$c636a19f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-06-13 08:25:21,688 [main] [INFO] org.springframework.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8083 (http)
2020-06-13 08:25:21,723 [main] [INFO] org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8083"]
2020-06-13 08:25:21,839 [main] [INFO] org.apache.catalina.core.StandardService - Starting service [Tomcat]
2020-06-13 08:25:21,840 [main] [INFO] org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.21]
2020-06-13 08:25:22,260 [main] [INFO] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2020-06-13 08:25:22,261 [main] [INFO] org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 6985 ms
2020-06-13 08:25:25,220 [main] [INFO] springfox.documentation.spring.web.PropertySourcedRequestMappingHandlerMapping - Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)]
2020-06-13 08:25:25,631 [main] [INFO] org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'
2020-06-13 08:25:27,595 [main] [INFO] springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper - Context refreshed
2020-06-13 08:25:27,710 [main] [INFO] springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper - Found 1 custom documentation plugin(s)
2020-06-13 08:25:27,857 [main] [INFO] springfox.documentation.spring.web.scanners.ApiListingReferenceScanner - Scanning for api listing references
2020-06-13 08:25:28,755 [main] [INFO] org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8083"]
2020-06-13 08:25:28,956 [main] [INFO] org.springframework.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8083 (http) with context path ''
2020-06-13 08:25:29,253 [main] [INFO] org.springframework.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 18082 (http)
2020-06-13 08:25:29,255 [main] [INFO] org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-127.0.0.1-18082"]
2020-06-13 08:25:29,289 [main] [INFO] org.apache.catalina.core.StandardService - Starting service [Tomcat]
2020-06-13 08:25:29,289 [main] [INFO] org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.21]
2020-06-13 08:25:29,304 [main] [INFO] org.apache.catalina.core.ContainerBase.[Tomcat-1].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2020-06-13 08:25:29,305 [main] [INFO] org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 336 ms
2020-06-13 08:25:29,389 [main] [INFO] org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver - Exposing 16 endpoint(s) beneath base path '/actuator'
2020-06-13 08:25:29,659 [main] [INFO] org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-127.0.0.1-18082"]
2020-06-13 08:25:29,692 [main] [INFO] org.springframework.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 18082 (http) with context path ''
2020-06-13 08:25:29,696 [main] [INFO] boot.Application - Started Application in 17.382 seconds (JVM running for 21.29)

上面的结果可以看到我刚刚发布的2个springboot的pod启动成功了,我们再看下其中一个pod的状态,执行如下命令


kubectl describe pod springboot-mybatis-deployment-9f5b78b76-2qtfg
[root@master k8s]# kubectl describe pod springboot-mybatis-deployment-9f5b78b76-2qtfg
Name:         springboot-mybatis-deployment-9f5b78b76-2qtfg
Namespace:    default
Priority:     0
Node:         worker1/192.168.59.138
Start Time:   Sat, 13 Jun 2020 04:25:04 -0400
Labels:       app=springboot-mybatis
              pod-template-hash=9f5b78b76
Annotations:  <none>
Status:       Running
IP:           10.244.1.2
IPs:
  IP:           10.244.1.2
Controlled By:  ReplicaSet/springboot-mybatis-deployment-9f5b78b76
Containers:
  spingboot-mybatis:
    Container ID:   docker://f3b0b7d1e2b9da0970e23134bbece26e4eb4fb0416e303119a0c4a34b954b666
    Image:          zjj2006forever/springboot-mybatis:1.2
    Image ID:       docker-pullable://zjj2006forever/springboot-mybatis@sha256:0e6f78256ab70ed5244042abc2a5bd5154a193fb9f97f05a3061e8334d387986
    Port:           8300/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 13 Jun 2020 04:25:08 -0400
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-cjp27 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-cjp27:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-cjp27
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m53s  default-scheduler  Successfully assigned default/springboot-mybatis-deployment-9f5b78b76-2qtfg to worker1
  Normal  Pulled     3m50s  kubelet, worker1   Container image "zjj2006forever/springboot-mybatis:1.2" already present on machine
  Normal  Created    3m50s  kubelet, worker1   Created container spingboot-mybatis
  Normal  Started    3m49s  kubelet, worker1   Started container spingboot-mybatis

上面的输出看到这个pod被调度到了worker1节点上,同时从上面的Events可以看到pod的启动过程。


3.测试


先让我们看一下我们刚刚部署的2个pod

root@master k8s]# kubectl get pod -l app -o wide
NAME                                             READY   STATUS    RESTARTS   AGE     IP           NODE      NOMINATED NODE   READINESS GATES
springboot-mybatis-deployment-5b78f66997-2hhdq   1/1     Running   0          7m23s   10.244.1.4   worker1   <none>           <none>
springboot-mybatis-deployment-5b78f66997-k87dx   1/1     Running   0          6m42s   10.244.1.5   worker1   <none>           <none>

上面的输出结果中可以看到,这2个pod的ip地址是10.244.1.4和10.244.1.5,这是由flannel网络插件分配的。


接着我们进入容器内部看一下网络连通性


kubectl exec -it springboot-mybatis-deployment-5b78f66997-2hhdq -- /bin/sh

我们分别ping集群的主192.168.59.132,从节点192.168.59.138和mysql数据库地址192.168.59.1,发现都是正常返回数据包的


我们用curl看一下健康检查的地址,返回如下

[root@worker1 ~]# curl http://10.244.1.4:18082/actuator/health
{"status":"UP","details":{"db":{"status":"UP","details":{"firstDataSource":{"status":"UP","details":{"database":"MySQL","hello":1}},"secondDataSource":{"status":"UP","details":{"database":"MySQL","hello":1}}}},"diskSpace":{"status":"UP","details":{"total":18238930944,"free":10361712640,"threshold":10485760}}}}

我们用浏览器输入地址http://10.244.1.4:8083/employee/jinjunzhu,返回505

这时在容器里面查看日志,输出见下面截图

cd /app/jar/logs/springboot-mybatis-deployment-5b78f66997-2hhdq/applog
tail -f catalina.out

微信图片_20221212111559.png

这个原因很明显,mysql没有对这个ip访问授权,执行一下授权命令:

//对ip地址192.168.59.132授权
grant all privileges on *.* to 'root'@'192.168.59.132' identified by '123456';
//是授权立即生效
flush privileges;

再次访问上面的url,成功,见下图

微信图片_20221212111633.png

pod中的日志如下:

微信图片_20221212111655.png

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3天前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
21天前
|
Kubernetes Cloud Native Java
当 Quarkus 遇上 Spring Boot,谁才是现代云原生应用的终极之选?究竟哪款能助你的应用傲视群雄?
Quarkus 和 Spring Boot 均为构建现代云原生应用的热门框架,旨在简化开发流程并提升性能。Spring Boot 依托庞大的 Spring 生态系统,提供开箱即用的体验,适合快速搭建应用。Quarkus 由红帽发起,专为 GraalVM 和 HotSpot 设计,强调性能优化和资源消耗最小化,是云原生环境的理想选择。
19 3
|
1月前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
59 2
|
2月前
|
Java 开发者 Spring
"揭秘SpringBoot魔法SPI机制:一键解锁服务扩展新姿势,让你的应用灵活飞天!"
【8月更文挑战第11天】SPI(Service Provider Interface)是Java的服务提供发现机制,用于运行时动态查找和加载服务实现。SpringBoot在其基础上进行了封装和优化,通过`spring.factories`文件提供更集中的配置方式,便于框架扩展和组件替换。本文通过定义接口`HelloService`及其实现类`HelloServiceImpl`,并在`spring.factories`中配置,结合`SpringFactoriesLoader`加载服务,展示了SpringBoot SPI机制的工作流程和优势。
47 5
|
2月前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
36 0
|
2月前
|
NoSQL Java Redis
Spring Boot集成Redis全攻略:高效数据存取,打造性能飞跃的Java微服务应用!
【8月更文挑战第3天】Spring Boot是备受欢迎的微服务框架,以其快速开发与轻量特性著称。结合高性能键值数据库Redis,可显著增强应用性能。集成步骤包括:添加`spring-boot-starter-data-redis`依赖,配置Redis服务器参数,注入`RedisTemplate`或`StringRedisTemplate`进行数据操作。这种集成方案适用于缓存、高并发等场景,有效提升数据处理效率。
355 2
|
2月前
|
监控 Java Serverless
美团 Flink 大作业部署问题之想在Serverless平台上实时查看Spring Boot应用的日志要怎么操作
美团 Flink 大作业部署问题之想在Serverless平台上实时查看Spring Boot应用的日志要怎么操作
|
2月前
|
Java Linux C++
【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
|
2月前
|
前端开发 JavaScript Java
Spring Boot应用中的资源分离与高效打包实践
通过实施资源分离和高效打包策略,不仅可以提升Spring Boot应用的开发和部署效率,还能显著提高用户体验。在实际项目中,根据项目的实际情况和团队的技术栈选择合适的工具和方案是关键。希望本文能为读者在Spring Boot项目中实现资源分离和高效打包提供一些有价值的参考。
|
监控 NoSQL Java
SpringBoot 的 44 种应用启动器,你都知道吗?
什么是应用启动器?SpringBoot集成了spring的很多模块,比如tomcat、redis等等。你用SpringBoot搭建项目,只需要在pom.xml引入相关的依赖,和在配置文件中简单的配置就可以使用相应模块了。 非常方便,spring boot集成了哪些启动器呢?
SpringBoot 的 44 种应用启动器,你都知道吗?