专栏首页云原生生态圈GitLab CICD与Kubernetes实践·部署Flask Web服务

GitLab CICD与Kubernetes实践·部署Flask Web服务

上篇?Gitlab CICD 与Kubernetes实践·部署GitLab Runner文章内通过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.*******.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 service.yaml ingress.yaml
    - kubectl rollout status -f deployment.yaml
    - kubectl get all,ing -l ref=${CI_ENVIRONMENT_SLUG}

上面便是运行Flask web service的Gitlab持续构建持续部署的配置文件,配置文件中主要是.gitlab-ci.yaml的语法[1]到诸多的配置环境变量[2],需要仔细的阅读和掌握才能很好的玩转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进行持续集成、持续部署、持续交付等实践。如果有什么不清楚的,大家可以留言,我们一起交流学习。

参考资料

[1]

gitlab-ci reference: https://docs.gitlab.com/ee/ci/yaml/README.html

[2]

runner variables: https://docs.gitlab.com/ee/ci/variables/README.html

本文分享自微信公众号 - 云原生生态圈(CloudNativeEcoSystem),作者:Marionxue

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ​GoLANG IN ACTION 2020

    因为头脑发热选择go语言?我想可能不是,在经过一系列的了解和调研后,我是认真的选择了golang, 当Rob Pike不满C++委员会要新添加35中新特性之后,...

    公众号: 云原生生态圈
  • Kubenretes上运行Prometheus联邦集群

    当我们有多个Kubernetes集群的时候,这个时候就需要需要指标汇总的需求了,如上图一样,我们假定在外部部署一个Prometheus的Federate,然后去...

    公众号: 云原生生态圈
  • 从GitLabCE CI/CD方法论中探索实践

    软件开发的连续方法基于自动执行脚本,以最大程度地减少在开发应用程序时引入错误的机会。从开发新代码到部署新代码,他们几乎不需要人工干预,甚至根本不需要干预。

    公众号: 云原生生态圈
  • 什么是响应式编程?

    本文来源:https://blog.csdn.net/get_set/article/details/79455258

    Java3y
  • 关于写作那些事之我该选择哪种格式 原

    不知道你是否留意过平时写作时的编辑器,有的是 markdown 编辑器,有的是各种富文本编辑器,到底选择哪一个相信你有自己的判断.

    雪之梦技术驿站
  • PDF翻译神器,再也不担心读不懂英文Paper了

    如果你经常跟文献打交道,那你应该切身体验过那种令人抓狂的心情:流畅地阅读 PDF 外文文献,必要情况下还得逐字逐句地翻译出来。

    AI科技大本营
  • highlight.js 在 Vue 中使用的一点儿经验

    overtrue
  • Spring Boot 与 Kotlin使用Freemarker模板引擎渲染web视图

    Web相关的介绍这里就不多阐述,还没了解的请移步《Spring Boot 与 Kotlin 使用Thymeleaf模板引擎渲染web视图》

    全科
  • 一个可以解析嵌套IIF语句的代码

    不太常用,对于一些IIF表达式,需要转换成sql server支持的格式,就写了这个转换。反复调试之后,就可以支持嵌套的调用了。 /// <summary>  ...

    用户1075292
  • Spring Boot 与 Kotlin 使用JdbcTemplate连接MySQL

    之前介绍了一些Web层的例子,包括构建RESTful API、使用Thymeleaf模板引擎渲染Web视图,但是这些内容还不足以构建一个动态的应用。通常我们做A...

    全科

扫码关注云+社区

领取腾讯云代金券