一、背景

记录一个Flask项目的快速交付的具体实现。所涉及的步骤为:

  • Dockerfile脚本编写
  • Helm Chart编写
  • Jenkins接入

参考地址:https://gitee.com/xiangys0134/deploy/tree/master/flask-demo

二、构建基础Docker镜像

参考地址:https://gitee.com/xiangys0134/deploy/blob/master/flask-demo/base_dockerfile/Dockerfile

# vim Dockerfile    # 添加如下内容
FROM python:3.8.17-alpine3.18
COPY requirements.txt /opt/requirements.txt
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r /opt/requirements.txt

# cat requirements.txt 
Flask==2.2.2

# docker build -t registry.cn-hangzhou.aliyuncs.com/xiangys0134/flask:2.2.2 .

三、测试Flask

# docker run -it registry.cn-hangzhou.aliyuncs.com/xiangys0134/flask:2.2.2 sh
# docker cp flaskweb1 gracious_wiles:/tmp        #另一个终端拷贝代码
/tmp/flaskweb1 # python -m flask run --host=0.0.0.0        #启动容器测试

# 备注:通过在容器中启动对应的python命令运行flask

四、编写应用Dockerfile

4.1 Dockerfile文件

# vim Dockerfile
FROM registry.cn-hangzhou.aliyuncs.com/xiangys0134/flask:2.2.2
# 镜像的作者 
LABEL maintainer="<250919938@qq.com>"

COPY . /app

ARG REGISTRY=https://pypi.org/simple

RUN pip install -i ${REGISTRY} -r /app/requirements.txt

WORKDIR /app

ENTRYPOINT ["python -m flask run --host=0.0.0.0"]

4.2 Build镜像

# docker build --build-arg REGISTRY="https://pypi.tuna.tsinghua.edu.cn/simple" -t registry.cn-hangzhou.aliyuncs.com/xiangys0134/app:frontend-api-v202307201044 .

# docker push registry.cn-hangzhou.aliyuncs.com/xiangys0134/app:frontend-api-v202307201045

# 网站项目参考地址:https://gitee.com/xiangys0134/deploy/tree/master/flask-demo/git

五、编写Helm

# helm create flask
# ll    # 查看内容
total 8
drwxr-xr-x 2 k8s-dev-test k8s-dev-test    6 Jul 20 10:11 charts
-rw-r--r-- 1 k8s-dev-test k8s-dev-test 1141 Jul 20 10:11 Chart.yaml
drwxr-xr-x 3 k8s-dev-test k8s-dev-test  193 Jul 20 13:56 templates
-rw-r--r-- 1 k8s-dev-test k8s-dev-test 3056 Jul 20 10:53 values.yaml

# 内容地址:https://gitee.com/xiangys0134/deploy/tree/master/flask-demo/flask

六、服务部署至k8s集群

6.1 手动部署

$ helm upgrade --install --namespace default --set image.tag=frontend-api-v202307201045 --set image.repository=registry.cn-hangzhou.aliyuncs.com/xiangys0134/app  --set replicaCount=1 frontend-api-flask .

# helm具体使用参考地址:https://helm.sh/zh/docs/

6.2 测试

# curl 192.168.7.45:31185/  # curl访问网站
Hello World!

七、Jenkins接入

7.1 构建镜像job

jenkins任务:test-demo-build,git分支:master

@Library('ops-pipline-library')_

def map = [:]
    // 自定义构建运行node节点环境,根据实际情况进行调整
    map.put('JENKINS_NODE','node1')
    // 应用的名称,最好与helm定义的应用一致
    map.put('APP_NAME','frontendapi')
    //认证仓库地址
    map.put('DOCKER_REGISTRY','https://registry.cn-shenzhen.aliyuncs.com')
    //镜像仓库认证key,需在jenkins中预先配置认证key
    map.put('DOCKER_REGISTRY_KEY','fb805ed9-7e7e-4c79-a9e4-325d5afacc7a')
    //应用仓库镜像,与镜像仓库地址一一对应
    map.put('DOCKER_IMG','registry.cn-shenzhen.aliyuncs.com/xiangys0134-dev/demo1-dev')
    //项目仓库地址,与GIT_KEY一一对应,如果要选择http/Https模式则GIT_KEY也同样需要调整
    map.put('GIT_URL','ssh://git@gitee.com/xiangys0134/deploy.git')
    //jenkins仓库认证key,对应GIT_URL
    map.put('GIT_KEY','e4bf623a-00e5-4169-68db-35be9ddc283e')
    // 编译目录及dockerfile build目录,根目录下则不填写。如果存在二级目录则写相对路径示例:abc/edb
    map.put('BUILD_DIR','flask-demo/git')
    // Dockerfile文件
    map.put('DOCKERFILE_NAME',"Dockerfile")
    // docker_build参数,示例:docker build --build-arg env=test -f Dockerfile
    map.put('DOCKER_BUILD_ARGS','--build-arg REGISTRY="https://pypi.tuna.tsinghua.edu.cn/simple" -f ')
    //编译命令,没有可以不填写
    map.put('BUILD_CMD',"")
   //触发多个job任务信息,release_dev|release_dev 必须与choices列表一一对应,否则报错
   //示例 map.put('DEPLOY_MAP','release_dev:yunwei_update_test,release_test:yunwei_update_test2')
    map.put('DEPLOY_MAP','release_dev:test-demo-update')
