美文网首页
flask项目使用Jenkins自动化部署到k8s集群

flask项目使用Jenkins自动化部署到k8s集群

作者: 惜鸟 | 来源:发表于2019-11-13 10:22 被阅读0次

    本项目是通过Jenkins自动化部署成功的,写此文的目的是为了记录该过程,方便以后查阅
    想将flask项目实现Jenkins自动化容器部署的同学可以参考此文

    一、flask项目结构

    flask项目结构

    二、各文件介绍

    1. 项目中 manage.py是flask项目在本地运行的启动文件,启动命令如下:

    python .\manage.py runserver
    

    其中manage.py的内容如下:

    # manage.py文件内容
    from flask_script import Manager
    from app import create_app
    
    
    app = create_app('default')
    manager = Manager(app=app)
    
    
    if __name__ == '__main__':
        manager.run()
    
    

    manage.py文件中的from app import create_app定义在app模块的__init__.py文件中,内容如下:

    from flask import Flask
    from flask_pymongo import PyMongo
    from config import config
    # 创建数据库
    mongo = PyMongo()
    
    
    def create_app(config_name):
        app = Flask(__name__)
        # 加载配置文件
        app.config.from_object(config[config_name])
        # 初始化数据库
        mongo.init_app(app)
        # 导入蓝图,在app目录下面建一个test模块
        from .test import blue as test_blueprint
        # 注册蓝图
        app.register_blueprint(test_blueprint, url_prefix='/api/v1')
    
        return app
    
    

    上面代码中的config模块的中config.py文件的内容如下:

    import os
    basedir = os.path.abspath(os.path.dirname(__file__))
    
    
    class Config:
        SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
        SSL_REDIRECT = False
        SQLALCHEMY_TRACK_MODIFICATIONS = False
        SQLALCHEMY_RECORD_QUERIES = True
        FLASKY_POSTS_PER_PAGE = 20
        FLASKY_FOLLOWERS_PER_PAGE = 50
        FLASKY_COMMENTS_PER_PAGE = 30
        FLASKY_SLOW_DB_QUERY_TIME = 0.5
    
        @staticmethod
        def init_app(app):
            pass
    
    
    class DevelopmentConfig(Config):
        DEBUG = True
        MONGO_URI = "mongodb://localhost:27017/myDatabase"
    
    
    class TestingConfig(Config):
        TESTING = True
        MONGO_URI = "mongodb://localhost:27017/myDatabase"
        WTF_CSRF_ENABLED = False
    
    
    class ProductionConfig(Config):
        DEBUG = True
        MONGO_URI = "mongodb://localhost:27017/myDatabase"
    
        @classmethod
        def init_app(cls, app):
            Config.init_app(app)
    
    
    class DockerConfig(ProductionConfig):
        @classmethod
        def init_app(cls, app):
            ProductionConfig.init_app(app)
    
            # log to stderr
            import logging
            from logging import StreamHandler
            file_handler = StreamHandler()
            file_handler.setLevel(logging.INFO)
            app.logger.addHandler(file_handler)
    
    
    config = {
        'development': DevelopmentConfig,
        'testing': TestingConfig,
        'production': ProductionConfig,
        'docker': DockerConfig,
        'default': DevelopmentConfig
    }
    
    

    上面代码中的test模块的__init__.py文件的内容如下:

    from flask import Blueprint
    
    blue = Blueprint('test', __name__)
    
    from . import test_api
    
    

    上面代码中的test_api就是test_api.py文件,内容如下:

    from . import blue
    from flask import jsonify, request
    from app import mongo
    
    res = {
        'code': 200,
        'msg': '成功',
        'success': True
    }
    
    error = {
        'code': 100,
        'msg': '出错了',
        'success': False
    }
    
    
    @blue.route('/test', methods=['GET'])
    def test():
        print(request.method)
        return jsonify(res)
    
    

    2. 项目中gunicorn.conf.py内容如下:

    workers = 5  # 定义同时开启的处理请求的进程数量,根据网站流量适当调整
    worker_class = "gevent"  # 采用gevent库,支持异步处理请求,提高吞吐量
    bind = "0.0.0.0:8888"  # 监听IP放宽,以便于Docker之间、Docker和宿主机之间的通信
    
    

    3. 项目中Dockerfile文件内容如下:

    FROM python:3.6
    COPY . /app
    WORKDIR /app
    RUN pip install --upgrade pip && pip install -i https://mirrors.aliyun.com/pypi/simple -r requirements.txt
    EXPOSE 5000
    CMD ["gunicorn", "manage:app", "-c", "./gunicorn.conf.py"]
    

    4. 项目中Jenkinsfile文件内容如下:

    pipeline{
          // 定义groovy脚本中使用的环境变量
          environment{
            // 镜像标签
            IMAGE_TAG =  sh(returnStdout: true,script: 'echo $image_tag').trim()
            // 镜像仓库地址
            ORIGIN_REPO =  sh(returnStdout: true,script: 'echo $origin_repo').trim()
            // 镜像仓库名称
            REPO =  sh(returnStdout: true,script: 'echo $repo').trim()
            // gitlab revision用于滚动更新镜像
            REVISION =  sh(returnStdout: true,script: 'echo $revision').trim()
            // 项目名称
            PROJECT_NAME = sh(returnStdout: true,script: 'echo $project_name').trim()
          }
    
          // 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
          agent{
            node{
              label 'slave-pipeline'
            }
          }
    
          // "stages"定义项目构建的多个模块,可以添加多个 “stage”, 可以多个 “stage” 串行或者并行执行
          stages{
        
            // 运行容器镜像构建和推送命令, 用到了environment中定义的groovy环境变量
            stage('Image Build And Publish'){
              steps{
                  container("kaniko") {
                      sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}"
                  }
              }
            }
    
    
            stage('Deploy to Kubernetes') {
                steps {
                    container('kubectl') {
                        step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG,REVISION,PROJECT_NAME'])
                    }
                }
            }
          }
        }
    
    

    5. 项目中deployment.yaml文件内容如下:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: ${PROJECT_NAME}
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: ${PROJECT_NAME}
      template:
        metadata:
          labels:
            app: ${PROJECT_NAME}
        spec:
          containers:
          - name: ${PROJECT_NAME}
            image: ${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}
            imagePullPolicy: Always
            ports:
            - containerPort: 8888
            env:
            - name: REVISION
              value: ${REVISION}
          imagePullSecrets:
          - name: wangdi-docker-password
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: ${PROJECT_NAME}-svc
      namespace: default
    spec:
      ports:
      - name: port
        port: 8500
        protocol: TCP
        targetPort: 8888
      selector:
        app: ${PROJECT_NAME}
      type: NodePort
    
    

    6. 项目中requirements.txt文件内容如下:

    flask
    flask-pymongo
    flask_script
    gunicorn
    gevent
    

    7. 项目中.gitignore文件内容如下:

    *.py[cod]
    
    # C extensions
    *.so
    
    # Packages
    *.egg
    *.egg-info
    dist
    build
    eggs
    parts
    bin
    var
    sdist
    develop-eggs
    .installed.cfg
    lib
    lib64
    __pycache__
    logdir
    
    # Installer logs
    pip-log.txt
    
    # Unit test / coverage reports
    .coverage
    .tox
    nosetests.xml
    
    # Translations
    *.mo
    
    # Mr Developer
    .mr.developer.cfg
    .project
    .pydevproject
    
    # SQLite databases
    *.sqlite
    
    # Virtual environment
    venv
    
    # Environment files
    .env
    .env-mysql
    .vscode
    

    三、部署项目

    将上面各文件创建好之后将代码提交到gitlab或者github上面,接下来开始实现自动化部署。

    1. 在k8s上面搭建jenkins,可以参考阿里云devops最佳实践

    2. Jenkins配置如下图

    • 在Jenkins中创建流水线


      在Jenkins中创建流水线
    • 给流水线设置初始化参数


      给流水线设置初始化参数
      给流水线设置初始化参数
      给流水线设置初始化参数
    • 开始参数化构建


      开始参数化构建
    • 构建成功


      构建成功
    • 在k8s集群查看运行的pod

    kubectl get pod
    
    pod运行成功

    四、总结

    这里完成了容器化devops的整个流程,项目的代码在github上面,点击这里查看。整个部署过程还是比较复杂的,需要对k8s和Jenkins都有了解才行,如果大家在实践过程中遇到问题欢迎留言,我们可以一起共同探讨解决问题。

    相关文章

      网友评论

          本文标题:flask项目使用Jenkins自动化部署到k8s集群

          本文链接:https://www.haomeiwen.com/subject/invqictx.html