当前位置: 首页 > news >正文

Jenkins 基于Kubernetes 弹性构建池

流程:

  • 创建Jenkins Agent;

  • 获取Jenkins Agent的参数;

  • 渲染yaml模板;

  • 调用K8s API在固定的NS中创建一个Pod;

  • 运行Jenkins pipeline到agent;

创建Agent

import hudson.model.Node.Mode
import hudson.slaves.*
import jenkins.model.Jenkins// 创建agent  下面是执行器数量的定义和label
String agentName = "__AGENT_NAME__"    
String executorNum = "1"     
String agentLabel = "JenkinsPod"agent_node = new DumbSlave(agentName, "Jenkins pod", "/opt/jenkins", executorNum,            Mode.EXCLUSIVE,   agentLabel,                       new JNLPLauncher(),         RetentionStrategy.INSTANCE) 
Jenkins.instance.addNode(agent_node)//获取agent的配置
node = Jenkins.instance.getNode(agentName)
computer = node.computer
jenkinsUrl = Jenkins.instance.rootUrl.trim().replaceAll('/$', '') return  """{
\"jenkinsUrl\" : \"${jenkinsUrl}\", 
\"jenkinsHome\": \"${node.remoteFS.trim()}\",
\"computerUrl\": \"${computer.url.trim().replaceAll('/$', '') as String}\",
\"computerSecret\": \"${computer.jnlpMac.trim()}\"
}"""

这里返回的是json类型的字符串,这样在调试的时候非常的方便。

这些信息最后在k8s里面需要以环境变量的方式指定出来。

其实手动创建好,然后将这串密钥拿下来,然后去启动他。但是现在自动化的去创建了。并且还将认证信息拿出来了。

后面在添加动态节点的时候先添加agent,然后拿到它的参数,最后渲染为pod的yaml,再去创建pod。

删除Agent

当资源不再使用了,就可以将节点删除。

import jenkins.model.JenkinsString agentName = "__AGENT_NAME__"Jenkins.instance.nodes.each { node ->String nodeName = node.nameif (nodeName.equals(agentName)) {Jenkins.instance.removeNode(node)}
}

ScriptConsole

// ScriptConsole运行脚本
def RunScriptConsole(scriptContent, crumb){response = sh returnStdout: true, script: """curl -s -d "script=\$(cat ${scriptContent})" \--header "Jenkins-Crumb:${crumb}" \-X  POST http://admin:112374bd5c557010386b55bb85a777aded@192.168.1.200:8080/scriptText"""try {response = readJSON text: response - "Result: "} catch(e){println(e)}return response
}// 获取Crumb值
def GetCrumb(){response = sh returnStdout: true, script: """ curl -s -u admin:admin \--location \--request GET 'http://192.168.1.200:8080/crumbIssuer/api/json' """response = readJSON text: responsereturn  response.crumb
}
http://192.168.11.128:8080/crumbIssuer/api/json{"_class":"hudson.security.csrf.DefaultCrumbIssuer","crumb":"f72990e2bc09a468effa69ec41f1432844bc709ca5ad6130d600da24ad16672a","crumbRequestField":"Jenkins-Crumb"}
curl -s -d "script=$(cat create_agent.groovy)" \--header "Jenkins-Crumb:f72990e2bc09a468effa69ec41f1432844bc709ca5ad6130d600da24ad16672a" \-X  POST http://admin:115fcd2e2d30505df7a18f23763c1332a0@192.168.11.128:8080/scriptText
[root@jenkins ~]# curl -s -d "script=$(cat create_agent.groovy)"   --header "Jenkins-Crumb:f72990e2bc09a468effa69ec41f1432844bc709ca5ad6130d600da24ad16672a"   -X  POST http://admin:115fcd2e2d30505df7a18f23763c1332a0@192.168.11.128:8080/scriptTextResult: {
"jenkinsUrl" : "http://192.168.11.128:8080", 
"jenkinsHome": "/opt/jenkins",
"computerUrl": "computer/%5F%5FAGENT%5FNAME%5F%5F",
"computerSecret": "6473dea92efa350d744450b91f010cd01880e0686597b8d33ef0876e698127c7"
}

