【Devops】 发布一个Python项目(Flask服务后端)到K8S环境

摘要:
前言:我有一段时间没有更新我的博客了。今天,我想与您分享如何在K8S环境中成功部署和运行python项目。我想做一个记录准备。containerPort容器暴露的访问端口。注意,这是在容器内,可以随机定义。但是,必须确保服务和地址之间的一致性

前言:

有一段时间没有更新博客了,今天给大家分享一下如何将一个python项目成功部署并运行到K8S环境,特做一个记录

准备工作

1. 编写一个python项目,我这边提供的一个Flask服务,提供接口的mock能力。(项目里面编写如下文件)

  1. dockerfile
  2. jenkinsfile
  3. deploy文件夹(内含: deploy.yaml   service.yaml   ingress.yaml)

流程简释:

jenkinsFile 执行流水线语法---打包docker镜像---把镜像发布到K8s环境(这里用到了deploy的三个文件: deploy,servic,ingress)

必备文件介绍

1. jenkinsFile  【我这里给出的是一个示例,实际要按自己公司的需求和情况来进行部署】

@Library('devops') 指代的是调用的K8S 第三方库(这个用流水线的公司都会提供,发布是基于这个库进行)
agent 指代发布的机器使用的是集群里面的slave 标签的机器
options 指代jenkins 的一些配置,例如30分钟超时,连接的代码库是(SVN、git、gitlab等等)
env 指代发布的时候使用到的一些环境变量,包括发布分支,镜像路径等信息
stage 指代jenkins发布的各个阶段
@Library('devops') _

String BUILD_RESULT = ""
String RELEASE_BUILD=""
pipeline {
    agent {
        label 'slave'
    }
    options {
        buildDiscarder(logRotator(numToKeepStr: '10'))
        disableConcurrentBuilds()
        skipDefaultCheckout()
        timeout(time: 30, unit: 'MINUTES')
        gitLabConnection('gitlab')
    }
    environment {
        IMAGE_CREDENTIALS = "credential-harbor"
        NOTIFY_ACCOUNT= "123456"
        DEV_BRANCH="dev"
        QA_BRANCH="v.*"
        IMAGE_REPOSITORY = "harbor.123.cn/test/mock"
        BUILD_CONTEXT="build"
    }

    stages {

        stage('Checkout') {

            steps {
                script {
                        container('tools') {
                            // checkout code
                            retry(2) { scmVars = checkout scm }
                            env.RELEASE_BUILD = scmVars.GIT_COMMIT
                            BUILD_RESULT = devops.updateBuildTasks(BUILD_RESULT,"Checkout OK...√")
                            echo 'begin checkout...'
                            echo sh(returnStdout: true, script: "env")

                    }
                }
            }
        }

        stage('build-mock-image') {

            steps {
                script {
                        container('tools') {
                            retry(2) {
                                sh """
                                        mkdir -p ${BUILD_CONTEXT};
                                     """
                            }
                            devops.dockerBuild(
                                    "Dockfile", //Dockerfile
                                    ".", // build context
                                    "${IMAGE_REPOSITORY}", // repo address
                                    env.RELEASE_BUILD, // tag
                                    IMAGE_CREDENTIALS, // credentials for pushing
                                ).start().push()
                        }
                }
            }
        }
        stage('deploy-mock') {
            when {
               expression { BRANCH_NAME ==~ env.DEV_BRANCH || BRANCH_NAME ==~ env.QA_BRANCH }
           }
            steps {
                script {
                    container('tools') {
                            //create configmap and ingress
                        devops.deploy("", "deploy/ingress.yaml","",false).start()
                        devops.deploy(
                                "deploy", //k8s files dir
                                "deploy/deploy.yaml",
                                RELEASE_BUILD,
                                true
                        ).start()
                    }
                }
            }
        }
    }
    post {
        success {
                script {
                    container('tools') {
                        devops.notificationSuccess("mock", "流水线完成了", RELEASE_BUILD, "dingTalk")
                    }
                }
            }
        failure {
                script {
                    container('tools') {
                        devops.notificationFailed("mock", "流水线失败了", RELEASE_BUILD, "dingTalk")
                    }
                }
            }
    }

}

2. dockerFile 【制作docker镜像文件,也是一个示范,实际情况实际分析】

 基础镜像使用 -silim 能有效缩减镜像大小 (700-900Mb 缩小到200多Mb 的区别)

ADD ./requirements.txt /src/requirements.txt
RUN pip --default-timeout=30 install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt
这里先把依赖文件复制过去,后续会读取这个缓存文件进行依赖安装,如果你的requirements 没有改动,则不会触发下载安装,能有效减少发布时间(很多公司的linux机器网络速度很慢)
后面指定了国内镜像,也是为了加快依赖的下载速度

运行项目可以不执行,因为你发布到K8S, 在deploy.yaml里面一定要执行镜像运行方式

注意:
获取requirements文件的方法: pipreqs . (pip install pipreqs)
# 基于的基础镜像
FROM python:3.7.5-slim
 
#制作者信息
MAINTAINER XXXX
 
#设置工作目录
WORKDIR /src

# 利用缓存安装依赖,设置requirements
ADD ./requirements.txt /src/requirements.txt
RUN pip --default-timeout=30 install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt

# 复制项目到镜像工作目录
ADD . /src
 
