zoukankan      html  css  js  c++  java
  • 容器云平台No.10~通过gogs+drone+kubernetes实现CI/CD

    什么是CI/CD

    持续集成(Continous Intergration,CI)是一种软件开发实践,即团队开发成员经常集成它们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都需要通过自动化的编译、发布、自动化回归测试来验证,从而尽快地发现集成错误。而这些自动化的操作则由CI软件进行执行。

    持续部署(Continous Delivery,CD)在持续集成的基础上,将集成后的代码部署到真实运行环境中(本文指部署到kubernetes集群)。交付团队 ->版本控制 ->构建和单元测试 ->自动验收测试 -> 发布

    什么是Drone

    Drone 是一个基于Docker容器技术的可扩展的持续集成引擎,用于自动化测试、构建、发布。每个构建都在一个临时的Docker容器中执行,使开发人员能够完全控制其构建环境并保证隔离。开发者只需在项目中包含 .drone.yml文件,将代码推送到 git 仓库,Drone就能够自动化的进行编译、测试、发布。

    使用drone实现CD/CD

    首先来看下丑陋的图

    简单梳理流程:

    1、开发人员向git(gitlab/github/gogs)提交代码,代码中必须包含Dockerfile和.drone.yml文件。
    2、将代码commit到远程仓库;发布应用时需要填写服务类型、服务名称、资源数量、实例个数等信息
    3、gogs触发drone自动构建
    4、Drone的CI流水线中包括了自定义脚本,根据准备好的kubernetes的YAML模板,将其中的变量替换成用户输入的选项
    生成应用的kubernetes YAML配置文件
    5、Drone的CI流水线自动编译代码并打包成docker镜像推送到Harbor镜像仓库
    6、更新DNS,插入一条DNS记录,IP地址是ingress节点的IP地址。
    7、Drone的CI流水线中自定义脚本调用kubernetes的API,部署应用;更新Ingress的配置,根据新部署的应用的名称,在ingress的配置文件中增加一条路由信息
    接下来,开始实战

    部署代码仓库gogs

    本文使用gogs,当然你可以选择gitlab,github等代码仓库
    1、创建gogs.yaml

    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: gogs
      labels:
        app: gogs
    spec:
      serviceName: gogs
      replicas: 1
      selector:
        matchLabels:
          app: gogs
      template:
        metadata:
          labels:
            app: gogs
        spec:
          terminationGracePeriodSeconds: 180
          containers:
          - name: gogs
            image: gogs/gogs
            imagePullPolicy: Always
            ports:
            - containerPort: 3000
              name: port
            - containerPort: 22
              name: ssh-port
            volumeMounts:
            - name: volume
              mountPath: /data
          volumes:
          - name: volume
            emptyDir: {}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: gogs
      labels:
        app: gogs
    spec:
      type: NodePort
      ports:
      - port: 3000
        targetPort: 3000
      selector:
        app: gogs
    

    2、执行部署并查看结果

    [root@k8s-node001 gogs]# kubectl  apply -f gogs.yaml 
    statefulset.apps/gogs created
    service/gogs created
    
    [root@k8s-node001 gogs]# kubectl  get po,svc -o wide 
    NAME         READY   STATUS    RESTARTS   AGE    IP               NODE          NOMINATED NODE   READINESS GATES
    pod/gogs-0   1/1     Running   0          2m2s   100.68.150.197   k8s-node001   <none>           <none>
    
    NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE     SELECTOR
    service/gogs         NodePort    10.106.102.74   <none>        3000:30526/TCP   2m3s    app=gogs
    

    3、浏览器打开,并配置gogs,然后就可以登录gogs了

    4、登录gogs

    至此,gogs配置完毕。
    Tips:本文的gogs,是测试环境,使用卷类型为:emptyDir,生产环境最好单独部署或者使用StorageClass保证数据持久可用性
    接下来部署drone

    部署CI工具Drone

    1、编写drone.yaml文件

    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: drone
      labels:
        app: drone
    spec:
      serviceName: drone
      replicas: 1
      selector:
        matchLabels:
          app: drone
      template:
        metadata:
          labels:
            app: drone
        spec:
          terminationGracePeriodSeconds: 180
          containers:
          - name: drone
            image: drone/drone:1
            imagePullPolicy: Always
            env:
              - name: DRONE_AGENTS_ENABLED
                value: "true"
              - name: DRONE_GOGS_SERVER
                value: http://192.168.100.181:30526/  # 注意这里填的是gogs的地址
              - name: DRONE_RPC_SECRET
                value: qawsedrftg
              - name: DRONE_SERVER_HOST
                value: drone.company.com
              - name: DRONE_SERVER_PROTO
                value: http
            ports:
            - containerPort: 80
              name: port
            - containerPort: 443
              name: ssl-port
            volumeMounts:
            - name: volume
              mountPath: /data
          volumes:
          - name: volume
            emptyDir: {}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: drone
      labels:
        app: drone
    spec:
      type: NodePort
      ports:
      - port: 80
        targetPort: 80
      selector:
        app: drone
    

    2、执行部署并查看结果

    [root@k8s-node001 drone]# kubectl  apply -f drone.yaml
    
    [root@k8s-node001 drone]# kubectl get po,svc  -o wide
    NAME          READY   STATUS    RESTARTS   AGE     IP   NODE          NOMINATED NODE   READINESS GATES
    pod/drone-0   1/1     Running   0          4m40s   100.68.150.198   k8s-node001   <none>           <none>
    
    NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE     SELECTOR
    service/drone        NodePort    10.100.77.138   <none>        80:31681/TCP     4m40s   app=drone
    

    3、现在就可以用浏览器访问http://192.168.100.181:31681 ,使用gogs的账号就可以登录drone了

    4、登录后可以看到,现在并没有任何项目,后续再gogs新建项目,就能看到了

    部署Drone Runner

    Runner的作用是询问Drone Server,然后执行pipeline,更多信息请查看官网
    1、编写drone-runner.yaml

    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      namespace: default
      name: drone
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - create
      - delete
    - apiGroups:
      - ""
      resources:
      - pods
      - pods/log
      verbs:
      - get
      - create
      - delete
      - list
      - watch
      - update
    ---
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: drone
      namespace: default
    subjects:
    - kind: ServiceAccount
      name: default
      namespace: default
    roleRef:
      kind: Role
      name: drone
      apiGroup: rbac.authorization.k8s.io
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: drone-runner
      labels:
        app.kubernetes.io/name: drone-runner
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: drone-runner
      template:
        metadata:
          labels:
            app.kubernetes.io/name: drone-runner
        spec:
          containers:
          - name: drone-runner
            image: drone/drone-runner-kube:latest
            ports:
            - containerPort: 3000
            env:
            - name: DRONE_RPC_HOST
              value: 192.168.100.181:31681  # Drone Server地址
            - name: DRONE_RPC_PROTO
              value: http
            - name: DRONE_RPC_SECRET
              value: qawsedrftg         # Drone Server部署时候填写的secret
    

    2、执行部署并查看结果

    [root@k8s-node001 drone]# kubectl  apply -f drone-runner.yaml
    
    [root@k8s-node001 drone]# kubectl  get po
    NAME                            READY   STATUS    RESTARTS   AGE
    drone-runner-7c64bffb45-dh2dn   1/1     Running   0          11m
    

    至此,实现CI/CD的环境都准备好了,现在来跑一个demo

    CI/CD示例

    1、gogs新建项目demo

    2、drone上点sync,就可以看到demo项目

    3、激活demo项目,保存

    4、在gogs的demo项目中,添加.drone.yml文件,添加一个pipeline

    5、提交代码,但是不触发CI,Commit的时候填写[CI SKIP]就可以跳过触发CI

    如果这里直接Commit提交代码,就直接触发CI功能,Drone就开始执行这个pipeline了
    [CI SKIP]的作用就是如果需要修改多个文件,这时候会很有用;
    当然在实际开发过程中,都是把项目clone到本地,编辑好所有文件,再push到代码仓库,这样就不需要[CI SKIP]了
    6、我们这里随便修改 README,然后知己commit,不是用[CI SKIP]看下效果

    7、执行结果,这里失败了,后面再解决

    8、如果您commit以后并没有触发Drone,需要在gogs查看webhooks时候正常,如下图

    9、这里我们来解决pipeline执行失败的问题
    我们通过drone界面可以看到项目pipeline报错如下,显示runner clone代码失败了

    Initialized empty Git repository in /drone/src/.git/
    + git fetch origin +refs/heads/master:
    fatal: unable to access 'http://192.168.100.181:3000/scofield/demo.git/': Failed to connect to 192.168.100.181 port 3000: Connection refused
    

    首先看下这个pipeline,很简单,使用镜像alpine执行两条输出语句

    kind: pipeline
    type: kubernetes
    name: default
    
    steps:
    - name: greeting
      image: alpine
      commands:
      - echo hello
      - echo world
    

    但是默认情况下,Drone执行pipeline之前会克隆项目,url就是gogs的http地址,这里是http://192.168.100.181:3000/scofield/demo.git 因为我这里测试环境使用NodePort暴露的服务,Drone需要使用http://192.168.100.181:30526/scofield/demo.git 这个地址才能克隆到项目,如果使用ingress暴露gogs服务,这个url就是域名而不是IP,就不会出现这个问题。
    那现在需要解决这个问题,我们就自定义clone,修改默认的克隆地址,修改如下,修改完直接commit代码,触发CI

    通过drone页面查看结果,可以看到clone成功

    而且执行的echo命令也成功执行

    至此本文实战结束

    总结

    本文是“基于Docker及Kubernetes构建的容器云平台”系列第十篇,也是最后一篇,如果您看完了整个系列文章,在此感谢。
    通过这十篇文章,您应该可以构建出一个测试环境的容器平台。关于容器云平台更多内容,后续会继续分享,尽请持续关注。

    PS:后续文章会同步到dev.kubeops.net

  • 相关阅读:
    footer在最低显示
    jQuery toast message 地址 使用
    linux 获取经过N层Nginx转发的访问来源真实IP
    Java Json格式的字符串转变对象
    多个机器获取微信access-token导致的有效性问题
    站点技术---301重定向
    C++技术问题总结-第8篇 STL内存池是怎么实现的
    IIS中遇到无法预览的问题(HTTP 错误 401.3
    梯度下降深入浅出
    COM-IE-(2)
  • 原文地址:https://www.cnblogs.com/scofield666/p/13716279.html
Copyright © 2011-2022 走看看