Pod Yaml模板

apiVersion: v1
kind: Pod
metadata:labels:app: __AGENT_NAME__name: __AGENT_NAME__namespace: __NAMESPACE__
spec:containers:- name: dindimage: 'docker:stable-dind'command:- dockerd- --host=unix:///var/run/docker.sock- --host=tcp://0.0.0.0:8000- --insecure-registry=192.168.1.200:8088securityContext:privileged: truevolumeMounts:- mountPath: /var/runname: docker-dir- image: agenttest:6 #jenkins/inbound-agent:4.10-3-jdk8name: __AGENT_NAME__imagePullPolicy: IfNotPresentresources:limits:cpu: 1000mmemory: 8Girequests:cpu: 500mmemory: 2Gienv:- name: JENKINS_URLvalue: __JENKINS_URL__- name: JENKINS_SECRETvalue: __JENKINS_SECRET__- name: JENKINS_AGENT_NAMEvalue: __AGENT_NAME__- name: JENKINS_AGENT_WORKDIRvalue: /home/jenkins/workspacevolumeMounts:- mountPath: /var/runname: docker-dirdnsPolicy: ClusterFirstrestartPolicy: Alwaysvolumes:- name: docker-diremptyDir: {}

这里有两个容器,一个是docker in docker,因为containerd里面没有这个文件了。

因为docker共享了目录,在另外一个容器目录里面也可以看到,那么在另外的容器里面就可以运行docker命令了。

Kubernetes API准备工作

  1. 创建一个NS名称空间, 专用于运行Pod;

kubectl create ns jenkins
  1. 创建一个secret关联serviceaccount和role,操作K8s API;

# 创建role
kubectl -n jenkins create role jenkinsadmin \
--verb=create,delete,update,list,get,patch \
--resource=pods# 创建服务账户
kubectl -n jenkins create serviceaccount jenkinsadmin# 创建角色绑定
kubectl -n jenkins create rolebinding jenkinsadmin --role=jenkinsadmin --serviceaccount=jenkins:jenkinsadmin# 创建secret
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:name: jenkinsadmin-tokennamespace: jenkinsannotations:kubernetes.io/service-account.name: jenkinsadmin
type: kubernetes.io/service-account-token
EOFwhile ! kubectl -n jenkins describe secret jenkinsadmin-token | grep -E '^token' >/dev/null; doecho "waiting for token..." >&2sleep 1
done# 获取令牌
TOKEN=$(kubectl -n jenkins get secret jenkinsadmin-token -o jsonpath='{.data.token}' | base64 --decode)echo $TOKEN# 获取API
kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'# 使用令牌玩转 API
curl -X GET https://127.0.0.1:35659/api --header "Authorization: Bearer $TOKEN" --insecure
[root@192 ~]# curl -X GET https://127.0.0.1:6443/api --header "Authorization: Bearer $TOKEN" --insecure
{"kind": "APIVersions","versions": ["v1"],"serverAddressByClientCIDRs": [{"clientCIDR": "0.0.0.0/0","serverAddress": "192.168.11.134:6443"}]
}

将token 以secret text类型存储到Jenkins

POD API

