0
点赞
收藏
分享

微信扫一扫

资源控制器--laravel进阶篇

先峰老师 2024-11-24 阅读 11

前言

这里会做整体CICD的思路和流程的介绍,会给出核心的Jenkins pipeline脚本,最后会演示一下 实验/实操 结果
由于整体内容较多,所以不打算在这里做每一步的详细演示 - 本文仅作自己的实操记录和日后回顾用
要看保姆式教学的可以划走了,没有K8S基础的也可以划走了

正文

1. 整体实现思路

  1. 在K8S集群中部署Jenkins服务(我这里实验用的是 Jenkins 2.486版本),给Jenkins分配对应的NFS、PV、PVC、SA、NS、SVC等资源,挂载Jenkins配置文件到服务器
  2. 在Jenkins中安装 kubernetes、blue ocean 插件
  3. 配置Jenkins和K8S集群正常通信
  4. 配置 pod template - 这里的 pod template 实际上就是对 Jenkins agent(以前叫 Jenkins slave) 的配置,用于完成git代码拉取、mvn打包、docker镜像上传等操作
  5. 新建流水线任务,加入自己的pipeline脚本

CICD流程:

2. 插件简介

2.1 Kubernetes插件简介

Kubernetes插件使用 - Kubernetes Plugin的配置主要有两部分组成:

  • kubernetes的连接参数:主要用于配置如果连接kubernetes
  • kubernetes的pod模板:调用kubernetes创建jenkins slave使用的pod模板

在这里插入图片描述

2.2 Blue Ocean 插件简介

Blue Ocean 是 Jenkins 的一款现代化 UI 插件,旨在为持续集成/持续交付 (CI/CD) 提供更加直观、用户友好的界面和体验。

  • 全新的可视化流水线体验
    • Blue Ocean 提供了流水线运行过程的直观可视化,用户可以清晰地查看流水线的各个阶段(stage)、步骤(step)及其状态(成功、失败、运行中)。
    • 支持图形化展示流水线的分支、并行任务及错误点,便于快速诊断和调试。
  • 简化的流水线创建和编辑
    • 内置交互式流水线编辑器,支持通过拖放操作创建 Jenkinsfile,降低了学习曲线。
    • 用户无需编写复杂的脚本即可快速配置和生成流水线代码。
  • 强大的分支支持
    • 专为 Git 和其他分布式版本控制系统的多分支流水线设计。
    • 自动检测代码仓库中的分支和 Pull Request,独立运行每个分支的流水线任务。
  • 高效的协作能力
    • 在失败的任务或构建上添加评论,方便团队成员进行问题协作和修复。
    • 支持通过直观的界面查看构建日志、失败原因以及历史记录。
  • 插件生态集成
    • 与 Jenkins 的现有插件(如 Git、GitHub、Bitbucket、Docker 等)无缝集成。
    • 支持各种通知机制(如邮件、Slack、Webhook)来增强 CI/CD 流程。
  • 跨平台友好
    • 适配桌面端和移动端,用户可以随时随地查看流水线状态。
      在这里插入图片描述

3. pipeline脚本示例

