小团队 CI/CD 实践:无需运维,Java Web应用的自动化部署

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文介绍如何使用GitHub Actions和阿里云Kubernetes(ACK)实现Java Web应用的自动化部署。通过CI/CD流程,开发人员无需手动处理复杂的运维任务,从而提高效率并减少错误。文中详细讲解了Docker与Kubernetes的概念,并演示了从创建Kubernetes集群、配置容器镜像服务到设置GitHub仓库Secrets及编写GitHub Actions工作流的具体步骤。最终实现了代码提交后自动构建、推送镜像并部署到Kubernetes集群的功能。整个过程不仅简化了部署流程,还确保了应用在不同环境中的稳定运行。

引子

在许多小团队中,开发人员不仅要编写应用代码,还需要负责将应用部署到生产环境。对于没有专职运维人员的团队,每次手动部署都不仅费时费力,还容易出错。因此,采用CI/CD(持续集成/持续部署) 来实现自动化部署,成为了解决这一问题的最佳方式。

本文将演示如何使用GitHub Actions阿里云 Kubernetes(ACK) 来实现Java Web 应用的自动化部署。我们的目标是,开发人员无需将精力耗费在运维任务上,而是通过现成的云服务来简化部署过程。

需要说明的是,本文的核心目标是降低部署的运维成本,因此选择了多个云服务来演示整个流程,但在实际应用中,大家可以根据团队的情况进行调整。例如,如果团队有足够的精力,也可以自行部署CI/CD工具,如JenkinsGitLab CI,而Kubernetes 提供商的选择也非常多,甚至可以自行搭建Kubernetes集群。

本文的重点不在于具体工具的选择,而在于对整个自动化部署流程的掌握。一旦理解了基本流程,切换到其他工具或平台时,上手速度会非常快,因为它们的流程都大差不差的。

认识Docker与Kubernetes

在正式开始操作前,如果是第一次接触的同学,可以先阅读下第二章节,来对Docker与Kubernetes建立起一个认识:

Docker

如果把一个应用程序比作一件商品,那么Docker就像是为这件商品打包的“集装箱”。在没有Docker的年代,开发人员在本地运行的应用,往往在部署到服务器时会遇到各种问题,比如依赖库不一致、操作系统版本不同等。就像你将一件精心制作的商品从一个国家运到另一个国家,可能会因为不同的运输环境、气候条件等因素,导致商品在到达目的地时无法正常使用。

Docker就像是一个标准化的“集装箱”,它能把你的应用程序和它需要的所有依赖打包在一起,形成一个独立的“镜像”image。无论你是在开发环境、测试环境,还是生产环境,Docker镜像都能确保应用在每个环境中以相同的方式运行,就像集装箱能在全球范围内标准化运输一样。它解决了“我本地运行没问题,为什么服务器上就不行?” 这个历史难题。

用个例子说明一下: 你要制作一份美味的蛋糕,并寄给朋友。没有Docker的话,你只能把蛋糕装进一个普通的纸箱,然后寄出去。结果朋友收到后发现,蛋糕因为运输颠簸、天气变化,变得面目全非。而使用Docker,就相当于你把蛋糕放进一个坚固的保温集装箱,确保在任何运输条件下,蛋糕能保持新鲜、完整。无论你把这个蛋糕寄到哪里,朋友收到的蛋糕都和你制作时一模一样。

Kubernetes

上文中提到Docker是打包应用的“集装箱”,那么Kubernetes就是管理这些集装箱的“码头系统”。在实际生产环境中,应用程序往往需要部署到多个服务器上(或者称为节点),还需要根据流量的变化,灵活调整应用实例的数量。手动管理这些工作量大且容易出错,就像手工管理码头上成百上千个集装箱一样,效率低下。

Kubernetes 的出现,让这一切变得自动化和可控。它提供了一个强大的管理平台,用来自动调度和管理运行中的 Docker容器。Kubernetes不仅能够帮你决定应用(容器)应该在哪台服务器上运行,还能根据流量自动扩容或者缩容,确保应用始终保持高可用性。

再举个例子: 假设你经营一个全球连锁的快递公司,每天都有成千上万的集装箱到达各个港口。如果没有一个智能的管理系统,你需要手动决定每个集装箱应该放在哪个仓库、什么时候发货、运输中如何调度,甚至在货物需求增加时,你还得临时增加人手来处理这些集装箱。

Kubernetes就是这个智能的“码头管理系统”。它会根据你的需求,自动分配集装箱到各个港口,确保货物按时到达。如果某个港口的集装箱积压了,它可以自动将多余的货物调度到别的港口,保证高效运转。当货物需求增加时,它甚至可以“雇佣”更多的卡车来处理这些集装箱——这就是Kubernetes的自动扩展功能。