//删除POD
def DeletePod(namespace, podName){withCredentials([string(credentialsId: 'f66733bf-ef35-402d-87d1-a79510387d2b', variable: 'CICDTOKEN')]) {sh """curl --location --request DELETE "https://192.168.1.200:6443/api/v1/namespaces/${namespace}/pods/${podName}" \--header "Authorization: Bearer ${CICDTOKEN}" \--insecure >/dev/null"""}
}// 创建POD
def CreatePod(namespace, podYaml){withCredentials([string(credentialsId: 'f66733bf-ef35-402d-87d1-a79510387d2b', variable: 'CICDTOKEN')]) {sh """curl --location --request POST "https://192.168.1.200:6443/api/v1/namespaces/${namespace}/pods" \--header 'Content-Type: application/yaml' \--header "Authorization: Bearer ${CICDTOKEN}" \--data "${podYaml}" --insecure >/dev/null"""}
}
curl --location --request POST "https://192.168.11.134:6443/api/v1/namespaces/jenkins/pods" \
--header 'Content-Type: application/yaml' \
--header "Authorization: Bearer ${TOKEN}" \
--data "${podYaml}" --insecure >/dev/nullcurl --location --request DELETE "https://192.168.11.134:6443/api/v1/namespaces/jenkins/pods/nginx" \
--header "Authorization: Bearer ${TOKEN}" \
--insecure >/dev/null
curl --location --request GET 'https://192.168.11.134:6443/api/v1/namespaces/jenkins/pods' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjBqSWxfOExtSW1pVmpKVkFUVGFQbHp1ZE5TcFo0SjlmOUtjMWFveWtrZGMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJqZW5raW5zIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImplbmtpbnNhZG1pbi10b2tlbi1jbTRsNyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJqZW5raW5zYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjMDAwZTVhMC00Yzg0LTQyZWEtYmJiNy1mZmM5MDBhYzUyMjIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6amVua2luczpqZW5raW5zYWRtaW4ifQ.A-InywzLZZfwx_4-Na9iDDRGsIH0Bjm9Xk92VxKsnP7hflEbOU631EU0eHnewgg0UqAD1kkhW39XupN13oTXrOjHrzWdm_UUMe2cBIYCZD19VIpNnRZ6bBLZ3LFHA2F0gXO14HaVZiUvSYBXgIfyHydetIFQFBPWFtU7091u5iB4pcw_gE-VzGjX6NDHj-81j6Ap2Qr0gIrNvrPVAOpPO9uCSg3PNCgvQMq2ZNrY2te1w7QxmeFPEpOIPiK6VbUkRjhQlHmawULZFol2k5Wwv9z0m1hPQcc2Nten1f1__GR39hUjryWXfltJ8OLpbKWK-AtfBkHx8VqbiKH1vQOrRg' \
--header 'Content-Type: text/plain' \
--data-raw 'abc'

这里请求方法由get换成了delete

自定义构建镜像

  • https://helm.sh/zh/docs/intro/install/

  • https://github.com/jenkinsci/docker-inbound-agent/blob/master/8/alpine/Dockerfile

  • https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux

FROM centos:7USER root
ADD tools/jdk-8u201-linux-x64.tar.gz /usr/local
ENV JAVA_HOME=/usr/local/jdk1.8.0_201
ENV M2_HOME=/usr/local/apache-maven-3.8.1COPY tools/agent.jar /usr/share/jenkins/agent.jar
COPY tools/jenkins-agent /usr/local/bin/jenkins-agent
COPY tools/apache-maven-3.8.1 /usr/local/apache-maven-3.8.1
COPY tools/helm /usr/bin/helm
COPY tools/kubectl /usr/bin/kubectlRUN echo "export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin" >> /etc/profile  && \source /etc/profile && \java -version && \chmod +x /usr/local/bin/jenkins-agent && \ln -s /usr/local/bin/jenkins-agent /usr/local/bin/jenkins-slave && \yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && \yum -y install docker-ce && \mkdir -p /home/jenkins/workspace && chmod 777 /home/jenkins/workspace && \yum -y install git && \chmod +x /usr/bin/helm && helm version && chmod +x /usr/bin/kubectlCOPY tools/daemon.json  /etc/docker/daemon.json
ENTRYPOINT ["/usr/local/bin/jenkins-agent"]

上面就是整个流程,k8s动态创建 销毁pod,在pod上面创建构建任务,构建完任务就将这个pod给删除了。

相关文章:

Jenkins 基于Kubernetes 弹性构建池

