使用Jenkins发布应用到K8S集群

一、基础环境

ip地址作用
192.168.2.101K8S集群
192.168.2.104Harbor
jenkins.xxx.comJenkins
gitea.xxx.comGitea

二、环境准备

2.1、Jenkins安装插件

需要安装如下插件 Kubernetes

2.2、配置凭据

进入Jenkins,进入系统管理–凭据管理,进入后点击添加,添加如下两个凭据,类型都是Username with Password id:gitea-creds 和 harbor-creds,用户名和密码分别是harbor及gitea的用户名和密码

2.3、配置云

在Jenkins的系统管理–云,点击添加,

  • 名称:随意设置
  • Kubernetes 地址:https://kubernetes.default.svc.cluster.local
  • 禁用 HTTPS 证书检查 :勾选
  • Kubernetes 命名空间:devops
  • Jenkins 地址:http://jenkins.devops.svc.cluster.local:8080
  • Jenkins 通道:jenkins.devops.svc.cluster.local:50000

2.4、gitea准备及代码

在gitea创建一个仓库,并克隆到本地计算机,使用vscode打开后,写入如下几个文件,文件名称及内容如下 app.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from flask import Flask
import socket

app = Flask(__name__)

@app.route('/')
def hello():
    hostname = socket.gethostname()
    # 核心测试点:你以后可以把 v1 改成 v2、v3,看网页会不会变!
    return f"<h1>Hello K8s! This is Version: v2</h1><p>Running on Pod: {hostname}</p>"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)

requirements.txt

1
2
flask==3.0.0
werkzeug==3.0.0

Dockerfile

1
2
3
4
5
6
7
FROM 192.168.2.104/library/python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY app.py .
EXPOSE 8080
CMD ["python", "app.py"]

k8s-deploy.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-python-app
  namespace: devops
spec:
  replicas: 2 # 给你搞两个 Pod 跑,感受一下负载均衡
  selector:
    matchLabels:
      app: my-python-app
  template:
    metadata:
      labels:
        app: my-python-app
    spec:
      containers:
      - name: web
        # 你的 Harbor 地址
        image: 192.168.2.104/library/my-python-app:IMAGE_TAG_PLACEHOLDER
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-python-app-svc
  namespace: devops
spec:
  selector:
    app: my-python-app
  ports:
  - port: 8080
    targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-python-app-ingress
  namespace: devops
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.xxx.com 
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-python-app-svc
            port:
              number: 8080

将上述几个文件提交并推送到gitea即可

2.5、镜像准备

在192.168.2.104上执行如下命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 1. 同步隐藏的 JNLP 通信代理镜像
docker pull jenkins/inbound-agent:latest
docker tag jenkins/inbound-agent:latest 192.168.2.104/library/inbound-agent:latest
docker push 192.168.2.104/library/inbound-agent:latest

# 2. 同步 Kaniko 打包引擎镜像 (如果 gcr.io 拉不动,可以用 dockerhub 的镜像源)
docker pull gcr.io/kaniko-project/executor:debug  # 或者 pull bitnami/kaniko:latest 视你的网络而定
docker tag gcr.io/kaniko-project/executor:debug 192.168.2.104/library/kaniko:debug
docker push 192.168.2.104/library/kaniko:debug

# 3. 同步 Kubectl 部署工具镜像
docker pull bitnami/kubectl:latest
docker tag bitnami/kubectl:latest 192.168.2.104/library/kubectl:latest
docker push 192.168.2.104/library/kubectl:latest

docker pull python:3.9-slim
docker tag docker.io/library/python:3.9-slim 192.168.2.104/library/python:3.9-slim
docker push 192.168.2.104/library/python:3.9-slim

三、配置部署任务

