【GitLab系列三】K8s集群内使用GitLab Pipeline编译、构建、发布Flask Web服务

上篇Gitlab CICD 与Kubernetes实践·部署GitLab文章内通过Kubernetes已经完成Gitlab Runner的部署的,现在我通过一个实际的案例来测试和使用Gitlab Runner在持续集成方面的优势。

服务背景

通过Gitlab CI完成Flask web Service服务代码风格检查、单元测试、打包、发布到k8s环境里面,同时我们会在.gitlab-ci.yml文件中配置基于分支branchtag的匹配执行相应的操作任务。Flask web Service是一个带有web登录界面的服务,服务运行的端口为5000,下面是该服务构建Docker镜像的Dockerfile

FROM python:3.4

COPY . /skeleton
WORKDIR /skeleton
RUN pip install -r requirements.txt -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com # 配置pip源,加速下载
EXPOSE 5000
ENTRYPOINT ["sh", "scripts/dev.sh"]

定义.gitlab-ci.yml

然后为项目准备.gitlab-ci.yml文件,这个文件稍微有点长,可以通过远程调用模板库的方式优化配置,此处我们不在多说:

stages: # 此处分为五个阶段,按顺序执行对应的环节
  - style
  - test
  - release
  - review
  - deploy

pep8: # pep8是自定义命名的jobs
  image: python:2.7 # 指定下面script块的指令在哪个镜像运行的容器环境内运行
  stage: style # 声明该pep8的job是属于哪个stage阶段运行
  script: # 该阶段执行的操作,其实就像在terminal里面执行命令一样。
    - pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com tox
    - tox -e pep8 # 使用tox命令进行pep8代码格式检查规范性检查,配置文件为当前项目下的tox.ini

unittest-py2.7:
  image: python:2.7
  stage: test
  script:
    - pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com tox
    - tox -e py27 # 指定使用py27虚拟环境

unittest-py3.4:
  image: python:3.4
  stage: test
  script:
    - pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com tox
    - tox -e py34 # 指定使用py34虚拟环境

buildimage:
  image: docker:latest # 该环节需要构建镜像,需要docker二进制命令,所以指定一个docker镜像
  variables: # 给buildimage这个job传递的变量
    DOCKER_DRIVER: overlay
    DOCKER_HOST: tcp://localhost:2375 # 与service指定容器通信
  services:
    - name: docker:17.03-dind
      command:
          - "--registry-mirror=https://*****.mirror.aliyuncs.com" # 配置镜像加速,当登录私有镜像仓库的时候,如果仓库的证书不受信任,可以在下方添加`--insecure-registry=*****`选项
  stage: release
  script:
    - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" ${CI_REGISTRY_REPO_URL} # 登录私有或者共有镜像仓库
    - docker build -t "${CI_REGISTRY_IMAGE}:latest" -f ./Dockerfile . # 构建镜像
    - docker tag "${CI_REGISTRY_IMAGE}:latest" "${CI_REGISTRY_REPO_URL}/${CI_REGISTRY_NAMESPACE}/${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}" # 给镜像打个推送到镜像仓库的地址
    - test ! -z "${CI_COMMIT_TAG}" && docker push "${CI_REGISTRY_REPO_URL}/${CI_REGISTRY_NAMESPACE}/${CI_REGISTRY_IMAGE}:latest" # 判断CI_COMMIT_TAG是否存在
    - docker push "${CI_REGISTRY_REPO_URL}/${CI_REGISTRY_NAMESPACE}/${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}" # 推送到镜像仓库