流程&#xff1a;创建Jenkins Agent&#xff1b;获取Jenkins Agent的参数&#xff1b;渲染yaml模板&#xff1b;调用K8s API在固定的NS中创建一个Pod&#xff1b;运行Jenkins pipeline到agent&#xff1b;创建Agentimport hudson.model.Node.Mode import hudson.slaves.* impor…...

经典算法题---链表奇偶重排(好题)双指针系列

我听别人说这世界上有一种鸟是没有脚的&#xff0c;它只能够一直的飞呀飞呀&#xff0c;飞累了就在风里面睡觉&#xff0c;这种鸟一辈子只能下地一次&#xff0c;那一次就是它死亡的时候。——《阿甘正传》这一文章讲解链表的奇偶排序问题&#xff0c;这是一道不难但是挺好的链…...

数据仓库实战

目录1、最佳实战1.1 表的分类1.2 ETL策略1.3 任务调度2、项目实战2.1 项目概述2.2 数据描述2.3 架构设计2.4 环境搭建2.5 项目开发1、最佳实战 1.1 表的分类 维度建模中表的类型&#xff1a;事实表和维度表 事实表又可以分为&#xff1a;事务事实表、周期快照事实表、累积快照…...

GPT系列:GPT, GPT-2, GPT-3精简总结 (模型结构+训练范式+实验)

&#x1f604; 花一个小时快速跟着 人生导师-李沐 过了一遍GPT, GPT-2, GPT-3。下面精简地总结了GPT系列的模型结构训练范式实验。 文章目录1、GPT1.1、模型结构&#xff1a;1.2、范式&#xff1a;预训练 finetune1.3、实验部分:2、GPT-22.1、模型结构2.2、范式&#xff1a;预…...

ASE12N65SE-ASEMI高压MOS管ASE12N65SE

编辑-Z ASE12N65SE在ITO-220AB封装里的静态漏极源导通电阻&#xff08;RDS(ON)&#xff09;为0.68Ω&#xff0c;是一款N沟道高压MOS管。ASE12N65SE的最大脉冲正向电流ISM为48A&#xff0c;零栅极电压漏极电流(IDSS)为10uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。ASE…...

centos8防火墙命令配置(开放端口)

查看防火墙状态&#xff1a;&#xff08;root用户&#xff09;firewall-cmd –state启动防火墙&#xff1a;&#xff08;root用户&#xff09;systemctl start firewalld.service查看防火墙开放端口&#xff1a;&#xff08;root用户&#xff09; firewall-cmd --list-ports …...

Instagram营销教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Instagram营销初学者教程 - 从简单和简单的步骤学习Instagram营销从基本到高级概念&#xff0c;包括概述&#xff0c;业务战略&#xff0c;安装和注册&#xff0c;发布和参与&#xff0c;活动审查&#xff0c;微调内容&#xff0c;营销工具和应用程序&#xff0c;集成…...

HTTP Code含义

HTTP Code描述详细100继续100&#xff08;继续&#xff09;状态代码表示一个已收到请求&#xff0c;尚未被拒绝服务器。服务器打算在请求已完全收到并已采取行动。当请求包含 Expect 标头字段时100-continue expectation&#xff0c;100响应表示服务器希望接收请求有效负载主体…...

Elasticsearch:Security API 介绍

在我之前的文章 “Elasticsearch&#xff1a;运用 API 创建 roles 及 users” &#xff0c;我展示了如何使用 Security API 来创建用户及角色来控制访问 Elasticsearch 中的索引。在今天的文章中&#xff0c;我将展示一个使用 Security API 来创建一个用户及角色来访问一个索引…...

springmvc考研交流平台 java ssm mysql

随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;考研交流平台当然也不能排除在外&#xff0c;从备考资料、课程学习的统计和分析&#xff0c;在过程中会产生大量的、各种各样的…...

2.15 vue3 day01 setup ref setup的参数 prop slot插槽 自定义事件通信