docker_img_build_base_v1(map)

7.2 部署至k8s集群

jenkins任务:test-demo-update,镜像tag:frontendapi-test-202307200536

...
# deploy
helm upgrade --install --atomic --reset-values --cleanup-on-fail --timeout 4m0s --namespace {namespace} \
--set image.repository='registry.cn-shenzhen.aliyuncs.com/xiangys0134-dev/demo1-dev' \
--set dockerbase64=dockerbase64 \
--set service.port=5000 \
--set service.targetport=5000 \
--set service.nodeport=31186 \
--set image.tag=release_tag \
--set resources.requests.cpu=200m \
--set resources.requests.memory=128Mi \
--set resources.limits.cpu=500m \
--set resources.limits.memory=512Mi \
--set livenessProbe.enabled=true \
--set readinessProbe.enabled=true \
--set livenessProbe.initialDelaySeconds=60 \
--set readinessProbe.initialDelaySeconds=60 \
--set livenessProbe.type=httpGet \
--set readinessProbe.type=httpGet \
--set livenessProbe.path=/ \
--set readinessProbe.path=/ \
--set replicaCount=1 \
--set lifecycle.preStop.exec.command[0]="/bin/sh" \
--set lifecycle.preStop.exec.command[1]="-c" \
--set lifecycle.preStop.exec.command[2]="sleep 10;" \
--set command="command" \
flask .
...

/* 备注:以上仅包含所用到的一些参数--set 只传递变量值,以下简单叙述部分功能
command         涉及程序的启动命令(可覆盖dockerfile的启动命令)
dockerbase64    涉及镜像仓库secret
service         涉及服务相关配置,默认为NodePort类型。可以指定对应service
resources       涉及分配的pod的cpu、内存资源
livenessProbe   涉及存活探测,默认为tcp探测
readinessProbe  同上
lifecycle       涉及pod的生命周期调用
其他:
nodeSelector    节点选择
tolerations     容忍度
pdb             干扰预算
ingress         涉及ingress7层负载
autoscaling     涉及pod水平自动扩缩
skywalking      涉及APM监控
*/

7.3 yaml信息

[k8s-dev-test@rancher-k8s-conn flask]$ kubectl get pods flask-6655749767-p49qb -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2023-07-20T05:57:50Z"
  generateName: flask-6655749767-
  labels:
    app: flask
    pod-template-hash: "6655749767"
...
spec:
  containers:
  - command:
    - sh
    - -c
    - python -m flask run --host=0.0.0.0
    envFrom:
    - configMapRef:
        name: flask
    image: registry.cn-shenzhen.aliyuncs.com/xiangys0134-dev/demo1-dev:frontendapi-test-202307200536
    imagePullPolicy: Always
    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sh
          - -c
          - sleep 10;
    livenessProbe:
      failureThreshold: 5
      httpGet:
        path: /
        port: 5000
        scheme: HTTP
      initialDelaySeconds: 60
      periodSeconds: 15
      successThreshold: 1
      timeoutSeconds: 3
    name: flask
    ports:
    - containerPort: 5000
      name: http
      protocol: TCP
    readinessProbe:
      failureThreshold: 3
      httpGet:
        path: /
        port: 5000
        scheme: HTTP
      initialDelaySeconds: 60
      periodSeconds: 10
      successThreshold: 1
      timeoutSeconds: 3
    resources:
      limits:
        cpu: 500m
        memory: 512Mi
      requests:
        cpu: 200m
        memory: 128Mi
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-xqwvs
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  imagePullSecrets:
  - name: flask-aws-image-secret
  nodeName: node-10
  preemptionPolicy: PreemptLowerPriority
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: default-token-xqwvs
    secret:
      defaultMode: 420
      secretName: default-token-xqwvs
...

最后修改日期: 2024年5月6日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。