# 给镜像下的项目文件赋权
RUN chmod a+x /src/*

# 运行项目
CMD python /src/run.py

3. deploy.yaml  【K8S的入口文件,也是核心发布文件,必需】

namespace 你想发布到K8S的 命名空间
app:mock  你发布的项目名称(在k8s里面显示的deploy名称)
command: ["/bin/sh"]
args: ["-c","python /src/run.py"]
----------程序运行命令, 指的是在镜像里面执行的操作,注意python和java的区别即可。

containerPort 容器暴露的访问端口,注意这是容器内的,随便定义,但是要保证service、ingress 里面保持一致性,程序启动端口也要用这个。否则无法访问
resources 设置了内存和CPU的限制, 这里按机器的实际情况进行设置
image 镜像名称
 
 
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: {{NAMESPACE}}
  name:mock
  labels:
    app:mock
spec:
  minReadySeconds: 10
  progressDeadlineSeconds: 20
  strategy:
    rollingUpdate:
      maxSurge: 1
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app:mock
  template:
    metadata:
      labels:
        app:mock
    spec:
      dnsConfig:
        options:
        - name: single-request-reopen
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: {{NODE_LABEL_KEY}}
                operator: In
                values:
                - "{{NODE_LABEL_VAL}}"
      restartPolicy: Always
      volumes:
      containers:
      - name: mock
        image: {{imageUrl}}
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh"]
        args: ["-c","python /src/run.py"]
        ports:
        - containerPort: 9900 
        resources:
          requests:
            memory: "1024Mi"
            cpu: "500m"
          limits:
            memory: "8192Mi"
            cpu: "4000m"

4. service.yaml 【K8S提供集群内服务访问的文件,开放服务给其他项目调用,必需】

K8S集群调用方式:  mock:9900 即----   serviceName:port

kind: Service
apiVersion: v1
metadata:
  name: mock
  namespace: {{NAMESPACE}}
spec:
  selector:
    app: mock
  ports:
  - protocol: TCP
    port: 9900
    targetPort: 9900

5. ingress.yaml 【K8S集群提供的外部访问域名文件,用于外部用户通过域名访问服务,非必需】

这里我加入了tls 配置(HTTPS证书访问),secretName为K8S集群里面已存在的证书名称,域名保持一致即可

注意服务名和端口需要和service.yaml对应,即可通过域名访问到服务,如下,通过  mock.test.cn 即可访问mock服务了。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: mock
  namespace: {{NAMESPACE}}
spec:
  tls:
    - hosts:
        - mock.test.cn
      secretName: test-cn
  rules:
  - host: mock.test.cn
    http:
      paths:
        - backend:
            serviceName: mock
            servicePort: 9900
          path: /

三、可能遇到的问题

1. Nginx 报错 :

解决:  python程序、deploy、service、ingress的端口保持一致性

另外: Flask 暴露的HOST=“0.0.0.0”

[error]  *97421558 connect() failed (111: Connection refused) while connecting to upstream, client: 1.1.1.1, server:mock.test.cn, request: "GET /api?taskId=1234 HTTP/1.1", upstream: "http://127.0.0.0:9900/api-waf?taskId=1234", host: "mock.test.cn"

2. 发布到不同分支:

确保你在jenkinsFile 设置了不同分支的名称, 例如你从  dev分支打包, tag是v1.0.0 那么用正则表达式:  dev|v.*  可同步发布到test和dev环境

免责声明:文章转载自《【Devops】 发布一个Python项目(Flask服务后端)到K8S环境》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇必应词典使用体验及改进建议nginx基于TCP的反向代理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python轻量级orm框架 peewee常用功能速查

peewee常用功能速查 peewee 简介 Peewee是一种简单而小的ORM。它有很少的(但富有表现力的)概念,使它易于学习和直观的使用。 常见orm数据库框架 Django ORM peewee SQLAlchemy Django ORM 优点:易用,学习曲线短和Django紧密集合,用Django时使用约定俗成的方法去操作数据库缺点:Quer...

CentOS7 更换镜像源

1)先安装wget 执行命令 yum install -y wget[root@localhost ~]# yum install -y wget 2) 查询国内镜像源 打开阿里镜像http://mirrors.aliyun.com/点击帮助: 3)下载CentOS 7的repo文件wget -O /etc/yum.repos.d/CentOS-Base....

python常见错误记录

1. x^y x**y 2. range(a,b,c) http://www.runoob.com/python/python-func-range.html 以a为首项(默认从0开始),c为公差(默认为1)且不超过b-1的等差数列 3. lambda匿名函数 https://blog.csdn.net/liang19890820/article/det...

openstack 制作大于2TB根分区自动扩容的CENTOS镜像

制作镜像的时候默认分的是30G空间 qemu-img create -f raw centos.img 30G 看官网文档安装完系统需要安装cloud-init和clout-utils包,本人安装了完这个工具 但是发现启动系统以后,root根分区开机只能自动扩展到900G或者500G。 后来经查需要使用GPT分区,根分区才能到2TB空间。 于是从做镜像,...

Python的魔法函数

概要 如何定义一个类 类里通常包含什么 各个部分解释 类是怎么来的 type和object的关系 判断对象的类型 上下文管理器 类结构 #!/usr/bin/env python #-*- coding: utf-8 -*- #Author: rex.cheny #E-mail: rex.cheny@outlook.com #类名后面写(object...

记录k8s安装es

apiVersion: policy/v1beta1 kind: PodDisruptionBudget metadata: name: elasticsearch-pdb namespace: test spec: selector: matchLabels: app: elasticsearch maxUnavail...