学习如何从头开始设置 CI/CD 管道

2025-05-26

学习如何从头开始设置 CI/CD 管道

在本教程中,我们将以 Go 应用程序为例并设置 CI/CD 管道。

Go因其能够简化和保障现代应用程序的构建,在开发者中越来越受欢迎。该语言由 Google 创建,因其开源特性和使用 Go 语言编写程序的能力而备受青睐。Go 还允许用户自由构建自己的前端网站和应用程序,并且易于开发、维护和使用。企业可以依靠 Go 来构建和扩展云计算系统,同时享受其强大的并发功能。此外,Go 还能在不占用过多资源的情况下提供高性能。

今天,我们将创建一个简单的 Go 应用程序,并为其设置 CI/CD 流水线。开始吧!

先决条件

  • 创建一个免费的 SingleStore 帐户。在本教程中,我们将使用 SingleStore 作为数据库解决方案。SingleStore 是一个高性能内存数据库,支持 SQL 和 NoSQL 数据模型。

  • 创建免费的Harness 云帐户来设置 CI/CD

  • 从这里快速下载并安装 Go

  • 从任何云提供商访问 Kubernetes 集群来部署我们的应用程序(您也可以使用MinikubeKind来创建单节点集群)。

  • Docker,最好是Docker Desktop

教程

示例代码库可在此处访问;您可以随意 fork 它或直接照着做。我不会详细介绍应用程序代码本身。它是一个示例“Hello World”应用,会在本地主机 8080 端口打印文本“Hello World”。

以下是该文件的代码main.go

package main

import (
    "fmt"
    "log"
    "net/http"
)

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home Page")
}

func wsEndpoint(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World")
}

func setupRoutes() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/ws", wsEndpoint)
}

func main() {
    fmt.Println("Hello World")
    setupRoutes()
    log.Fatal(http.ListenAndServe(":8080", nil))
}
Enter fullscreen mode Exit fullscreen mode

该应用程序还有一个带有main_test.go简单测试用例的测试文件。

package main

import (
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestHomePage(t *testing.T) {
    req, err := http.NewRequest("GET", "/", nil)
    if err != nil {
        t.Fatal(err)
    }
    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(homePage)
    handler.ServeHTTP(rr, req)
    if status := rr.Code; status != http.StatusOK {
        t.Errorf("handler returned wrong status code: got %v want %v",
            status, http.StatusOK)
    }
    if rr.Body.String() != "Home Page" {
        t.Errorf("handler returned unexpected body: got %v want %v",
            rr.Body.String(), "Home Page")
    }
}

func TestWsEndpoint(t *testing.T) {
    req, err := http.NewRequest("GET", "/ws", nil)
    if err != nil {
        t.Fatal(err)
    }
    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(wsEndpoint)
    handler.ServeHTTP(rr, req)
    if status := rr.Code; status != http.StatusOK {
        t.Errorf("handler returned wrong status code: got %v want %v",
            status, http.StatusOK)
    }
    if rr.Body.String() != "Hello World" {
        t.Errorf("handler returned unexpected body: got %v want %v",
            rr.Body.String(), "Hello World")
    }
}
Enter fullscreen mode Exit fullscreen mode

您在 repo 中看到的 Dockerfile 将用于构建我们的应用程序并将其作为映像推送到 Docker Hub。

FROM golang:1.16.4-buster AS builder

ARG VERSION=dev

WORKDIR /go/src/app
COPY main.go .
RUN go build -o main -ldflags=-X=main.version=${VERSION} main.go 

FROM debian:buster-slim
COPY --from=builder /go/src/app/main /go/bin/main
ENV PATH="/go/bin:${PATH}"
CMD ["main"]
Enter fullscreen mode Exit fullscreen mode

接下来我们将使用以下命令构建镜像并将其推送到 Docker Hub,

docker buildx build --platform=linux/arm64 --platform=linux/amd64 -t docker.io/<docker hub username>/<image name>:<tag> --push -f ./Dockerfile .
Enter fullscreen mode Exit fullscreen mode

一旦构建和推送成功,您可以通过访问您的 Docker Hub 帐户进行确认。

DockerHub 上的 Golang 镜像

我们将在 Kubernetes 集群上部署我们的应用程序。您可以forked 的仓库
中 看到deployment.yaml和文件,它们定义了部署和服务,以帮助我们部署和公开应用程序。此时,请确保您的 Kubernetes 集群已启动并正在运行。service.yaml

我们的deployment.yaml文件如下所示

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-app-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-app
  template:
    metadata:
      labels:
        app: go-app
    spec:
      containers:
      - name: go-app
        image: pavansa/golang-hello-world:latest
        ports:
        - containerPort: 8080
        env:
        - name: PORT
          value: "8080"
Enter fullscreen mode Exit fullscreen mode

service.yaml 文件如下所示,

apiVersion: v1
kind: Service
metadata:
  name: go-app-service
spec:
  selector:
    app: go-app
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer
Enter fullscreen mode Exit fullscreen mode

现在是时候设置一个 Harness 帐户来执行 CI/CD 了。Harness 是一个具有 AI/ML 功能的现代 CI/CD 平台。

创建一个免费的 Harness 帐户并开始您的第一个项目。注册 Harness 后,您将获得全新的 CI/CD 体验和功能。

添加所需的连接器,例如Harness Delegate、您的 GitHub 仓库、Docker Hub 帐户和密钥。Harness 中的 Delegate 是您需要在目标集群(在本例中为 Kubernetes 集群)上安装/运行的服务/软件,用于将您的构件、基础设施、协作、验证和其他提供程序与 Harness Manager 连接起来。首次设置 Harness 时,您需要安装 Harness Delegate

持续集成

登录 Harness 后,它首先会要求您创建一个项目。

从项目开始

如果您愿意,可以邀请合作者参与该项目。
邀请合作者

选择持续集成模块。
持续集成模块

创建您的第一个管道。
第一条管道

连接到您的源代码控制管理(如 GitHub),其中包含应用程序代码。
供应链管理连接

接下来,使用项目的适当语言配置您的管道。
配置管道

当您保存并继续时,您会在管道工作室中看到以下默认设置。
管道工作室

当您点击执行下的“Go Build App”时,您将看到以下设置详细信息。
去构建应用程序

默认设置

让我们修改上一步/上面的步骤,将其命名为“Test Go App”,在命令选项卡中添加以下代码,然后保存并运行管道。

修改管道

运行管道

您应该会看到成功的输出:)
成功输出

