github和dockerhub非常好用,是很多CI/CD平台的关键环节。不过它们作为互联网平台,天生具有开放共享的特点,对于企业内部代码开发来说,私密性不够,存在代码泄露的风险。

gitea是一套类似于github的软件,它的功能特性高度接近github,很容易上手。它还内置了一个容器注册表,几乎可以平替dockerhub。

gitea也支持actions,语法几乎和github actions一模一样,可以作为CI/CD工具使用。

使用gitea,可以在局域网内部搭建一个私有的CI/CD平台,满足企业软件开发的需要。

操作系统debian 12 ,kubernetes 1.28.4, gitea 1.21.11

一、安装与设置

1. 安装gitea容器

gitea的安装,最好是在docker或者裸机环境下进行。

在一台独立主机上,先安装docker

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

新建文件docker-compose.yaml,内容如下

version: "3"

networks:
  gitea:
    external: false

services:
  server:
    image: gitea/gitea:1.21.11
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "222:22"

运行

docker compose up -d

启动gitea。访问http://<gitea-server-ip>:3000 可以看到gitea界面。

进行初始配置,如果用户量不大,数据库类型可以选择SQLite。

设置管理员账号,并登录。

2. 修改docker设置

修改文件/etc/docker/daemon.json,增加如下内容

{
    "insecure-registries" : ["<gitea-server-ip>:3000"]
}

其中<gitea-server-ip>是gitea服务器的ip地址,根据实际情况修改。

然后运行

systemctl restart docker

重启docker。

3. 安装runner容器

gitea的actions,运行在一个独立的runner容器里面,需要单独安装。

先把runner镜像拉到本地

docker pull gitea/act_runner:latest

然后获取token, 用来让runner连接到gitea。

访问http:///<gitea-server-ip>:3000/admin/actions/runners进入gitea管理界面,点击创建Runner,会显示一个REGISTRATION TOKEN, 把它复制出来。<gitea-server-ip>是gitea服务器的IP地址,根据实际情况修改。

运行

docker run \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -e GITEA_INSTANCE_URL=http://<gitea-server-ip>:3000 \
    -e GITEA_RUNNER_REGISTRATION_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx \
    --name my_runner \
    -d gitea/act_runner:latest

其中<gitea-server-ip>是gitea服务器的ip地址,xxxxxxxxxxxxxxxxxxxxxxxxxxxx就是上面步骤得到的token,根据实际情况修改。

访问http://<gitea-server-ip>:3000/admin/actions/runners,可以看到runner已经在线了。

4. 安装https反向代理

使用nginx和acme.sh,给gitea套上https。

首先需要给gitea服务器申请一个域名,假设域名为gitea.yourdomain.com。

在gitea服务器上,运行

apt install nginx

安装nginx。

修改/etc/nginx/nginx.conf,在 http{} 配置内,添加以下内容