env.BRANCH_NAME = 'master'
node('devops') {
stage('Clone') {
echo "1.下载代码"
withCredentials([usernamePassword(credentialsId: 'github', usernameVariable: 'gitHubUser', passwordVariable: 'gitHubToken')]) {
git url: "https://${gitHubUser}:${gitHubToken}@github.com/cqweiheng/myspringboot.git"
}
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.代码扫描"
}
stage('Build') {
echo "3.构建docker镜像"
// 执行 Maven 构建,生成 jar 文件
sh 'mvn clean package -Dmaven.test.skip=true'
// 打包成镜像
sh "docker build -t cqweiheng/test:myspringboot-${build_tag} ."
}
stage('Push') {
echo "4.推送镜像"
withCredentials([usernamePassword(credentialsId: 'dockerhub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"
// 这里可以改用 harbor
//sh "docker login 192.168.86.100 -u ${harborUser} -p ${harborPassword}"
sh "docker push cqweiheng/test:myspringboot-${build_tag}"
}
}
stage('Deploy to dev') {
echo "5.发布到 dev 环境"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev.yaml"
sh "cat k8s-dev.yaml"
sh "kubectl apply -f k8s-dev.yaml"
sh "sleep 10"
sh "kubectl get pods -n dev"
}
stage('Deploy to test') {
def userSelected = input(
id: 'userSelected',
message: '确认发布到【测试】环境?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "确认\n取消",
name: '请选择'
]
]
)
echo "用户选择:${userSelected}"
if (userSelected == "确认") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-test.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-test.yaml"
sh "cat k8s-test.yaml"
sh "kubectl apply -f k8s-test.yaml"
sh "sleep 10"
sh "kubectl get pods -n test"
} else {
//exit
echo "用户选择不发布到测试环境,本次部署流程终止。"
currentBuild.result = 'ABORTED'
error("用户选择取消发布到测试环境。")
}
}
stage('Deploy to pro') {
def userSelected = input(

id: 'userSelected',
message: '确认发布到【生产】环境?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "确认\n取消",
name: '请选择'
]
]
// 仅允许指定用户操作 - 通过授权,仅测试团队可以操作
//,submitter: 'test-user,test-group'
)
echo "用户选择:${userSelected}"
if (userSelected == "确认") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-prod.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-prod.yaml"
sh "cat k8s-prod.yaml"
sh "kubectl apply -f k8s-prod.yaml --record"
sh "sleep 10"
sh "kubectl get pods -n prod"
}
}
}

4. 演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在 deploy to test 这里就停住了,等待授权
开发人员在 dev 环境自测完毕后,确认发布到测试环境,由测试团队进行验证
在这里插入图片描述

发布到生产这里可以通过添加 submitter 来控制用户权限,比如仅测试团队可以提交
在这里插入图片描述
在这里插入图片描述
到这里整个流程就结束了
从下图中可以看到Jenkins slave这个 pod 生命周期结束
在命名空间 dev, test, prod 中分别生成了新的 pod
在这里插入图片描述

访问一下,自己写的一个springboot 应用 -> OK的
在这里插入图片描述