deploy_review:
  image: bitnami/kubectl # 该环节需要创建k8s资源,需要kubectl二进制命令
  stage: review
  only:
    - branches # 该stage直对分支有效
  except:
    - tags # 创建tags该stage不被执行
  environment: # 定义jobs将被部署在的环境,如果没有将会被指定,keyword(name,url,kubernetes...)
    name: dev
    url: https://dev-gitlab-k8s-demo.c33a5017db3924e7a86deeeaca6a706b8.cn-beijing.alicontainer.com
    on_stop: stop_review # 定义stop的时候执行的jobs
  script:
    - kubectl version
    - cd manifests/
    - sed -i "s/__CI_ENVIRONMENT_SLUG__/${CI_ENVIRONMENT_SLUG}/" deployment.yaml ingress.yaml service.yaml
    - sed -i "s/__VERSION__/${CI_COMMIT_REF_NAME}/" deployment.yaml ingress.yaml service.yaml
    - |
      if kubectl apply -f deployment.yaml | grep -q unchanged; then
          echo "=> Patching deployment to force image update."
          kubectl patch -f deployment.yaml -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"ci-last-updated\":\"$(date +'%s')\"}}}}}"
      else
          echo "=> Deployment apply has changed the object, no need to force image update."
      fi
    - kubectl apply -f service.yaml || true
    - kubectl apply -f ingress.yaml
    - kubectl rollout status -f deployment.yaml
    - kubectl get all,ing -n devops
  when: manual

stop_review:
  image: bitnami/kubectl
  stage: review
  variables:
    GIT_STRATEGY: none # 声明此jobs不会再做代码的check out
  when: manual # 手动触发是否继续执行
  only:
    - branches
  except:
    - master # 除了master分支与tags的变化
    - tags
  environment:
    name: dev
    action: stop
  script:
    - kubectl version
    - kubectl delete ing -l ref=${CI_ENVIRONMENT_SLUG}
    - kubectl delete all -l ref=${CI_ENVIRONMENT_SLUG}

deploy:
  image: bitnami/kubectl
  stage: deploy
  environment:
    name: live
    url: https://${$CI_ENVIRONMENT_SLUG}.****.cn-beijing.alicontainer.com # 服务的访问域名
  only:
    - tags
  when: manual
  script:
    - kubectl version
    - cd manifests/
    - sed -i "s/__CI_ENVIRONMENT_SLUG__/${CI_ENVIRONMENT_SLUG}/" deployment.yaml ingress.yaml service.yaml
    - sed -i "s/__VERSION__/${CI_COMMIT_REF_NAME}/" deployment.yaml ingress.yaml service.yaml
    - kubectl apply -f deployment.yaml
    - kubectl apply -f service.yaml
    - kubectl apply -f ingress.yaml
    - kubectl rollout status -f deployment.yaml
    - kubectl get all,ing -l ref=${CI_ENVIRONMENT_SLUG}

上面便是运行Flask web service的Gitlab持续构建持续部署的配置文件,配置文件中主要是.gitlab-ci.yaml的语法到诸多的配置环境变量,需要仔细的阅读和掌握才能很好的玩转CI.

K8s资源对象声明

正如上面看到的,k8s的资源定义文件在项目.gitlab-ci.yml同级目录manifests内

🐳 👉 ls
README.md       deployment.yaml ingress.yaml    service.yaml

服务部署的配置文件deployment.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitlab-k8s-demo-__CI_ENVIRONMENT_SLUG__
  namespace: devops
  labels:
    app: gitlab-k8s-demo
    ref: __CI_ENVIRONMENT_SLUG__
    track: stable
spec:
  replicas: 2
  selector:
    matchLabels:
      app: gitlab-k8s-demo
      ref: __CI_ENVIRONMENT_SLUG__
  template:
    metadata:
      labels:
        app: gitlab-k8s-demo
        ref: __CI_ENVIRONMENT_SLUG__
        track: stable
    spec:
      imagePullSecrets:
        - name: myregistry
      containers:
      - name: app
        image: registry.cn-beijing.aliyuncs.com/*****/gitlab-ci-flaskapp-test:__VERSION__ # 前面是镜像的地址
        imagePullPolicy: Always
        ports:
        - name: web
          protocol: TCP
          containerPort: 5000 # flask web service暴露的端口
        livenessProbe:
          httpGet:
            path: /
            port: 5000
          initialDelaySeconds: 3
          timeoutSeconds: 2
        readinessProbe:
          httpGet:
            path: /
            port: 5000
          initialDelaySeconds: 3
          timeoutSeconds: 2