整体的架构与关系可以用这张图表示:
1.png
Docker:将应用打包成标准化的容器,确保在不同环境下都能一致运行。
Kubernetes:管理和调度这些容器,自动分配资源、扩展应用,并保证高可用性。

实操

在上文中已经明确了我们本次所使用的服务,这里再详细说明下每个服务所起的作用:

  • GitHub Actions:GitHub 的 CI/CD 工具,帮助我们实现代码提交后的自动化流程。
  • 阿里云 Kubernetes(ACK) :阿里云的托管 Kubernetes 服务。
  • 阿里云容器镜像服务(ACR) :Docker 镜像仓库,用于存储和管理 Docker 镜像。
  • Spring Boot:作为示例的 Java Web 应用框架。

同时,再对我们整个操作流程画图说明一下,如下:
02.png

1.开发Web应用

本篇的重点不在于应用,所以我们用Spring Boot简单起个应用,写个hello World的接口可以访问到就行,主要代码如下:

@RestController
public class HelloController {
   

    @GetMapping("/hello")
    public String hello() {
   
        return "Hello World!";
    }
}
AI 代码解读

编写完成后,先在本地启动测试下,确保应用可以正常使用,如下:
03.png
然后把它推送到Github仓库即可。

2.创建Kubernetes集群

直接登录阿里云控制台,搜索ACK即可找到容器服务 Kubernetes,如下:
4.png
我们这里只是演示,越简单越好,就买ACK托管版就可以了,配置就选最便宜的,然后一路下一步就行,如下:
5.png
等待几分钟,集群创建成功,如下:
6.png
集群创建完成后,进入集群的详情页面,点击连接信息,下载kubeconfig文件,这个文件包含你的集群配置信息,后续会用到它来访问集群。这里提一下,我们要的是公网访问的配置文件,如下:
7.png

3.创建阿里云容器镜像服务(ACR)

我们需要一个存储Docker镜像的地方,阿里云容器镜像服务(ACR)就是用来存储和管理 Docker 镜像的。在控制台搜索容器镜像服务,如下:
8.png
这里创建个人实例即可,如下:
9.png
点击 创建命名空间,为镜像仓库创建一个命名空间,如下:
10.png
创建完命名空间后,再点击 创建镜像仓库,如下:
11.png
创建完成后,可以得到仓库的连接相关信息,如下:
12.png
这些凭证将用于GitHub Actions登录ACR,推送Docker 镜像

4.配置GitHub仓库Secrets

接下来,我们需要将阿里云的相关凭证添加到GitHub仓库的Secrets中,这样GitHub Actions才能安全地访问阿里云的资源。