二、常用 Composition API 官方文档: 组合式 API 常见问答 | Vue.js 1.拉开序幕的setup 理解&#xff1a;Vue3.0中一个新的配置项&#xff0c;值为一个函数。 setup是所有Composition API&#xff08;组合API&#xff09;“ 表演的舞台 ”。 组件中所用到的&#xff1a;数据…...

CentOs7更新Yum源

1.安装wget yum install -y wget 2.备份配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak 3.下载国内yum源文件&#xff08;centOs7&#xff0c;比如阿里&#xff09; wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.al…...

【C/C++】VS2019下C++生成DLL并且成功调用(金针菇般细)

目录 一&#xff0c;生成动态链接库 二&#xff0c;使用动态链接库 一&#xff0c;生成动态链接库 1.打开VS2019&#xff0c;创建新项目&#xff0c;选择 动态链接库(DLL) 模板后进行下一步 2.输入项目名称&#xff0c;其它默认就行(可自行选择)&#xff0c;点击创建 3 工程…...

如何重新安装安卓手机系统

下载并安装您设备的驱动程序和ADB工具。如果您已经拥有了它们&#xff0c;请跳过此步骤。没有就百度下载。 打开终端或命令提示符&#xff0c;并将其设置为包含ADB二进制文件的目录。 启动设备并将其连接到计算机上。 在终端或命令提示符中运行以下命令以确认设备是否连接成…...

ArcGIS API for JavaScript 4.15系列(7)——Dojo中的Ajax请求操作

1、前言 作为重要的前后端交互技术&#xff0c;Ajax被广泛应用于Web项目中。无论是jQuery时代的$.ajax还是Vue时代下的axios&#xff0c;它们都对Ajax做了良好的封装处理。而Dojo也不例外&#xff0c;开发者使用dojo/request模块可以轻松实现Ajax相关操作&#xff0c;下面开始…...

智慧校园电子班牌系统

智慧电子班牌区别于传统电子班牌&#xff0c;智慧校园电子班牌系统更加注重老师和学生的沟通交流和及时数据交互。学校为每个教室配置一台智能电子班牌&#xff0c;一般安装于教室门口&#xff0c;用来实时显示学校通知、班级通知&#xff0c;可设置集中分布式管理&#xff0c;…...

软考高项——第五章进度管理

范围管理进度管理总线索规划进度管理定义活动活动排序估算活动资源估算活动时间制定进度管理计划控制进度进度管理总线索 进度管理的总线索包括&#xff1a; 1&#xff09;规划进度管理 2&#xff09;定义活动 3&#xff09;活动排序 4&#xff09;估算活动资源 5&#xff09;…...

基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【二】【整合springSecurity】

1、创建数据库 注意&#xff1a;mysql默认字符集为utf8&#xff0c;默认排序规则为utf8_general_ci。一般我们也会选择字符集为utf-8 MySQL在5.5.3之后增加了这个utf8mb4的编码&#xff0c;utf8mb4完全向下兼容utf8&#xff0c;为了节省空间&#xff0c;一般情况下使用utf8也就…...

字节6面,成功唬住面试官拿了27K,软件测试面试也没有传说中那么难吧....

字节的面试挺独特&#xff0c;每轮面试都没有 HR 约时间&#xff0c;一般是晚上 8 点左右面试官来一个电话&#xff0c;问是否能面试&#xff0c;能的话开始面&#xff0c;不能就约一个其它时间。全程 6 面&#xff0c;前五面技术面&#xff0c;电话面试&#xff0c;最后一面是…...

Qt扫盲-QMake 语言概述

QMake 语言概述一、概述二、变量三、替换函数四、测试函数一、概述 这里主要就是记录一下如何使用 qmake Manual&#xff0c;里面关于我对 qmake的理解&#xff0c;以及如何配置这个 qt 工程文件&#xff0c;通过配置工程文件&#xff0c;来构建出&#xff0c;APP&#xff0c;…...