Flask web service暴露的svc资源对象声明:

apiVersion: v1
kind: Service
metadata:
  name: gitlab-k8s-demo-__CI_ENVIRONMENT_SLUG__
  namespace: devops
  labels:
    app: gitlab-k8s-demo
    ref: __CI_ENVIRONMENT_SLUG__
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "5000"
    prometheus.io/scheme: "http"
    prometheus.io/path: "/"
spec:
  type: ClusterIP
  ports:
    - name: http-metrics
      port: 5000
      protocol: TCP
  selector:
    app: gitlab-k8s-demo
    ref: __CI_ENVIRONMENT_SLUG__

Flask web service暴露的外网访问的资源对象ingress声明:

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gitlab-k8s-demo-__CI_ENVIRONMENT_SLUG__
  namespace: devops
  labels:
    app: gitlab-k8s-demo
    ref: __CI_ENVIRONMENT_SLUG__
  annotations:
    nginx.ingress.kubernetes.io/service-weight: ''
spec:
  rules:
  - host: __CI_ENVIRONMENT_SLUG__-gitlab-k8s-demo.****.cn-beijing.alicontainer.com
    http:
      paths:
      - path: /
        backend:
          serviceName: gitlab-k8s-demo-__CI_ENVIRONMENT_SLUG__
          servicePort: 5000

配置Runner环境变量

上面的.gitlab-ci.yml中引用的变量就是从这里配置的,变量分为项目变量,gitlab group级别的,具体按需使用

Gitlab平台上配置Runner环境变量

配置完成之后就可以使用了。

查看效果

master分支变化

将代码推送到master分支,gitlab会自动的创建一个pipeline交由gitlab runner,当master分支发生变化时,CI的效果图如下:

master分支变化时Gitlab CI Pipeline

切换到一个新的分支上feature-01上看下CI会执行那些jobs,如下图,可以在.gitlab-ci.yaml中通过only/except按需定义。

其他分支变化时Gitlab CI Pipeline

其他分支

在Review环节需要手动的触发,当结果没有问题之后,就可以手动触发stop_review删除部署测试服务

其他分支变化时包含deploy_review与stop_review

deploy_review

deploy_review任务执行日志

stop_review

然后我们手动的触发stop_review删除刚才部署的已经没用的测试环境

stop_review执行日志

创建Tags

git tag v2.0
🐳 👉 git push origin --tags                
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To http://code.*******.cn-beijing.alicontainer.com/root/flask-ci-demo.git
 * [new tag]         v2.0 -> v2.0

当推送一个新的tag到gitlab之后,就会触发一个pipeline,匹配到那个tag的jobs

创建Tags后触发的Gitlab CI Pipeline

这说明是一个比较稳定的可以上线的版本了,

稳定版本Tags后上线日志

查看一下创建的服务

查看服务的运行状态

然后我们访问一下服务,查看是否可以正常使用

Flask web服务登录后的界面

可以正常登录并且显示如下表示服务运行成功了,测试到这里,基本上通过实践操作说清楚.gitlab-ci.yml里面配置的各项指令含义以及通过Gitlab CI pipeline进行持续集成、持续部署、持续交付等实践。如果有什么不清楚的,大家可以留言,我们一起交流学习。

云原生生态圈版权声明:
作者:云原生生态圈
文章标题: 【GitLab系列三】K8s集群内使用GitLab Pipeline编译、构建、发布Flask Web服务
链接:https://devopsman.cn/archives/121
来源:云原生生态圈
投稿联系: cloud.native@qq.com 文章版权归作者所有,未经允许请勿转载。
THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录