进入Jenkins之后,点击新建任务,建立流水线任务 在配置中,找到流水线在定义中找到Pipeline script,在内容中输入如下内容

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
pipeline {
    // 1. 定义动态构建节点 (K8s Pod)
    agent {
        kubernetes {
            yaml """
apiVersion: v1
kind: Pod
spec:
  serviceAccountName: jenkins-admin
  containers:
  # 强行覆盖默认的隐藏通信容器,让它走本地 Harbor!
  - name: jnlp
    image: 192.168.2.104/library/inbound-agent:latest
  # Kaniko (负责在 Containerd 环境下无 Docker 引擎打镜像)
  - name: kaniko
    image: 192.168.2.104/library/kaniko:debug
    command: ['sleep']
    args: ['99d']
    tty: true
    securityContext:
      runAsUser: 0
  
  # Kubectl (负责把镜像更新到 K8s)
  - name: kubectl
    image: 192.168.2.104/library/kubectl:latest
    command: ['sleep']
    args: ['99d']
    tty: true
    securityContext:
      runAsUser: 0
"""
        }
    }

    // 2. 定义全局环境变量
    environment {
        HARBOR_REGISTRY = "192.168.2.104"
        IMAGE_NAME = "library/my-python-app"
        // 使用 Jenkins 自带的构建次数作为版本号,如 v1, v2, v3
        IMAGE_TAG = "v${BUILD_NUMBER}" 
    }

    stages {
        //  1 阶段:拉取代码
        stage('Checkout Code') {
            steps {
                checkout scmGit(
                    branches: [[name: '*/main']], 
                    userRemoteConfigs: [[
                        // 【核心修改】:抛弃外网域名,直接写 K8s 内部的服务调用地址!
                        url: 'http://gitea.default.svc.cluster.local:3000/admin/Test1.git',
                        credentialsId: 'gitea-creds'
                    ]]
                )
            }
        }

        //  2 阶段:构建并推送镜像
        stage('Build & Push Image') {
            steps {
                container('kaniko') {
                    // 调取你在 Jenkins 里存的 Harbor 账号密码
                    withCredentials([usernamePassword(credentialsId: 'harbor-creds', passwordVariable: 'HARBOR_PWD', usernameVariable: 'HARBOR_USER')]) {
                        // 使用单引号 ''' 保护 Shell 脚本,让内部环境变量生效
                        sh '''
                            echo "🚀 开始配置 Harbor 认证..."
                            mkdir -p /kaniko/.docker
                            # 生成 Kaniko 专属的 auths 认证文件
                            echo "{\\"auths\\":{\\"${HARBOR_REGISTRY}\\":{\\"username\\":\\"${HARBOR_USER}\\",\\"password\\":\\"${HARBOR_PWD}\\"}}}" > /kaniko/.docker/config.json
                            
                            echo "🚀 开始构建并推送到 Harbor..."
                            # --insecure 和 --skip-tls-verify 专门应对 HTTP 协议或自签证书的 Harbor
                            /kaniko/executor \
                                --context `pwd` \
                                --dockerfile `pwd`/Dockerfile \
                                --destination ${HARBOR_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} \
                                --insecure \
                                --skip-tls-verify
                        '''
                    }
                }
            }
        }

        // 第 3 阶段:部署到 K8s
        stage('Deploy to K8s') {
            steps {
                container('kubectl') {
                    sh '''
                        echo "🚀 开始更新 K8s 部署文件..."
                        # 将 yaml 文件里的 IMAGE_TAG_PLACEHOLDER 替换为本次真实的 IMAGE_TAG (如 v3)
                        sed -i "s|IMAGE_TAG_PLACEHOLDER|${IMAGE_TAG}|g" k8s-deploy.yaml
                        
                        echo "🚀 正在发布到 K8s 集群..."
                        kubectl apply -f k8s-deploy.yaml
                        
                        echo "🎉 部署完成!"
                    '''
                }
            }
        }
    }
}

点击保存即可,点击立即构建 查看日志之后,将该地址写入到DNS之后,在浏览器打开,看到网页即可

comments powered by Disqus