server {
    listen 80;
    server_name gitea.yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen              443 ssl;
    server_name         gitea.yourdomain.com;
    ssl_certificate     /etc/nginx/certs/gitea.yourdomain.com/cert;
    ssl_certificate_key /etc/nginx/certs/gitea.yourdomain.com/key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

运行

curl https://get.acme.sh | sh -s email=my@example.com
alias acme.sh=~/.acme.sh/acme.sh

安装acme.sh。

如果域名是在google domain申请的,那么运行下列命令,申请证书

export GOOGLEDOMAINS_ACCESS_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxx" 
acme.sh --issue --dns dns_googledomains -d gitea.yourdomain.com

其中xxxxxxxxxxxxxxxxxxxxxxxxxxx是令牌,可以进入google domain的管理界面,在域名管理中点击安全->ACME DNS API->创建令牌,获得一个令牌。

运行

mkdir /etc/nginx/certs
mkdir /etc/nginx/certs/gitea.yourdomain.com
acme.sh --install-cert -d gitea.yourdomain.com \
--cert-file /etc/nginx/certs/gitea.yourdomain.com/cert \
--key-file /etc/nginx/certs/gitea.yourdomain.com/key \
--fullchain-file /etc/nginx/certs/gitea.yourdomain.com/fullchain \
--reloadcmd "systemctl reload nginx.service"

访问https://gitea.yourdomain.com, 就可以看到gitea的web界面了。

5. 在kubernetes集群上安装证书

登录到Kubernetes集群的每台master和worker主机上,运行下列命令

cd /usr/local/share/ca-certificates/
openssl s_client -showcerts -verify 5 -connect gitea.yourdomain.com:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | tee ca.crt
update-ca-certificates
systemctl restart containerd

把gitea的https证书添加到每台kubernetes主机上。

6.修改kubernetes代理服务器配置(可选)

如果kubernetes为镜像下载设置过代理服务器,那么需要修改配置。

在每台master和worker主机上,编辑文件/etc/systemd/system/containerd.service.d/http-proxy.conf,在NO_PROXY配置中加入gitea服务器的域名。类似于

[Service]
Environment="HTTP_PROXY=http://username:password@proxy-server-ip:port"
Environment="HTTPS_PROXY=http://username:password@proxy-server-ip:port"
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,aliyuncs.com,gitea.yourdomain.com,.svc,.cluster.local,.ewhisper.cn,<nodeCIDR>,<APIServerInternalURL>,<serviceNetworkCIDRs>,<etcdDiscoveryDomain>,<clusterNetworkCIDRs>,<platformSpecific>,<REST_OF_CUSTOM_EXCEPTIONS>"

其中gitea.yourdomain.com是gitea服务器的域名,根据实际情况修改。

然后在每台主机上重启containerd,运行

systemctl daemon-reload
systemctl restart containerd

二、样例部署和测试

1.部署测试案例

登录到gitea的web管理界面,新建一个仓库,名为gitea-action-runner。

在开发主机上运行下列命令,同步代码

git clone http://<gitea-server-ip>:3000/<gitea-username>/gitea-action-runner.git

其中<gitea-server-ip>是gitea服务器的IP地址,<gitea-username>是你在gitea上的账号名,根据实际情况修改。

运行下列命令,安装nodejs

curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash -
sudo apt-get install -y nodejs

运行下列命令,新建一个react应用。

npm create vite@latest  gitea-action-runner

选择react和javascript。

运行

cd gitea-action-runner
npm install

修改vite.config.js如下

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
 base: "/",
 plugins: [react()],
 preview: {
  port: 5173,
  strictPort: true,
 },
 server: {
  port: 5173,
  strictPort: true,
  host: true,
  origin: "http://0.0.0.0:5173",
 },
});

运行

npm run build
npm run preview

可以看到web服务的运行情况,ctrl+c退出。

在gitea-action-runner目录下,创建Dockerfile文件,内容如下

#It will use node:21-alpine3.19 as the parent image for
#building the Docker image
FROM node:21-alpine3.19
#It will create a working directory for Docker. The Docker
#image will be created in this working directory.
WORKDIR /app
#Copy the React application dependencies from the
#package.json to the react-app working directory.
COPY package.json .
#install all the React application dependencies
RUN npm i
COPY . .
RUN npm run build
#Expose the React application container on port 5173
EXPOSE 5173
#The command to start the React application container
CMD ["npm", "run", "preview"]

创建deployment.yaml文件,内容如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitea-react
  labels:
    app: gitea-react-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: gitea-react-app
  template:
    metadata:
      labels:
        app: gitea-react-app
    spec:
      containers:
      - name: gitea-react-app
        image: gitea.yourdomain.com/gitea-username/gitea-react-app:latest
        ports:
        - containerPort: 5173

其中gitea.yourdomain.com是gitea服务器的域名,gitea-username是你在gitea上的账号名,按照实际情况修改。

创建service.yaml文件,内容如下

apiVersion: v1
kind: Service
metadata:
  name: gitea-react
