开源CI&CD工具-Drone

目录

一.简介

二.组件介绍

[Drone Server(调度与管理中心)](#Drone Server(调度与管理中心))

[Drone Runner(任务执行者)](#Drone Runner(任务执行者))

三.配置部署

[3.1 配置Gitee](#3.1 配置Gitee)

设置仓库Webhooks

设置Gitee第三方应用

仓库中添加配置文件

[3.2 部署Drone Server和Drone Runner](#3.2 部署Drone Server和Drone Runner)

[Drone Server](#Drone Server)

[Drone Runner](#Drone Runner)

[3.3 初始化Drone Web UI](#3.3 初始化Drone Web UI)

[3.4 测试](#3.4 测试)


一.简介

在现代软件开发流程中,持续集成(CI)与持续部署(CD)已成为团队快速交付与稳定迭代的关键环节。

Drone作为一个轻量级 、云原生的 CI/CD 系统,以其容器化、易扩展、高度自动化的特性,被越来越多团队用于替代传统的Jenkins、GitLab CI等工具。

本文将介绍一个基于Drone + GitLab + Harbor + Kubernetes的完整自动化构建与部署架构,帮助开发者实现从代码提交到应用上线的全自动流水线。

整个CI&CD流程如上面数据访问流所示:

1.当开发者向代码仓库推送代码或合并分支时,代码仓库通过Webhook通知Drone Server;

2.Drone Server分配任务给Drone Runner执行代码拉取、编译构建、生成容器镜像、推送到容器仓库、部署到Kubernetes或者服务器上、自定义的测试验证脚本等;

整个过程完全自动化,构建日志和执行状态可通过Drone Web UI实时查看。

二.组件介绍

Drone Server(调度与管理中心)

Drone Server是整个流水线的核心调度控制器,主要功能包括:

  • 接收来自GitLab等代码仓库的Webhook请求;

  • 校验签名与权限;

  • 解析项目根目录下的 .drone.yml配置文件;

  • 调度Drone Runner执行任务;

  • 提供Web UI用于实时查看:

    • 仓库与分支列表;

    • 构建历史与执行日志;

    • 每个步骤的状态(成功 / 失败 / 执行中)。

Server与Runner之间通过gRPC / HTTP API通信,并使用DRONE_RPC_SECRET进行身份认证。

Drone Runner(任务执行者)

Drone Runner是一个常驻的执行代理,负责从Drone Server拉取构建任务并启动实际的执行环境。它本身并不直接执行构建步骤,而是根据 .drone.yml文件的内容,动态创建临时容器(或 Kubernetes Pod) 来完成各个步骤的操作。

整个过程如下:

  1. 拉取任务:Drone Runner从Drone Server轮询新的构建请求;

  2. 准备环境:为本次构建创建一个隔离的执行环境(Docker容器或 K8s Pod);

  3. 执行步骤:按照 .drone.yml中定义的每个step,依次启动临时容器执行任务;

  4. 上报结果:任务执行完毕后,Runner收集所有步骤的日志与状态,通过gRPC / HTTP回传给Drone Server;

  5. 清理环境:临时容器或Pod自动销毁,确保环境干净、可复用。

Drone Runner 支持多实例并行运行,不同Runner可通过标签(Label)区分职责,这样既保证了任务隔离,又能提升整个CI&CD集群的执行效率。

三.配置部署

我们以Kubernetes和Gitee代码库为例来演示整个Drone环境的搭建并测试CI&CD流程。

首先规划一个可供访问的域名,来代理Drone Server的Webhook,例如https://drone.fzwtest.xyz,虽然是个人测试环境,但为了保证安全性,我们只允许来自Gitee的出口IP地址段访问Drone的443端口。

3.1 配置Gitee

创建一个用来测试的代码仓库,然后做如下配置

设置仓库Webhooks

设置Gitee第三方应用

注意这是全局设置,不是代码仓库的设置,用来允许Drone Server回调Gitee API

仓库中添加配置文件

如下图所示,.drone.yml中定义CI&CD要执行的命令,Dockerfile和Kubernetes-cd.yaml是本次示例的.drone.yml用到的两个文件(根据实际情况添加)

.drone.yml文件内容如下,其中git clone阶段选择自定义执行命令,没有用它的集成组件:

复制代码
kind: pipeline
type: kubernetes
name: cidemo
metadata:
  namespace: drone
service_account_name: drone-ci
clone:
  disable: true

steps:
  - name: ci-Gitclone
    image: alpine/git
    environment:
      SSH_PRIVATE_KEY:
        from_secret: ssh_private_key
    commands:
      - echo "beginclone"
      - mkdir -p ~/.ssh
      - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
      - chmod 600 ~/.ssh/id_rsa
      - ssh-keyscan -H gitee.com >> ~/.ssh/known_hosts
      - git clone git@gitee.com:fan-zhiwei1211/fund-distribution.git;cd fund-distribution && git checkout dev
      - cp -r . ../
      - echo "endclone"
      - echo `date +"%Y-%m-%d_%H-%M-%S"`","`git rev-parse HEAD | cut -c 1-7` > /drone/src/.tags
      - cat /drone/src/.tags


  - name: ci-ImagePush
    image: docker:20.10-dind
    privileged: true
    environment:
      DOCKER_USERNAME:
        from_secret: DOCKER_USERNAME
      DOCKER_PASSWORD:
        from_secret: DOCKER_PASSWORD
    volumes:
      - name: dockersock
        host:
          path: /var/run
    commands:
      - dockerd-entrypoint.sh &  # 启动 docker daemon
      - sleep 10
      - docker version
      - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin crpi-d7xhghcft4dbtjor.cn-beijing.personal.cr.aliyuncs.com
      - TAG=$(cut -d ',' -f 1 /drone/src/.tags)
      - echo "Using tag:$TAG"
      - docker build -t crpi-d7xhghcft4dbtjor.cn-beijing.personal.cr.aliyuncs.com/dronefzw/fund-distribution:$TAG .
      - docker push crpi-d7xhghcft4dbtjor.cn-beijing.personal.cr.aliyuncs.com/dronefzw/fund-distribution:$TAG



  - name: cd-DeployToK8s
    image: bitnami/kubectl
    working_dir: /drone/src
    privileged: true
    environment:
      myuser:
        from_secret: DOCKER_USERNAME
      mypass:
        from_secret: DOCKER_PASSWORD
    commands:
      - pwd && ls /drone/src/
      - sed -i "s|IMAGE_TAG|`cat /drone/src/.tags |cut -d "," -f 1`|g" /drone/src/kubernetes-cd.yaml
      - kubectl apply -f /drone/src/kubernetes-cd.yaml
      - kubectl rollout status deployment/fund-distribution -n dev --timeout=10s
      - kubectl get pod -l app=fund-distribution -n dev -o wide

  - name: cd-test-api-with-curl
    image: curlimages/curl:latest
    commands:
      - |
        echo "开始测试API..."
        sleep 10
        RESPONSE_CODE=$(curl -o /dev/null -s -w "%{http_code}" http://fund-distribution.dev.svc.cluster.local:8124/)
        echo "获取到状态码: $RESPONSE_CODE" 
        if [ "$RESPONSE_CODE" != "200" ]; then
          echo "测试失败,状态码: $RESPONSE_CODE (期望200)" >&2
          exit 1  # 明确返回非0状态码
        else
          echo "测试通过"
        fi

trigger:
  event:
    - push
  branches:
    - dev

Dockerfile内容如下:

复制代码
# 使用轻量级基础镜像
#FROM docker.m.daocloud.io/library/python:3.11-slim
FROM crpi-d7xhghcft4dbtjor.cn-beijing.personal.cr.aliyuncs.com/dronefzw/fund-distribution:basic
WORKDIR /app
# 复制所有文件到容器中
COPY . /app

# 安装依赖(如果你有 requirements.txt)
#RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
# 暴露 80 端口
EXPOSE 8888

# 启动 nginx
CMD ["python3", "run.py"]

kubernetes-cd.yaml内容如下:

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fund-distribution
  namespace: dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fund-distribution
  template:
    metadata:
      labels:
        app: fund-distribution
    spec:
      imagePullSecrets:
        - name: acr-plaintext-secret
      containers:
        - name: fund-distribution
          image: crpi-d7xhghcft4dbtjor.cn-beijing.personal.cr.aliyuncs.com/dronefzw/fund-distribution:IMAGE_TAG
          ports:
            - containerPort: 8888

---
apiVersion: v1
kind: Service
metadata:
  name: fund-distribution
  namespace: dev
spec:
  selector:
    app: fund-distribution
  ports:
    - protocol: TCP
      port: 8124
      targetPort: 8888
      nodePort: 32669
  type: NodePort

3.2 部署Drone Server和Drone Runner

Drone Server

复制代码
apiVersion: v1
kind: ServiceAccount
metadata:
  name: drone-ci
  namespace: drone
automountServiceAccountToken: true
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: drone-secrets-manager
  namespace: drone
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log", "pods/exec","secrets"]
  verbs: ["get", "create","update", "delete","list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: drone-secrets-binding
  namespace: drone
subjects:
- kind: ServiceAccount
  name: drone-ci
  namespace: drone
roleRef:
  kind: Role
  name: drone-secrets-manager
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: docker-sock-access
rules:
- apiGroups: [""]
  resources: ["nodes/proxy"]
  verbs: ["get", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: drone-docker-access
subjects:
- kind: ServiceAccount
  name: drone-ci
  namespace: drone
roleRef:
  kind: ClusterRole
  name: docker-sock-access
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: drone-ci-role
  namespace: dev  # 注意:需要与测试用例部署的namespace一致
rules:
- apiGroups: ["apps", ""]
  resources: ["deployments", "pods", "services"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: drone-ci-rolebinding
  namespace: dev # 注意:需要与测试用例部署的namespace一致
subjects:
- kind: ServiceAccount
  name: drone-ci
  namespace: drone
roleRef:
  kind: Role
  name: drone-ci-role
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: drone-config
  namespace: drone
data:
  DRONE_GITEE_CLIENT_ID: "xxxxxxxxx" #自行修改
  DRONE_GITEE_CLIENT_SECRET: "xxxxxxxxxx" #自行修改
  DRONE_GITEE_SECRET:"xxxxxxxxxx"  #自行修改,可选配置
  DRONE_RPC_SECRET: "sdsgrgty54t4rereer"
  DRONE_SERVER_HOST: "drone.fzwtest.xyz"
  DRONE_SERVER_PROTO: "https"
  DRONE_SERVER_PORT: ":80"
  DRONE_LOGS_DEBUG: "true"
  DRONE_USER_CREATE: "username:fan-zhiwei1211_admin,admin:true"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: drone-ingress
  namespace: drone
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - drone.fzwtest.xyz
      secretName: drone-tlss
  rules:
    - host: drone.fzwtest.xyz
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: drone-server
                port:
                  number: 80
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: drone-pvc
  namespace: drone
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: drone-server
  namespace: drone
spec:
  replicas: 1
  selector:
    matchLabels:
      app: drone-server
  template:
    metadata:
      labels:
        app: drone-server
    spec:
      serviceAccountName: drone-ci
      containers:
      - name: drone-server
        image: drone/drone:2.17
        envFrom:
        - configMapRef:
            name: drone-config
        securityContext:
            runAsUser: 0
            capabilities:
                add: ["NET_BIND_SERVICE"]  # 允许绑定特权端口
        ports:
        - containerPort: 80
        volumeMounts:
        - name: drone-data
          mountPath: /data
      volumes:
      - name: drone-data
        persistentVolumeClaim:
          claimName: drone-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: drone-server
  namespace: drone
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http
  - port: 443
    targetPort: 443
    name: https
  selector:
    app: drone-server

Drone Runner

复制代码
apiVersion: v1
kind: Secret
metadata:
  name: acr-plaintext-secret
  namespace: dev  # 按需修改命名空间
type: kubernetes.io/dockerconfigjson
stringData:  # 注意这里使用 stringData 而非 data
  .dockerconfigjson: |
    {
      "auths": {
        "crpi-d7xhghcft4dbtjor.cn-beijing.personal.cr.aliyuncs.com": {
          "username": "xxxx", #容器仓库鉴权,自行修改
          "password": "xxxxxxx", #容器仓库鉴权,自行修改
          "auth": "xxxxxxxx" #容器仓库鉴权,自行修改
        }
      }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: drone-runner
  namespace: drone
spec:
  replicas: 1
  selector:
    matchLabels:
      app: drone-runner
  template:
    metadata:
      labels:
        app: drone-runner
    spec:
      serviceAccountName: drone-ci
      containers:
      - name: drone-runner
        image: drone/drone-runner-kube:latest
        env:
        - name: DRONE_RPC_HOST
          value: "drone-server.drone.svc.cluster.local"  # K8S 内部 Service 地址
        - name: DRONE_RPC_SECRET
          valueFrom:
            configMapKeyRef:
              name: drone-config
              key: DRONE_RPC_SECRET
        - name: DRONE_RUNNER_CAPACITY
          value: "2"
        - name: DRONE_RUNNER_PRIVILEGED_IMAGES
          value: "plugins/docker,appleboy/drone-docker"

部署到Kubernetes中,确保服务运行正常:

kubectl get pod -n drone

NAME READY STATUS RESTARTS AGE

drone-runner-f5cd6496b-s7wbl 1/1 Running 0 31s

drone-server-6c6d4d778b-5tzrv 1/1 Running 0 33s

3.3 初始化Drone Web UI

登录Drone的域名 https://drone.fzwtest.xyz/ 并同意授权,进入操作页面

可以点击SYNC同步仓库,点击我们的示例仓库,激活CI&CD集成

可以添加自己需要的Secrets,用来.drone.yml的参数调用。例如我们示例中的DOCKER_USERNAME和DOCKER_PASSWORD以及ssh_private_key

3.4 测试

现在提交代码到dev分支,会看到自动触发了CI&CD流程,并且能看到.drone.yml中定义的几个step的执行日志。

查看我们的测试服务已经成功部署

kubectl get pod -n dev

NAME READY STATUS RESTARTS AGE

fund-distribution-9478b5f84-825h7 1/1 Running 0 28m

相关推荐
程思扬2 小时前
开源 + 实时 + 无网络限制:Excalidraw 是流程图协作新选择
网络·人工智能·阿里云·ai·开源·流程图
刘一说2 小时前
Spring Boot 应用的云原生 Docker 化部署实践指南
spring boot·docker·云原生
zhangfeng11332 小时前
学习文本大模型的学习路径,各种大模型对比和分类以及各个大模型对硬件的要求,开源大模型有哪些
学习·分类·开源
❀͜͡傀儡师2 小时前
docker部署开源监控软件hertzbeat
docker·容器·开源·hertzbeat
想用offer打牌3 小时前
修复seata的HikariCP中加载驱动程序类的问题
后端·架构·开源
酷柚易汛智推官3 小时前
阿里“千问”破局C端AI:开源基石与B端势能的双重革命
人工智能·开源·酷柚易汛
paopao_wu3 小时前
DeepSeek-OCR实战(05):DeepSeek-OCR-WebUI部署(Docker)
docker·ai·容器·ocr
Wang's Blog3 小时前
K8S R&D: Kubernetes从集群安全、调度、扩展到监控形成完整技术体系
安全·kubernetes
❀͜͡傀儡师4 小时前
Docker 部署 DeepSeek-OCR 和WebUI
docker·容器·ocr