雷达点云与相机标定避坑指南:如何用MATLAB Lidar Camera Calibrator提高标定精度

MATLAB Lidar Camera Calibrator实战&#xff1a;高精度标定的7个关键步骤与避坑策略 当激光雷达与相机数据需要融合时&#xff0c;标定精度直接决定了后续感知算法的上限。许多工程师在首次使用MATLAB Lidar Camera Calibrator时&#xff0c;常因自动标定结果不理想而陷入困惑…...

nanomsg性能基准测试终极指南:不同消息大小下的吞吐量对比分析

nanomsg性能基准测试终极指南&#xff1a;不同消息大小下的吞吐量对比分析 【免费下载链接】nanomsg nanomsg library 项目地址: https://gitcode.com/gh_mirrors/na/nanomsg nanomsg是一个轻量级、高性能的消息传递库&#xff0c;专为解决常见的通信模式而设计。作为na…...

别再傻傻分不清了!用Simulink手把手带你搞懂导纳控制与阻抗控制的本质区别

导纳控制 vs 阻抗控制&#xff1a;从理论到Simulink实战的深度解析 在机器人控制领域&#xff0c;柔性交互是一个永恒的话题。想象一下&#xff0c;当机械臂需要完成精密装配任务时&#xff0c;既要有足够的刚性保证定位精度&#xff0c;又要在意外碰撞时表现出适当的柔顺性——…...

Docker镜像的制作

什么是Docker镜像&#xff1f; Docker镜像是一个轻量级、独立的可执行软件包&#xff0c;包含运行应用程序所需的一切&#xff1a;代码、运行时、系统工具、系统库和设置。镜像是容器的基础&#xff0c;容器是镜像的运行实例。 准备工作 安装Docker 首先确保你的系统已安装D…...

揭秘League Akari:如何通过LCU API革新英雄联盟游戏体验?

揭秘League Akari&#xff1a;如何通过LCU API革新英雄联盟游戏体验&#xff1f; 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit …...

如何使用Compiler Explorer实时编译原理:揭秘代码到汇编的转换过程

如何使用Compiler Explorer实时编译原理&#xff1a;揭秘代码到汇编的转换过程 【免费下载链接】compiler-explorer Run compilers interactively from your web browser and interact with the assembly 项目地址: https://gitcode.com/gh_mirrors/co/compiler-explorer …...

Android16进阶之MediaPlayer.selectTrack调用流程与实战(二百五十)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》作者 博主新书推荐&#xff1a;《Android系统多媒体进阶实战》&#x1f680; Android Audio工程师专栏地址&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; Android多媒体专栏地址&a…...

原子操作的实现原理

在并发编程、操作系统与计算机体系结构中&#xff0c;原子操作是保证数据安全、避免竞态条件的基石。它的核心特性是不可中断、不可分割&#xff0c;操作要么完整执行&#xff0c;要么完全不执行&#xff0c;绝不会出现中间状态。本文将从定义出发&#xff0c;逐层拆解原子操作…...

从单变量到多变量:ODE与PDE的核心差异与应用场景解析

1. 从自变量数量看本质差异 第一次接触微分方程时&#xff0c;我也曾被ODE和PDE搞得晕头转向。直到有天导师用了个特别形象的比喻&#xff1a;ODE就像观察单车道上的车流&#xff0c;而PDE则是分析整个立交桥的交通网络。这个比方一下子点醒了我——核心差异就在于自变量数量这…...

工业现场的空压机监控总得整点活吧?今天咱们拿MCGS6.2搞个仿真系统,带曲线报警和报表那种。直接上干货,先开工程建个空压机模型

空压机mcgs6.2仿真&#xff0c;带曲线报警和报表界面在设备窗口拖个模拟设备&#xff0c;配四个关键变量&#xff1a;出口压力&#xff08;0-1.6MPa&#xff09;、运行温度&#xff08;0-120℃&#xff09;、电机电流&#xff08;0-50A&#xff09;、运行状态&#xff08;0/1&a…...