5. 闲聊

  1. 这里 svc 用的 NodePort,实际生产中如果做四层负载的话,应该会用 LoadBalance
  2. 做版本回滚的话,可以新起一个pipeline,调用shell脚本,选择版本号后进行回滚操作
    参考:
    #查看历史版本
    kubectl rollout history deployment/<deployment_name>
    #回退到指定版本
    kubectl rollout undo deployment/<deployment_name> --to-revision=<revision_number>
    
  3. 这里是用的单个集群,将开发、测试和生产环境部署在 同一个 K8S 集群中,并通过 Namespace 来区分不同环境。这种方式简单高效,但需要合理的规划和配置,确保资源隔离和环境安全性。
    比如按 namespace 做资源配额,按 单个pod 做资源限制
    #按 namespace 做资源限制
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: resource-quota
      namespace: dev
    spec:
      hard:
        pods: "20"                  # 最大允许 20 个 Pod
        requests.cpu: "4"           # 总 CPU 请求限制 4 核
        requests.memory: "8Gi"      # 总内存请求限制 8GB
        limits.cpu: "8"             # 总 CPU 限制 8 核
        limits.memory: "16Gi"       # 总内存限制 16GB
    
    #按 单个pod 做资源限制 - 防止单个 Pod 占用过多资源
    apiVersion: v1
    kind: LimitRange
    metadata:
      name: limits
      namespace: dev
    spec:
      limits:
      - default:
          cpu: "500m"
          memory: "512Mi"
        defaultRequest:
          cpu: "200m"
          memory: "256Mi"
        type: Container
    
  4. Jenkins 的 Pipeline 可以通过不同的 kubeconfig 文件操作不同的集群。再直白点就是,可以通过 kubeconfig 文件 做服务器隔离、集群隔离的CICD 发布到dev、test、prod环境 - 当然这个我还没实际操作过
    顺带搜了一下,大约是这样做的,下面的内容仅供参考
    #1.为每个集群(dev 和 test)生成独立的 kubeconfig 文件
    kubectl config view --raw > kubeconfig-dev.yaml
    kubectl config view --raw > kubeconfig-test.yaml
    #2.将这些 kubeconfig 文件上传到 Jenkins 的凭据管理系统,确保安全性
    #在 Jenkins 中添加 kubeconfig 凭据
    #	打开 Jenkins Dashboard。
    #	进入 "Manage Jenkins" > "Credentials"。
    #	添加凭据:
    #		Kind:Secret file
    #		File:上传 kubeconfig-dev.yaml 和 kubeconfig-test.yaml。
    #		ID:分别命名为 kubeconfig-dev 和 kubeconfig-test。
    
    #3.在 Jenkins Pipeline 中使用 kubeconfig 文件
    #利用 withCredentials 加载对应的 kubeconfig 文件,动态切换集群。
    pipeline {
    agent any
    stages {
        stage('Deploy to Dev') {
            steps {
                script {
                    echo "Deploying to Dev Cluster..."
                    withCredentials([file(credentialsId: 'kubeconfig-dev', variable: 'KUBECONFIG')]) {
                        // 使用 kubeconfig-dev 操作 dev 集群
                        sh 'kubectl apply -f k8s-dev.yaml'
                        sh 'kubectl get pods -n dev'
                    }
                }
            }
        }
        stage('Deploy to Test') {
            steps {
                script {
                    input "Confirm deployment to Test environment?"
                    echo "Deploying to Test Cluster..."
                    withCredentials([file(credentialsId: 'kubeconfig-test', variable: 'KUBECONFIG')]) {
                        // 使用 kubeconfig-test 操作 test 集群
                        sh 'kubectl apply -f k8s-test.yaml'
                        sh 'kubectl get pods -n test'
                    }
                }
            }
        }
    }
    

}
```
这种就是各集群的资源、权限完全独立,不会相互影响。即使某一环境出现问题,其他环境仍可正常工作。

适合场景
- 多集群部署:开发、测试、生产环境分布在不同的 Kubernetes 集群中。
- 跨区域服务器管理:如不同集群位于不同的云平台(阿里云、腾讯云、AWS 等)。
- 严格隔离需求:需要通过不同的 kubeconfig 文件实现权限和资源隔离。

6. 踩过的坑

6.1 FailedCreatePodSandbox - error getting clusterInfomation: connection is unauthorized

在这里插入图片描述
这个错误纠结了好久,最开始解题思路有误
看日志一直以为是授权出了问题
做了如下尝试,又检查了calico插件,发现全都是正常的
第二天Google搜了一下:
https://devopscube.com/clusterinformation-connection-unauthorized/
重启calico后OK,气不气?

#授权
kubectl create clusterrolebinding calico-access-jenkins-admin \
  --clusterrole=calico-kube-controllers \
  --serviceaccount=devops:jenkins-admin

#绑定token - vim jenkins-admin-token.yaml
apiVersion: v1
kind: Secret
metadata:
  name: jenkins-admin-token
  namespace: devops
  annotations:
    kubernetes.io/service-account.name: jenkins-admin
type: kubernetes.io/service-account-token
#kubectl apply -f jenkins-admin-token.yaml


#验证是否生效
kubectl -n devops describe secret $(kubectl -n devops get secret | grep jenkins-admin | awk '{print $1}')
curl -k -H "Authorization: Bearer <your-token>" https://<kube-apiserver>:6443/apis/crd.projectcalico.org/v1/clusterinformations

#能正常访问说明权限没有问题
kubectl --token=<your-token> get clusterinformation -o yaml

6.2 jenkins svc 没有暴露50000 端口

这个好像没什么可说的,加上就好了
在这里插入图片描述

6.3 Jenkins slave 构建镜像时提示 docker: not found

在这里插入图片描述
这个东西也搞了一阵子,后来自己基于
FROM jenkins/agent:latest
添加了 docker.io、maven-3.9.5、kubectl v1.31.2
然后打包成自己的Jenkins slave镜像使用,整个流程才正常跑通
这个镜像我推送到了 dockerhub 上,有需要的同学可以直接拿来用(不过由于版本问题,估计大概率也只有我自己用,哈哈)
镜像:cqweiheng/test:jenkins-agent-with-docker-v4

举报

相关推荐

0 条评论