spec:
  selector:
    app: gitea-react-app
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 5173
    targetPort: 5173

在gitea-action-runner目录下,新建目录.github/workflows,进入该目录,新建文件workflow.yaml,内容如下

name: Deploy act-react

on:
  push:
    branches:
      - main

env:
  REGISTRY_URL: <gitea-server-ip>:3000/<gitea-username>
  REGISTRY_SITE: http://<gitea-server-ip>:3000
  SERVICE_NAME: gitea-react-app
  SERVICE_TAG: latest

jobs:
  build:
    runs-on: ubuntu-latest
    if: gitea.ref == 'refs/heads/main'
    steps:
      - name: Checkout
        uses: https://gitea.com/actions/checkout@v4

      - name: Login to Docker Hub
        uses: https://gitea.com/docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY_SITE }}
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Set up Docker Buildx
        uses: https://gitea.com/docker/setup-buildx-action@v3
        with:
          config-inline: |
            [registry."<gitea-server-ip>:3000"]
              http = true
              insecure = true

      - name: Build and push orchestration service
        uses: https://gitea.com/docker/build-push-action@v5
        with:
          context: .
          tags: |
            ${{ env.REGISTRY_URL }}/${{ env.SERVICE_NAME }}:${{gitea.sha}}
            ${{ env.REGISTRY_URL }}/${{ env.SERVICE_NAME }}:latest
          push: true

      - name: Deploying
        uses: http://<gitea-server-ip>:3000/<gitea-username>/kubectl@master
        env:
          KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
        with:
          args:   apply -f deployment.yaml -f service.yaml

      - name: Update image
        uses: http://<gitea-server-ip>:3000/<gitea-username>/kubectl@master
        env:
          KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
        with:
          args:  set image deployment/gitea-react ${{ env.SERVICE_NAME }}=<gitea.yourdomain.com>/<gitea-username>/${{ env.SERVICE_NAME }}:${{gitea.sha}}

其中<gitea-server-ip>是gitea服务器的IP地址,gitea.yourdomain.com是gitea服务器的域名,<gitea-username>是你在gitea上的账号,根据实际情况修改。

登录到gitea的web管理界面,进入仓库gitea-action-runner,点击设置->Actions->密钥,添加3个密钥:

DOCKERHUB_USERNAME,值为你在gitea上的账号名。

DOCKERHUB_TOKEN,值为你在gitea上的账号密码。

KUBE_CONFIG,值为kubernetes master主机的config文件内容,通过在master主机上运行 cat $HOME/.kube/config | base64 得到。

登录到gitea的web管理界面,点击右上角的“+”,点击“迁移外部仓库”,选择github,克隆URL填写https://github.com/actions-hub/kubectl ,选中“该仓库将是一个镜像”,点击”迁移仓库”,完成对kubectl action的克隆。

2. 测试自动触发

在gitea-action-runner目录下,运行下列命令,把代码同步到gitea。

git add -A
git commit -m "first commit"
git branch -M main
git push origin main

push操作自动触发了工作流,登录到gitea的web界面,在仓库的actions下面,可以看到工作流的整个运行过程,包括代码检出、docker镜像构建、docker镜像推送,最后把deployment和service部署到kubernetes集群的整个流程。

登录到Kubernetes的master主机,运行

kubectl get deployment
kubectl get svc

可以看到新增的deployment和service,名为gitea-react。

访问http://<gitea-react-svc-ip>:5173 ,可以看到react应用的界面。

<gitea-react-svc-ip>是名为gitea-react的service的外部ip地址,根据实际情况修改。

这样gitea actions就安装部署完成了,每次push代码,就会自动触发运行,完成CI/CD的整个过程。

参考:

https://docs.gitea.com/installation/install-with-docker

https://medium.com/@lokanx/how-to-build-docker-containers-using-gitea-runners-600729555e07

https://docs.gitea.com/zh-cn/1.20/usage/actions/act-runner

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注