找回密码
 立即注册
首页 业界区 业界 【Kubernetes】入门-部署Spring应用

【Kubernetes】入门-部署Spring应用

卢莹洁 4 天前
Kubernetes

基本概念

Pod

是什么: Kubernetes 中最小的、最简单的部署和管理单元。
类比: 一台“逻辑主机”或一个“虚拟机实例”。
关键点

  • 一个 Pod 可以包含一个或多个紧密相关的容器(例如,一个应用容器和一个日志收集 sidecar 容器)。
  • 这些容器共享网络命名空间(拥有相同的 IP 地址和端口空间)、存储卷和其他资源。
  • Pod 是短暂的,会被频繁地创建和销毁
Deployment

是什么: 用于部署和管理 Pod 副本集的声明式定义。
解决的问题: 如何确保指定数量的、完全相同的 Pod 副本始终在运行?如何无缝更新应用(滚动更新)?如何在更新出问题时快速回滚?
关键点

  • 你定义一个“期望状态”(例如,需要运行 3 个 Nginx Pod),Deployment 控制器会确保实际状态始终匹配这个期望状态。
  • 它是实现无状态应用部署的首选控制器。
Service

是什么: 一个稳定的网络端点,用于访问一组 Pod。
解决的问题: Pod 是短暂的,IP 地址会变。客户端如何稳定地找到并访问这些动态变化的 Pod?
关键点

  • Service 提供一个固定的 虚拟 IP (ClusterIP) 和 DNS 名称。
  • 通过 标签选择器 (Label Selector) 来匹配一组 Pod,并将流量负载均衡到这些 Pod 上。
  • 常见的类型:

    • ClusterIP: 默认类型,仅在集群内部可访问。
    • NodePort: 在每个节点上开放一个静态端口,从而可以从集群外部访问。
    • LoadBalancer: 使用云提供商的负载均衡器,向外部公开服务

Volume (存储卷)

是什么: 允许 Pod 中的容器持久化存储数据。
解决的问题: 容器内部的文件系统是临时的,容器重启后数据会丢失。如何持久化保存数据(如数据库文件、日志)?
关键点

  • 存储卷的生命周期独立于 Pod。即使 Pod 被销毁,存储卷中的数据依然存在。
  • 支持多种后端存储类型:本地存储、云存储(如 AWS EBS、GCE PD)、NFS、分布式存储(如 Ceph)等。
Namespace (命名空间)
是什么: 在物理集群内部创建的虚拟集群,用于实现资源隔离和分组。
解决的问题: 在有多个团队或项目的大型集群中,如何避免资源(如 Pod、Service 名称)冲突?如何实现资源配额管理?
关键点

  • 默认有 default, kube-system (系统组件), kube-public 等命名空间。
  • 可以为每个命名空间设置资源配额,限制其能使用的 CPU、内存等资源总量。
ConfigMap & Secret


  • ConfigMap: 用于将非机密的配置数据(如配置文件、环境变量、命令行参数)与容器镜像解耦。让你可以不重写镜像就能改变应用配置。
  • Secret: 与 ConfigMap 类似,但专门用于存储敏感信息,如密码、OAuth 令牌、SSH 密钥。数据会以 Base64 编码(非加密,需额外措施保障安全)存储。
使用K8S部署Spring Boot应用

前置条件,docker和kubernetes已安装配置

参考:macOS上优雅运行Docker容器
准备一个Spring Boot应用

SpringK8sDemoApplication
  1. @SpringBootApplication
  2. @RestController
  3. public class SpringK8sDemoApplication {
  4.         private static Date firstTime;
  5.         private static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  6.         public static void main(String[] args) {
  7.                 SpringApplication.run(SpringK8sDemoApplication.class, args);
  8.         }
  9.         @GetMapping("/")
  10.         public String hello() {
  11.                 if (firstTime == null) {
  12.                         firstTime = new Date();
  13.                 }
  14.                 // 容器里看日志是否有负载均衡
  15.                 System.out.println("request in " + formatter.format(new Date()));
  16.                 return "Hello from Spring Boot on Kubernetes! first time: " + formatter.format(firstTime);
  17.         }
  18.         @GetMapping("/health")
  19.         public String health() {
  20.                 return "OK";
  21.         }
  22. }
复制代码
pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.         <modelVersion>4.0.0</modelVersion>
  5.         <parent>
  6.                 <groupId>org.springframework.boot</groupId>
  7.                 spring-boot-starter-parent</artifactId>
  8.                 <version>3.5.7</version>
  9.                 <relativePath />
  10.         </parent>
  11.         <groupId>com.example</groupId>
  12.         spring-k8s-demo</artifactId>
  13.         <version>0.0.1-SNAPSHOT</version>
  14.         <name>spring-k8s-demo</name>
  15.         <description>Demo project for Spring Boot</description>
  16.         <properties>
  17.                 <java.version>21</java.version>
  18.         </properties>
  19.         <dependencies>
  20.                 <dependency>
  21.                         <groupId>org.springframework.boot</groupId>
  22.                         spring-boot-starter</artifactId>
  23.                 </dependency>
  24.                 <dependency>
  25.                         <groupId>org.springframework.boot</groupId>
  26.                         spring-boot-starter-web</artifactId>
  27.                 </dependency>
  28.                 <dependency>
  29.                         <groupId>org.springframework.boot</groupId>
  30.                         spring-boot-starter-test</artifactId>
  31.                         <scope>test</scope>
  32.                 </dependency>
  33.         </dependencies>
  34.         <build>
  35.                 <plugins>
  36.                         <plugin>
  37.                                 <groupId>org.springframework.boot</groupId>
  38.                                 spring-boot-maven-plugin</artifactId>
  39.                         </plugin>
  40.                 </plugins>
  41.         </build>
  42. </project>
