自学内容网 自学内容网

使用argo workflow 实现springboot 项目的CI、CD

在实现 Spring Boot 项目的 CI/CD 流程时,可以使用 Argo Workflows 来自动化构建、测试和部署过程。Argo Workflows 是一个 Kubernetes 原生的工作流引擎,能够在 Kubernetes 集群中定义、运行、监控和管理复杂的工作流。

基础镜像制作

基础镜像

FROM openjdk:8-jdk-slim

这行指定了构建的基础镜像是 openjdk:8-jdk-slim。这是一个包含了 Java 8 开发工具包(JDK)的精简版镜像,适用于 Java 开发和运行环境。

设置镜像源并安装工具git

RUN echo "deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib" > /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y git wget tar \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*
  • 更改 apt 源:使用阿里云的 Debian 镜像源(bullseye),提高安装软件包时的速度和稳定性,尤其是在中国地区。

  • 更新软件包索引:apt-get update 更新包索引。

  • 安装软件包:通过 apt-get install -y 安装 git(用于版本控制)、wget(用于下载文件)、和 tar(用于解压文件)。

  • 清理缓存:使用 apt-get clean 清理下载缓存,减少镜像体积。然后,rm -rf /var/lib/apt/lists/* 删除 apt 包索引文件,进一步减小镜像体积。

下载和安装 Maven

RUN wget https://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.tar.gz -P /tmp || (echo "Maven download failed!" && exit 1)
  • 下载 Maven:使用 wget 从阿里云镜像站点下载 Maven 3.8.6 的二进制压缩包。如果下载失败,将输出错误消息并终止构建。
RUN tar -xvzf /tmp/apache-maven-3.8.6-bin.tar.gz -C /usr/share/ \
    && rm -f /tmp/apache-maven-3.8.6-bin.tar.gz \
    && ln -s /usr/share/apache-maven-3.8.6/bin/mvn /usr/bin/mvn
  • 解压 Maven:解压下载的 Maven 压缩包到 /usr/share/目录。

  • 清理临时文件:删除下载的压缩包。

  • 创建符号链接:通过 ln -s 创建一个符号链接,将 Maven 的可执行文件 mvn 链接到 /usr/bin/mvn,使得 Maven 命令可以在任何地方使用。

设置环境变量

ENV MAVEN_HOME=/usr/share/apache-maven-3.8.6
ENV PATH=$MAVEN_HOME/bin:$PATH
  • MAVEN_HOME:设置 Maven 的环境变量,指向解压后的 Maven 目录。
  • 更新 PATH:将 Maven 的 bin 目录添加到 PATH 环境变量中,这样就可以直接在命令行使用 mvn 命令。

设置工作目录

WORKDIR /app

设置容器的工作目录为 /app。所有后续的命令(如构建、运行程序)将会在该目录下执行。这个目录是你在容器中执行应用程序的默认位置。

默认命令

CMD ["bash"]
  • 这个命令指定了容器启动时的默认命令是 bash。也就是说,如果你运行这个容器但没有指定其他命令,它将启动一个交互式的 bash shell。

最终dockerfile

FROM openjdk:8-jdk-slim

# 使用 Debian 11 (bullseye) 的镜像源
RUN echo "deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib" > /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y git wget tar \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 下载 Maven
RUN wget https://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.tar.gz -P /tmp || (echo "Maven download failed!" && exit 1)

# 解压 Maven 并创建符号链接
RUN tar -xvzf /tmp/apache-maven-3.8.6-bin.tar.gz -C /usr/share/ \
    && rm -f /tmp/apache-maven-3.8.6-bin.tar.gz \
    && ln -s /usr/share/apache-maven-3.8.6/bin/mvn /usr/bin/mvn

# 设置环境变量
ENV MAVEN_HOME=/usr/share/apache-maven-3.8.6
ENV PATH=$MAVEN_HOME/bin:$PATH

# 设置工作目录
WORKDIR /app

# 默认命令
CMD ["bash"]

执行构建:

docker build -t git-maven-base:v1 . -f Dockerfile

制作ci argo workflow 模版

volumeClaimTemplates

volumeClaimTemplates:
  - metadata:
      name: shared-workdir
    spec:
      accessModes: ["ReadWriteMany"]
      resources:
        requests:
          storage: 1Gi
  - metadata:
      name: maven-repo-cache
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 2Gi
  • shared-workdir: 这个 PVC 用于在工作流中的不同任务之间共享数据。它的存储请求为 1 GiB,并且支持 ReadWriteMany,意味着多个 pod 可以同时读写该存储。

  • maven-repo-cache : 用于缓存 Maven 本地仓库的数据。它的存储请求为 2 GiB,同样支持 ReadWriteMany可以在不同的 pod 之间共享缓存数据,避免每次构建时都重新下载依赖

templates

在 templates 部分定义了多个步骤的模板,每个步骤会在不同的容器中执行。

main 模板

- name: main
  dag:
    tasks:
      - name: git-clone
        template: git-clone
      - name: docker-build
        template: docker-build
        dependencies: [git-clone]
  • dag:这里使用的是 DAG(有向无环图) 结构,git-clone 任务是 docker-build 的前置依赖(即 docker-build 需要在 git-clone 完成后才开始执行)。

git-clone 模板

- name: git-clone
  container:
    image: git-maven-base:v1
    command: [sh, -c]
    args:
      - |
        git clone https://gitee.com/qfxcoffee/shield.git /src
        cd /src/arthas-study && mvn clean package -DskipTests
        cd /src/arthas-study/target
        mv arthas-study.jar /src/arthas-study.jar
        mv /src/arthas-study/docker/Dockerfile /src/
        cp -r /src/. /mnt/  # 将文件复制到挂载的 PVC 中
    volumeMounts:
      - name: shared-workdir
        mountPath: /mnt  # 挂载到容器的 /mnt 目录
      - name: maven-repo-cache
        mountPath: /root/.m2/repository  # 挂载到 Maven 本地仓库路径

git-clone 任务使用一个 git-maven-base:v1 的镜像来执行 Git 克隆操作,并且使用 Maven 构建项目。

构建过程中,Maven 会将依赖缓存到 /root/.m2/repository,并且将源码和构建产物(如 arthas-study.jarDockerfile)复制到 /mnt,这个路径会映射到共享的 PVC (shared-workdir),保证不同任务之间的数据共享。

docker-build 模板

- name: docker-build
  container:
    image: docker:19.03.12-dind
    command: [ "/bin/sh", "-c" ]
    args: [
      "docker info && cd /mnt && docker build -t my-image:v1 ."
    ]
    volumeMounts:
      - name: shared-workdir
        mountPath: /mnt  # 挂载到容器的 /mnt 目录
      - name: docker-socket
        mountPath: /var/run/docker.sock
      - name: maven-repo-cache
        mountPath: /root/.m2/repository  # 挂载到 Maven 本地仓库路径
  • docker-build 任务使用 docker:19.03.12-dind 镜像(Docker-in-Docker),这意味着可以在容器内执行 Docker 命令。它会进入挂载的 /mnt 目录,执行 docker build 来构建 Docker 镜像。

  • 挂载了 docker-socket,这样容器可以与宿主机上的 Docker 服务进行通信,执行构建命令。

volumes

volumes:
  - name: docker-socket
    hostPath:
      path: /var/run/docker.sock
      type: Socket
  - name: maven-repo-cache
    hostPath:
      path: /root/.m2/repository
      type: Directory

  • docker-socket: 宿主机上的 Docker 套接字 (/var/run/docker.sock) 被挂载到容器中,使得容器能够访问宿主机的 Docker 引擎,从而执行 Docker 命令。

  • maven-repo-cache: 这里挂载了宿主机上的 /root/.m2/repository 目录到容器中,用于缓存 Maven 本地仓库。这意味着 Maven 任务在执行时会使用这个缓存,而不必每次都从远程仓库下载依赖,减少了构建时间。

hostPathvolumeClaimTemplates 中的 PVC 用法:

hostPath 通过指定宿主机上的目录或套接字,让容器能够访问宿主机的资源。
volumeClaimTemplates 则是在 Kubernetes 中动态创建 PVC,并在 Pod 内部挂载这些 PVC,使得多个任务之间可以共享文件和数据。

这两种挂载方式在某些场景下配合使用,可以提供灵活的数据共享和存储策略。

完整workflow文件

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: pvs-demo-
spec:
  entrypoint: main
  volumeClaimTemplates:
    - metadata:
        name: shared-workdir  # 共享的 PVC 名称
      spec:
        accessModes: ["ReadWriteMany"]  # 多个 Pod 可以同时读取和写入
        resources:
          requests:
            storage: 1Gi
    - metadata:
        name: maven-repo-cache  # 用于缓存 Maven 本地仓库
      spec:
        accessModes: [ "ReadWriteMany" ]
        resources:
          requests:
            storage: 2Gi
  templates:
    - name: main
      dag:
        tasks:
          - name: git-clone
            template: git-clone
          - name: docker-build
            template: docker-build
            dependencies: [git-clone]

    - name: git-clone
      container:
        image: git-maven-base:v1
        command: [sh, -c]
        args:
          - |
            git clone https://gitee.com/qfxcoffee/shield.git /src
            cd /src/arthas-study && mvn clean package -DskipTests
            cd /src/arthas-study/target
            mv arthas-study.jar /src/arthas-study.jar
            mv /src/arthas-study/docker/Dockerfile /src/
            cp -r /src/. /mnt/  # 将文件复制到挂载的 PVC 中
        volumeMounts:
          - name: shared-workdir  # 挂载 PVC
            mountPath: /mnt  # 挂载到容器的 /mnt 目录
          - name: maven-repo-cache
            mountPath: /root/.m2/repository  # 将 PVC 挂载到 Maven 本地仓库路径

    - name: docker-build
      container:
        image: docker:19.03.12-dind
        command: [ "/bin/sh", "-c" ]
        args: [
          "docker info && cd /mnt && docker build -t my-image:v1 ."
        ]
        volumeMounts:
          - name: shared-workdir  # 挂载共享 PVC,确保构建上下文可用
            mountPath: /mnt  # 挂载到容器的 /mnt 目录
          - name: docker-socket
            mountPath: /var/run/docker.sock
          - name: maven-repo-cache
            mountPath: /root/.m2/repository  # 将 PVC 挂载到 Maven 本地仓库路径

  volumes:
    - name: docker-socket
      hostPath:
        path: /var/run/docker.sock
        type: Socket
    - name: maven-repo-cache
      hostPath:
        path: /root/.m2/repository  # 宿主机上的目录路径
        type: Directory  # 可以是 Directory 或 File,取决于你的需求

在这里插入图片描述

在这里插入图片描述

可以看到maven构建及docker构建镜像成功

制作cd argo workflow 模版

Workflow 结构

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: springboot-service-workflow-
spec:
  entrypoint: springboot-workflow
  • apiVersion: argoproj.io/v1alpha1kind: Workflow:这定义了这是一个 Argo Workflow 类型的资源,表示这个文件用于定义一个工作流。

  • metadata.generateName: springboot-service-workflow-:这个字段为工作流生成一个唯一的名称。generateName 表示 Argo 会在每次创建工作流时,为该工作流添加一个随机的后缀,以确保工作流名称的唯一性。

  • spec.entrypoint: springboot-workflow:指定工作流的入口点,即从哪个模板开始执行。在这个例子中,工作流会从 springboot-workflow 模板开始执行。

Templates 定义

接下来的部分定义了工作流中的多个步骤 (steps),这些步骤会按顺序执行。

创建 Kubernetes 服务 (create-service)

- name: create-service
  resource:
    action: apply
    manifest: |
      apiVersion: v1
      kind: Service
      metadata:
        name: springboot-service
      spec:
        selector:
          app: springboot-app
        ports:
          - protocol: TCP
            port: 8080
            targetPort: 8080
        type: NodePort  # 可以根据需要修改为 LoadBalancer 或 NodePort

  • name: create-service:这个步骤的名称。
  • resource:
    • action: apply:表示使用 kubectl apply 命令应用 Kubernetes 资源,创建一个服务。
    • manifest: 这是一个 Kubernetes Service 的 YAML 定义,描述了服务的配置。
    • apiVersion: v1 和 kind: Service:表示这个资源是一个 Kubernetes 服务。
    • metadata.name: springboot-service:服务的名称是 springboot-service。
      • spec:
        • selector: 用于选择应用的 Pod。这里的选择器选择标签为 app: springboot-app 的 Pod。
        • ports: 定义服务的端口,服务监听 8080 端口,并将请求转发到目标端口 8080。
        • type: NodePort:指定服务类型为 NodePort,这意味着服务将暴露在 Kubernetes 节点的一个端口上,便于从外部访问应用。你可以根据需要将其改为 LoadBalancer 或 ClusterIP,具体取决于你的网络需求。

启动 Spring Boot 容器 (springboot-container)


- name: springboot-container
  container:
    name: springboot-app
    image: my-image:v1  # 替换成你的 Docker 镜像
    command: [ "java" ]  # 显式指定命令为 `java`
    args: [ "-jar", "arthas-study.jar" ]  # 显式指定 `arthas-study.jar` 文件作为参数
    ports:
      - containerPort: 8080
    env:
      - name: SPRING_PROFILES_ACTIVE
        value: "prod"
  metadata:
    labels:
      app: springboot-app

完整workflow内容

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: springboot-service-workflow-
spec:
  entrypoint: springboot-workflow
  templates:
    - name: springboot-workflow
      steps:
        - - name: create-service
            template: create-service
        - - name: start-springboot-container
            template: springboot-container

    - name: create-service
      resource:
        action: apply
        manifest: |
          apiVersion: v1
          kind: Service
          metadata:
            name: springboot-service
          spec:
            selector:
              app: springboot-app
            ports:
              - protocol: TCP
                port: 8080
                targetPort: 8080
            type: NodePort  # 可以根据需要修改为 LoadBalancer 或 NodePort

    - name: springboot-container
      container:
        name: springboot-app
        image: my-image:v1  # 替换成你的 Docker 镜像
        command: [ "java" ]  # 显式指定命令为 `java`
        args: [ "-jar", "arthas-study.jar" ]  # 显式指定 `arthas-study.jar` 文件作为参数
        ports:
          - containerPort: 8080
        env:
          - name: SPRING_PROFILES_ACTIVE
            value: "prod"
      metadata:
        labels:
          app: springboot-app

在这里插入图片描述

可以看到springboot项目已经运行成功。

kubectl get svc -n argo

在这里插入图片描述

http://192.168.56.115:32356/user/1

在这里插入图片描述


原文地址:https://blog.csdn.net/qq_37362891/article/details/143996233

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!