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

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

  • 从GitLabCE CI/CD方法论中探索实践

  • GitLab与Kubernetes实践篇·K8s内部署GtiLab

  • GitLab与Kubernetes实践篇·K8s内部署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 CICD与Kubernetes实践·部署Flask Web服务_第1张图片 Gitlab平台上配置Runner环境变量

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

查看效果

master分支变化

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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第2张图片 master分支变化时Gitlab CI Pipeline

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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第3张图片 其他分支变化时Gitlab CI Pipeline

其他分支

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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第4张图片 其他分支变化时包含deploy_review与stop_review

deploy_review

GitLab CICD与Kubernetes实践·部署Flask Web服务_第5张图片 deploy_review任务执行日志

stop_review

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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第6张图片 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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第7张图片 创建Tags后触发的Gitlab CI Pipeline

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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第8张图片 稳定版本Tags后上线日志

查看一下创建的服务

GitLab CICD与Kubernetes实践·部署Flask Web服务_第9张图片 查看服务的运行状态

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

GitLab CICD与Kubernetes实践·部署Flask Web服务_第10张图片 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

    • ???? GitlabCI与Kubernetes实践·部署GitLab-Runner

    • ???? Gitlab CICD 与Kubernetes实践·部署GitLab

    • ???? 从GitLabCE CI/CD方法论中探索实践

    • ???? 15 个 Kubectl 现有命令使用技巧 - 拿来即用

    • ???? Jenkins在kubernetes上的初体验

    • ???? 走进Network Namespace学会容器网络调试

    • ???? 实践 | Kubernetes守护进程集之DaemonSet

    • ???? 神奇!如何快速成为一名优秀的YAML工程师?

    • ???? 最流行的五款Kubernetes交互式可视化工具

    • ???? ab压力测试模拟实现kubernetes Pod水平自动伸缩

    • ???? 用Prometheus对业务服务进行监控

    • ???? Prometheus监控系列-监控篇

    • ???? kubernetes炼气期之掌握Kubernetes的背景

    • ???? Prometheus监控系列-部署篇

    • ???? 2020年最高效的10款Kubernetes助力神器

    • ???? 写给孩子看的Kubernetes动画指南 

    • ???? kubernetes的ingress控制器比较(traefik2.0.5安装指南)

    • ???? kubernetes深度探究Node和Pod的亲和性和反亲和性

    • ???? 在kuebernetes上通过nfs-server持久化postgresql

    • ???? kubernetes监控架构核心组件Metrics-server

    • ???? 基于BasicAuth认证的Traefik2.0.5

    • ???? 在Kubernetes上部署Nginx Ingress controller

    • ???? kubernetes安装方案大全

    • ???? kubernetes最常用的资源对象Deployment

    • ???? kubernetes炼气期之掌握kuebernetes背景

    • ???? kubernetes炼气期之k8s平台快速搭建

    • ???? 二进制部署Kubernetes集群1.9版本

你可能还喜欢

点击下方图片即可阅读

GitLab CICD与Kubernetes实践·部署Flask Web服务_第11张图片

Gitlab CICD与Kubernetes实践·部署Gitlab Runner

你可能感兴趣的:(kubernetes,docker,gitlab,gwt,单元测试)