复制代码
构建 Docker 镜像

Dockerfile
  1. FROM eclipse-temurin:21-jre-alpine AS runtime
  2. # 创建应用目录
  3. WORKDIR /app
  4. # 复制jar文件
  5. COPY target/spring-k8s-demo-0.0.1-SNAPSHOT.jar app.jar
  6. # 暴露端口
  7. EXPOSE 8080
  8. # 启动应用
  9. ENTRYPOINT ["java", "-jar", "app.jar"]
复制代码
build.sh
  1. # 切换指定JDK版本(可选)
  2. export JAVA_HOME=`/usr/libexec/java_home -v 21`
  3. # 可替换mvn
  4. mvnd clean package -DskipTests
  5. # 构建镜像
  6. docker build -t spring-k8s-demo:latest .
复制代码
编写 k8s Deployment 文件

k8s-deployment.yaml
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: spring-app
  5. spec:
  6.   replicas: 2  # 运行 2 个 Pod 副本
  7.   selector:
  8.     matchLabels:
  9.       app: spring-app
  10.   template:
  11.     metadata:
  12.       labels:
  13.         app: spring-app
  14.     spec:
  15.       containers:
  16.       - name: spring-app
  17.         image: spring-k8s-demo:latest
  18.         ports:
  19.         - containerPort: 8080   # 容器内暴露的端口
  20.         livenessProbe:          # 存活探针
  21.           httpGet:
  22.             path: /health
  23.             port: 8080
  24.           initialDelaySeconds: 300
  25.           periodSeconds: 10
  26.         readinessProbe:         # 就绪探针
  27.           httpGet:
  28.             path: /health
  29.             port: 8080
  30.           initialDelaySeconds: 300
  31.           periodSeconds: 10
  32.         resources:              # 分配资源
  33.           requests:
  34.             memory: "256Mi"
  35.             cpu: "250m"
  36.           limits:
  37.             memory: "512Mi"
  38.             cpu: "500m"
复制代码
k8s-services.yaml
  1. # service.yaml
  2. apiVersion: v1
  3. kind: Service
  4. metadata:
  5.   name: sprint-service
  6.   labels:
  7.     app: sprint-service
  8. spec:
  9.   type: NodePort
  10.   selector:
  11.     app: spring-app
  12.   ports:
  13.     - protocol: TCP
  14.       port: 80
  15.       targetPort: 8080
  16.       nodePort: 30080
复制代码
配置文件解释

  • Deployment:

    • replicas: 2:确保任何时候都有 2 个 Pod 在运行。
    • selector & labels:Deployment 通过 app: spring-app 这个标签来管理它创建的 Pod。
    • image:指定从哪个镜像运行容器。
    • resources:为容器设置 CPU 和内存的资源请求与限制,这是生产环境的最佳实践。

  • Service:

    • type: NodePort: 在每个节点上开放一个静态端口,从而可以从集群外部访问
    • selector: app: spring-app:Service 通过这个标签找到要代理的 Pod。
    • ports:将 Service 的 80 端口流量转发到 Pod 的 8080 端口。

部署到集群

应用配置
  1. kubectl apply -f k8s-deployment.yaml
  2. kubectl apply -f k8s-services.yaml
复制代码
测试


  • 查看pod状态
  1. kubectl get pods
复制代码
Pod 状态变为 Running

  • 查看Deployment状态
  1. kubectl get deployment
复制代码

  • 查看 Service
  1. kubectl get service
复制代码

  • curl
  1. curl http://192.168.64.3:30080/
复制代码
1.png

根据时间,可以看到每次轮询到不同pod,也就是不同容器
注意:因为我使用是colima所以需要使用colima list命令查出来IP是192.168.64.3
k8s 常用命令
  1. # 查看所有节点
  2. kubectl get nodes
  3. # 查看节点详情
  4. kubectl describe node <node-name>
  5. # 查看Pod
  6. kubectl get pods
  7. # 查看Pod详情
  8. kubectl describe pod <pod-name>
  9. # 查看Pod日志
  10. kubectl logs <pod-name> -n <namespace>
  11. # 查看单个 Pod 的日志
  12. kubectl logs <pod-name>
  13. # 查看部署
  14. kubectl get deployments
  15. # 查看部署详情
  16. kubectl describe deployment <deployment-name>
  17. # 查看由 Deployment 创建的所有 Pod 的日志
  18. kubectl logs -l app=spring-app
  19. # 转发端口(用于本地测试)
  20. kubectl port-forward svc/sprint-service 8080:80
  21. # 水平扩缩容(将副本数从 2 增加到 3)
  22. kubectl scale deployment spring-app --replicas=3
  23. # 查看部署历史
  24. kubectl rollout history deployment/<deployment-name>
  25. # 滚动更新(例如,更新到新版本的镜像)
  26. kubectl set image deployment/spring-app java-app=spring-k8s-demo:2.0.0
  27. # 回滚到上一个版本
  28. kubectl rollout undo deployment/<deployment-name>
  29. # 删除部署
  30. kubectl delete -f k8s-deployment.yaml
  31. kubectl delete -f k8s-services.yaml
复制代码
引用

https://github.com/WilsonPan/java-developer
例子: https://github.com/WilsonPan/java-developer/tree/main/samples/spring-demo

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册