我们成功为应用程序创建了一条 CI 流水线,用于代码的构建和测试。接下来,让我们将这个想法扩展到我们的目标环境,也就是 Kubernetes,来部署这段无错误的应用程序代码。

持续交付和部署

现在是时候部署我们的 Go 应用程序了,创建部署阶段。
应用程序部署

为您的阶段添加一个名称,选择部署类型为“Kubernetes”,然后单击“设置阶段”。
部署详细信息

这是您在创建部署阶段后应该看到的内容。
服务工作室

我们需要创建一个服务。因此,点击“添加服务”。下一步,我们需要为服务添加名称和清单详细信息。
服务详情

点击“添加清单”以添加详细信息。
舱单详情添加

然后选择K8S清单并继续。
k8s清单

k8s 类型 mani

指定 K8S 清单存储。我们知道清单文件位于 GitHub 中。因此选择 GitHub。
清单存储

添加一个新的 GitHub 连接器来连接您的清单文件。
GitHub 连接器文件

逐步指定所有细节。
来源详情

通过内置秘密添加凭证。
信用秘密

与您的代表联系。
连接委托

确保您的清单与您的委托人的连接成功。
成功代理连接

现在,从你的 GitHub 仓库添加清单详细信息。 保存所有内容并继续。 你应该会看到包含清单详细信息的服务。
来自 repo 的 mani 详细信息

包含舱单详情的服务

您的管道工作室将会像这样,并附加了您的服务。
已添加服务

添加新环境,保存并继续。
新环境

同样,添加新的基础设施。选择“Kubernetes”作为基础设施类型,并添加集群详细信息。
基础设施库类型

集群详细信息

保存并继续。

下一步,您需要选择部署策略类型。我们选择“滚动”作为部署策略。
部署策略

我们都完成了,这就是我们的 CD 管道的样子。
CD 管道

现在,保存所有内容并运行管道。
运行 CICD 管道

您应该看到管道从 CI 开始逐步执​​行,然后 CD 成功执行。
CICD成功

自动化 CI/CD

最后一步是通过创建触发器来实现 CI/CD 流水线的自动化。我们开始吧。

在管道工作室中,您可以看到“触发器”选项卡。
触发器选项卡

单击“触发器”选项卡并创建一个新的触发器。
新触发器

添加 GitHub 触发器,每当有人将新代码推送到主分支时,管道就会自动触发。
GitHub 触发器

触发器详细信息
触发器已添加
更多触发细节

保存所有内容并创建触发器。

您应该在“触发器”选项卡下看到已创建的触发器。

现在,让我们确认一下我们的 CI/CD 是否自动化并正常运行。将一个 readme 文件添加到我们的 GitHub 仓库,看看它是否触发了我们的流水线。
更新的自述文件

您会看到,当发生新的代码提交时,管道就会触发。
自动化流水线

我们已经成功地使用 Harness 实现了 Go 应用程序的 CI/CD 流程自动化。

另外,请查看我关于持续集成和部署的其他文章。

文章来源:https://dev.to/pavanbelagatti/learn-how-to-setup-a-cicd-pipeline-from-scratch-for-a-go-application-4m69
PREV
我最喜欢的用于构建 AI/ML 应用程序的 DevTools!
NEXT
免费学习生成式人工智能 [电子书]!