首先打开你的 GitHub 仓库,点击 Settings ,然后选择左侧的 Secrets and variables下的Actions,再点击 New repository secret ,如下:
13.png
然后添加相关的Secrets,这里需要注意一下,因为后续的配置需要用到它们,所以这里的名称需要和后续的配置文件中保持一致,否则读取不到打包会报错的,如下:

  • ALIYUN_REGISTRY_USERNAME:阿里云容器镜像服务(ACR)的用户名。
  • ALIYUN_REGISTRY_PASSWORD:阿里云容器镜像服务(ACR)的密码。
  • ALIYUN_REGISTRY_URL:ACR 镜像仓库的登录地址。
  • ALIYUN_NAMESPACE:ACR 命名空间。
  • ALIYUN_REPO_NAME:ACR 镜像仓库名称`。
  • ALIYUN_KUBECONFIG:将之前下载的 kubeconfig 文件内容复制粘贴到这里,用于后续 GitHub Actions 通过 kubectl 访问 Kubernetes 集群。

5.创建GitHub Actions工作流

接下来在项目的根目录中,创建一个文件 .github/workflows/ci-cd.yml(Ps:文件名随意,目录必须一致),并添加以下内容:

name: CI/CD for Spring Boot Hello World

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up JDK 17
        uses: actions/setup-java@v2
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Build with Maven
        run: mvn clean package

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Log in to ACR
        run: |
          docker login \
            --username=${
   { secrets.ALIYUN_REGISTRY_USERNAME }} \
            ${
   { secrets.ALIYUN_REGISTRY_URL }} \
            --password=${
   { secrets.ALIYUN_REGISTRY_PASSWORD }}

      - name: Build and Push Docker image
        run: |
          # 构建本地镜像
          docker build -t springboot-hello-world:latest .

          # 打标签
          docker tag springboot-hello-world:latest ${
   {
    secrets.ALIYUN_REGISTRY_URL }}/${
   {
    secrets.ALIYUN_NAMESPACE }}/${
   {
    secrets.ALIYUN_REPO_NAME }}:latest

          # 推送镜像
          docker push ${
   {
    secrets.ALIYUN_REGISTRY_URL }}/${
   {
    secrets.ALIYUN_NAMESPACE }}/${
   {
    secrets.ALIYUN_REPO_NAME }}:latest

  deploy:
    needs: build
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'latest'

      - name: Configure kubectl
        run: |
          mkdir -p $HOME/.kube
          echo "${
   { secrets.ALIYUN_KUBECONFIG }}" > $HOME/.kube/config
          chmod 600 $HOME/.kube/config

      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/springboot-hello-world springboot-hello-world=${
   { secrets.ALIYUN_REGISTRY_URL }}/${
   { secrets.ALIYUN_NAMESPACE }}/${
   { secrets.ALIYUN_REPO_NAME }}:latest
AI 代码解读

项目打包需要我们编写Dockerfile,也很简单,根据实际情况简单配下就行,示例如下:

FROM eclipse-temurin:17-jre-alpine

WORKDIR /app

COPY target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]
AI 代码解读

现在我们往Master分支上提交代码就会自动触发action来帮助我们打包镜像,如下:
14.png
在实际业务场景中,我们会存在测试、生产等多个环境的分支,都需要进行自动化构建,也是很简单,在上面的配置里加上其他分支即可。由于我们的应用非常简单,所以整个打包的时间也相对较短,打包成功后,如下:
15.png

6.创建Kubernetes集群配置:

最后还需要我们在项目里添加一下Kubernetes集群的相关配置,如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot-hello-world
spec:
  replicas: 1
  selector:
    matchLabels:
      app: springboot-hello-world
  template:
    metadata:
      labels:
        app: springboot-hello-world
    spec:
      containers:
      - name: springboot-hello-world
        image: registry.cn-hangzhou.aliyuncs.com/my-app/springboot-hello-world:latest
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: springboot-hello-world-service
spec:
  selector:
    app: springboot-hello-world
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer
AI 代码解读

提交到仓库后,可以在Kubernetes集群的控制台里看到我们的服务实例了,如下:
16.png

7.访问以及版本管理

部署成功后,访问下公网ip,也可以正常访问我们的应用,如下:
17.png
按照我们现有的配置,我们后续每次向Master分支提交代码都会自动打包以及更新我们的服务,比如我们在接口的响应上加上123,代码如下:

@RestController
public class HelloController {
   

  @GetMapping("/hello")
  public String hello() {
   
    return "Hello World! 123";
  }
}
AI 代码解读

等待打包成功后,再次访问,会看到已经更新了,如下:
18.png
如果我们发布的新版本应用有BUG,需要回滚,操作也是非常简单,进入到集群详情-历史版本里就可以看到我们的版本记录,如下:
19.png
想要回滚到哪个版本直接点击回滚到该版本即可。

小结

相信大家看到这里对于整个流程也有了清晰的认识,可以根据自己的实际选择适合的来替换某个节点的服务或工具。另外,可能有人会说把代码发到Github上等于把业务泄露了。我这里说下我的看法:本身针对小团队肯定越快越好,自然不用搭建的是最快的。另外,把仓库设为私有仓库,开发人员的权限简单配置下就足够用了。等你体量做大了,自然也不需要用它了。

相关实践学习
通过容器镜像仓库与容器服务快速部署spring-hello应用
本教程主要讲述如何将本地Java代码程序上传并在云端以容器化的构建、传输和运行。
Kubernetes极速入门
Kubernetes(K8S)是Google在2014年发布的一个开源项目,用于自动化容器化应用程序的部署、扩展和管理。Kubernetes通常结合docker容器工作,并且整合多个运行着docker容器的主机集群。 本课程从Kubernetes的简介、功能、架构,集群的概念、工具及部署等各个方面进行了详细的讲解及展示,通过对本课程的学习,可以对Kubernetes有一个较为全面的认识,并初步掌握Kubernetes相关的安装部署及使用技巧。本课程由黑马程序员提供。   相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
打赏
0
9
9
0
163
分享
相关文章
Java 大数据在智能教育在线实验室设备管理与实验资源优化配置中的应用实践
本文探讨Java大数据技术在智能教育在线实验室设备管理与资源优化中的应用。通过统一接入异构设备、构建四层实时处理管道及安全防护双体系,显著提升设备利用率与实验效率。某“双一流”高校实践显示,设备利用率从41%升至89%,等待时间缩短78%。该方案降低管理成本,为教育数字化转型提供技术支持。
72 0
|
10天前
|
Java 17 及以上版本核心特性在现代开发实践中的深度应用与高效实践方法 Java 开发实践
本项目以“学生成绩管理系统”为例,深入实践Java 17+核心特性与现代开发技术。采用Spring Boot 3.1、WebFlux、R2DBC等构建响应式应用,结合Record类、模式匹配、Stream优化等新特性提升代码质量。涵盖容器化部署(Docker)、自动化测试、性能优化及安全加固,全面展示Java最新技术在实际项目中的应用,助力开发者掌握现代化Java开发方法。
47 1
Java 大视界 —— Java 大数据在智慧交通停车场智能管理与车位预测中的应用实践(174)
本文围绕 Java 大数据在智慧交通停车场智能管理与车位预测中的应用展开,深入剖析行业痛点,系统阐述大数据技术的应用架构,结合大型体育中心停车场案例,展示系统实施过程与显著成效,提供极具实操价值的技术方案。
开发 JavaFX 与 Java Swing 桌面应用的实用技巧与实践方案
本文介绍了Java桌面应用开发的技术选型与JavaFX实战方案。首先对比了JavaFX和Swing的特点,推荐JavaFX更适合现代UI需求。重点讲解了JavaFX 19+的技术升级,包括模块化开发(module-info.java配置)和响应式UI设计(CSS样式管理)。在数据访问层展示了JDBC 4.3的集成和异步加载实现。高级UI组件部分演示了自定义表格和图表可视化的开发方法。最后介绍了MVVM架构的实现,包括视图模型的数据绑定和FXML控制器的集成,为开发者提供了完整的JavaFX桌面应用开发解决方案。
100 0
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
69 1
|
1月前
|
Java 抽象类与接口在 Java17 + 开发中的现代应用实践解析
《Java抽象类与接口核心技术解析》 摘要:本文全面剖析Java抽象类与接口的核心概念与技术差异。抽象类通过模板设计实现代码复用,支持具体方法与状态管理;接口则定义行为规范,实现多态支持。文章详细对比了两者在实例化、方法实现、继承机制等方面的区别,并提供了模板方法模式(抽象类)和策略模式(接口)的典型应用示例。特别指出Java8+新特性为接口带来的灵活性提升,包括默认方法和静态方法。最后给出最佳实践建议:优先使用接口定义行为规范,通过抽象类实现代码复用,合理组合两者构建灵活架构。
45 2
Java 大视界 -- Java 大数据机器学习模型在金融衍生品定价中的创新方法与实践(166)
本文围绕 Java 大数据机器学习模型在金融衍生品定价中的应用展开,分析定价现状与挑战,阐述技术原理与应用,结合真实案例与代码给出实操方案,助力提升金融衍生品定价的准确性与效率。
Java 大视界 -- Java 大数据机器学习模型在金融衍生品定价中的创新方法与实践(166)
现代应用场景中 Java 集合框架的核心技术与实践要点
本内容聚焦Java 17及最新技术趋势,通过实例解析Java集合框架的高级用法与性能优化。涵盖Record类简化数据模型、集合工厂方法创建不可变集合、HashMap初始容量调优、ConcurrentHashMap高效并发处理、Stream API复杂数据操作与并行流、TreeMap自定义排序等核心知识点。同时引入JMH微基准测试与VisualVM工具分析性能,总结现代集合框架最佳实践,如泛型使用、合适集合类型选择及线程安全策略。结合实际案例,助你深入掌握Java集合框架的高效应用与优化技巧。
81 4
【Java进阶】JavaScript电灯开关实例:从理论到实践
这个例子展示了JavaScript的基本功能,包括操作HTML元素,监听事件,以及改变元素的样式。通过学习和理解这个例子,你可以了解到JavaScript在网页中的应用,以及如何使用JavaScript来创建交互式的网页。
71 13
从理论到实践:使用JAVA实现RAG、Agent、微调等六种常见大模型定制策略
大语言模型(LLM)在过去几年中彻底改变了自然语言处理领域,展现了在理解和生成类人文本方面的卓越能力。然而,通用LLM的开箱即用性能并不总能满足特定的业务需求或领域要求。为了将LLM更好地应用于实际场景,开发出了多种LLM定制策略。本文将深入探讨RAG(Retrieval Augmented Generation)、Agent、微调(Fine-Tuning)等六种常见的大模型定制策略,并使用JAVA进行demo处理,以期为AI资深架构师提供实践指导。
497 73

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问