【Kubernetes】控制器Statefulset

news2024/9/23 15:32:24

Statefulset控制器

  • 一、概念
  • 二、Statefulset资源清单文件编写技巧
    • 2.1、查看定义Statefulset资源需要的字段
    • 2.2、查看statefulset.spec字段如何定义
    • 2.3、查看statefulset的spec.template字段如何定义
  • 三、Statefulset使用案例:部署web站点
    • 3.1、编写一个Statefulset资源清单文件
    • 3.2、更新资源清单文件
    • 3.3、查看相关资源
  • 四、StatefulSet组成部分
    • 4.1、 Headless Service
      • 【1】headless service会为service分配一个域名
      • 【2】StatefulSet会为关联的Pod保持一个不变的Pod Name
      • 【3】StatefulSet会为关联的Pod分配一个dnsName
    • 4.2、volumeClaimTemplates
    • 4.3、总结
  • 五、Statefulset管理pod:扩容、缩容、更新
    • 5.1、动态扩缩容
    • 5.2、滚动更新

一、概念

StatefulSet是为了管理有状态服务的问题而设计的.

扩展:
有状态服务?

StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、redis集群等。

无状态服务?

RC、Deployment、DaemonSet都是管理无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。

二、Statefulset资源清单文件编写技巧

2.1、查看定义Statefulset资源需要的字段

[root@master ~]# kubectl explain statefulset
KIND:     StatefulSet
VERSION:  apps/v1

DESCRIPTION:
     StatefulSet represents a set of pods with consistent identities. Identities
     are defined as:
     - Network: A single stable DNS and hostname.
     - Storage: As many VolumeClaims as requested.

     The StatefulSet guarantees that a given network identity will always map to
     the same storage identity.

FIELDS:
   apiVersion   <string> # 定义资源需要使用的api版本
   kind <string>         # 定义资源类型
   metadata     <Object> # 定义元数据
   spec <Object>         # 定义容器相关的信息  

2.2、查看statefulset.spec字段如何定义

[root@master ~]#  kubectl explain statefulset.spec
KIND:     StatefulSet
VERSION:  apps/v1

RESOURCE: spec <Object>

DESCRIPTION:
     Spec defines the desired identities of pods in this set.

     A StatefulSetSpec is the specification of a StatefulSet.

FIELDS:
   podManagementPolicy  <string>      # POD管理策略
   replicas     <integer>             # 副本数
   revisionHistoryLimit <integer>     # 保留的历史版本
   selector     <Object> -required-   # 标签选择器,选择它所关联的pod
   serviceName  <string> -required-   # headless service的名字
   template     <Object> -required-   # 生成pod的模板
   updateStrategy       <Object>      # 更新策略
   volumeClaimTemplates <[]Object>    # 存储卷申请模板

2.3、查看statefulset的spec.template字段如何定义

对于template而言,其内部定义的就是pod,pod模板是一个独立的对象。
.spec.template里的内容是声明Pod对象时要定义的各种属性,所以这部分也叫做PodTemplate(Pod模板)

[root@master ~]# kubectl explain statefulset.spec.template
KIND:     StatefulSet
VERSION:  apps/v1

RESOURCE: template <Object>
DESCRIPTION:
    ......
FIELDS:
   metadata     <Object>  # 定义多少个Pod副本(默认将仅部署1个Pod)、匹配Pod标签的选择器、创建pod的模板、存储卷申请模板 
   spec <Object>  # Pod里的容器属性等配置 
                  # 在spec.template.spec.selector中定义的标签选择器必须能够匹配到spec.template.metadata.labels里定义的Pod标签,否则Kubernetes将不允许创建statefulset。

三、Statefulset使用案例:部署web站点

3.1、编写一个Statefulset资源清单文件

[root@master 12]# cat statefulset.yaml
apiVersion: v1   # 定义api版本
kind: Service    # 定义要创建的资源:service
metadata:
  name: nginx    # 定义service的名字
  labels: 
     app: nginx  # service的标签
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None  # 创建一个没有ip的service
  selector:
    app: nginx     # 选择拥有app=nginx标签的pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"   # headless service的名字
  replicas: 2            # 副本数
  template:
    metadata:            # 定义pod的模板
     labels:
       app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80  # 容器服务的端口
          name: web          # 端口别名
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:     # 存储卷申请模板
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"] # 访问模式:单路读写
      storageClassName: "nfs"  # 指定从哪个存储类申请pv
      resources:
        requests:
          storage: 1Gi   # 需要1G的pvc,会自动跟符合条件的pv绑定 

3.2、更新资源清单文件

[root@master 12]# kubectl apply -f statefulset.yaml
service/nginx created
statefulset.apps/web created
# 查看statefulset是否创建成功
[root@master 12]# kubectl get statefulset
NAME   READY   AGE
web    2/2     2m7s
# 查看pod
[root@master 12]# kubectl get pods -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          2m50s
web-1   1/1     Running   0          2m8s
# 通过上面可以看到创建的pod是有序的

3.3、查看相关资源

[root@master 12]# kubectl get svc -l app=nginx
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    3m50s
[root@master 12]# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0     Bound    pvc-223fc042-1b1b-4516-a1b5-a5572434d3ee   1Gi        RWO            nfs            4m8s
www-web-1     Bound    pvc-b4f026b2-4984-4302-b45d-00c57a74a162   1Gi        RWO            nfs            3m26s
[root@master 12]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                 STORAGECLASS   REASON   AGE
pvc-223fc042-1b1b-4516-a1b5-a5572434d3ee   1Gi        RWO            Delete           Bound      default/www-web-0     nfs                     4m39s
pvc-b4f026b2-4984-4302-b45d-00c57a74a162   1Gi        RWO            Delete           Bound      default/www-web-1     nfs                     3m56s
[root@master 12]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname';done
web-0
web-1

四、StatefulSet组成部分

4.1、 Headless Service

用来定义pod网路标识,生成可解析的DNS记录

Headless service不分配clusterIP,headless service可以通过解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通过解析service的DNS返回service的ClusterIP。

【1】headless service会为service分配一个域名

<service name>.$<namespace name>.svc.cluster.local

K8s中资源的全局FQDN格式:
  Service_NAME.NameSpace_NAME.Domain.LTD.
  Domain.LTD.=svc.cluster.local #这是默认k8s集群的域名。

扩展:FQDN

FQDN 全称 Fully Qualified Domain Name
即全限定域名:同时带有主机名和域名的名称
FQDN = Hostname + DomainName
如 主机名是 xianchao 域名是 baidu.com
FQDN= xianchao.baidu.com

【2】StatefulSet会为关联的Pod保持一个不变的Pod Name

statefulset中Pod的名字格式为$(StatefulSet name)-$(pod序号)

【3】StatefulSet会为关联的Pod分配一个dnsName

$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local

4.2、volumeClaimTemplates

为什么要用volumeClaimTemplate?

对于有状态应用都会用到持久化存储,比如mysql主从,由于主从数据库的数据是不能存放在一个目录下的,每个mysql节点都需要有自己独立的存储空间。
而在deployment中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,它们数据是同步的,而statefulset定义中的每一个pod都不能使用同一个存储卷,这就需要使用volumeClainTemplate。
当在使用statefulset创建pod时,volumeClainTemplate会自动生成一个PVC,从而请求绑定一个PV,每一个pod都有自己专用的存储卷。

Pod、PVC和PV对应的关系图如下:
在这里插入图片描述
使用kubectl run运行一个提供nslookup命令的容器,这个命令来自于dnsutils包,通过对pod主机名执行nslookup,可以检查它们在集群内部的DNS地址

kubectl run busybox --image docker.io/library/busybox:1.28  --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
If you don't see a command prompt, try pressing enter.
/ # nslookup web-0.nginx.default.svc.cluster.local
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-0.nginx.default.svc.cluster.local # 查询service dns,会把对应的pod ip解析出来
Address 1: 10.244.196.144 web-0.nginx.default.svc.cluster.local

4.3、总结

  • 1、Statefulset管理的pod,pod名字是有序的,由statefulset的名字-0、1、2这种格式组成
  • 2、创建statefulset资源的时候,必须事先创建好一个service,如果创建的service没有ip,那对这个service做dns解析,会找到它所关联的pod ip,如果创建的service有ip,那对这个service做dns解析,会解析到service本身ip。
  • 3、statefulset管理的pod,删除pod,新创建的pod名字跟删除的pod名字是一样的
  • 4、statefulset具有volumeclaimtemplate这个字段,这个是卷申请模板,会自动创建pv,pvc也会自动生成,跟pv进行绑定,那如果创建的statefulset使用了volumeclaimtemplate这个字段,那创建pod,数据目录是独享的
  • 5、ststefulset创建的pod,是有域名的(域名组成:pod-name.svc-name.svc-namespace.svc.cluster.local)

五、Statefulset管理pod:扩容、缩容、更新

5.1、动态扩缩容

如果我们觉得两个副本太少了,想要增加,只需要修改配置文件statefulset.yaml里的replicas的值即可,原来replicas: 2,现在变成replicaset: 3,修改之后,执行如下命令更新:

[root@master 12]# kubectl apply -f statefulset.yaml
service/nginx unchanged
statefulset.apps/web configured
[root@master 12]# kubectl get sts
NAME   READY   AGE
web    3/3     80m
[root@master 12]# kubectl get pods -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          81m
web-1   1/1     Running   0          80m
web-2   1/1     Running   0          28s

也可以直接编辑控制器实现扩容,这个是我们把请求提交给了apiserver,实时修改
在这里插入图片描述

[root@master 12]# kubectl edit sts web  # 副本改成4
statefulset.apps/web edited
[root@master 12]# kubectl get pods -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          82m
web-1   1/1     Running   0          81m
web-2   1/1     Running   0          90s
web-3   1/1     Running   0          7s

5.2、滚动更新

kubectl explain sts.spec.updateStrategy

[root@master 12]# kubectl explain sts.spec.updateStrategy
KIND:     StatefulSet
VERSION:  apps/v1

RESOURCE: updateStrategy <Object>

DESCRIPTION:
     updateStrategy indicates the StatefulSetUpdateStrategy that will be
     employed to update Pods in the StatefulSet when a revision is made to
     Template.

     StatefulSetUpdateStrategy indicates the strategy that the StatefulSet
     controller will use to perform updates. It includes any additional
     parameters necessary to perform the update for the indicated strategy.

FIELDS:
   rollingUpdate        <Object>
     RollingUpdate is used to communicate parameters when Type is
     RollingUpdateStatefulSetStrategyType.

   type <string>
     Type indicates the type of the StatefulSetUpdateStrategy. Default is
     RollingUpdate
     Possible enum values:
     - `"OnDelete"`  
     - `"RollingUpdate"`  
[root@master 12]# cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
     app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  updateStrategy:  # 1、添加更新策略
    rollingUpdate:
      partition: 1  # 序号大于等于1的pod做更新
      maxUnavailable: 0  # 滚动更新时允许不可用 Pod 的最大数量
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
     labels:
       app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v2  # 2、修改镜像:容器才会更新
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "nfs"
      resources:
        requests:
          storage: 1Gi
# 在一个终端执行如下命令:kubectl apply -f statefulset.yaml
# 在另一个终端动态查看pod
[root@master ~]# kubectl get pods -l app=nginx -w
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          102m
web-1   1/1     Running   0          101m
web-2   1/1     Running   0          22m
web-3   1/1     Running   0          20m
web-3   1/1     Terminating   0          20m
web-3   1/1     Terminating   0          20m
web-3   0/1     Terminating   0          20m
web-3   0/1     Terminating   0          20m
web-3   0/1     Terminating   0          20m
web-2   1/1     Terminating   0          22m
web-2   1/1     Terminating   0          22m
web-2   0/1     Terminating   0          22m
web-2   0/1     Terminating   0          22m
web-2   0/1     Terminating   0          22m
web-2   0/1     Pending       0          0s
web-2   0/1     Pending       0          0s
web-2   0/1     ContainerCreating   0          0s
web-2   0/1     ContainerCreating   0          1s
web-2   1/1     Running             0          10s
web-1   1/1     Terminating         0          102m
web-1   1/1     Terminating         0          102m
web-1   0/1     Terminating         0          102m
web-1   0/1     Terminating         0          102m
web-1   0/1     Terminating         0          102m
web-1   0/1     Pending             0          0s
web-1   0/1     Pending             0          0s
web-1   0/1     ContainerCreating   0          0s
web-1   0/1     ContainerCreating   0          0s
web-1   1/1     Running             0          9s
web-2   1/1     Running             0          42s
web-1   1/1     Running             0          52s

# 从上面结果可以看出来,pod在更新的时候,只是更新了web-1、2、3 
# partition: 1表示更新的时候会把pod序号大于等于1的进行更新

如果更新策略是OnDelete,那不会自动更新pod,需要手动删除,重新常见的pod才会实现更新
修改策略:

  updateStrategy:
   type: OnDelete
   # rollingUpdate:
   #   partition: 1
   #   maxUnavailable: 0
[root@master 12]# kubectl apply -f statefulset.yaml
service/nginx unchanged
statefulset.apps/web configured
[root@master 12]# kubectl get pod  -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          121m
web-1   1/1     Running   0          18m
web-2   1/1     Running   0          18m
[root@master 12]# kubectl delete pod web-0
pod "web-0" deleted
# 在另一种终端动态查看
[root@master ~]# kubectl get pod -w
NAME                              READY   STATUS    RESTARTS      AGE
web-0                             1/1     Running   0             122m
web-1                             1/1     Running   0             19m
web-2                             1/1     Running   0             19m
web-0                             1/1     Terminating   0             122m
web-0                             1/1     Terminating   0             122m
web-0                             0/1     Terminating   0             122m
web-0                             0/1     Terminating   0             122m
web-0                             0/1     Terminating   0             122m
web-0                             0/1     Pending       0             0s
web-0                             0/1     Pending       0             0s
web-0                             0/1     ContainerCreating   0             0s
web-0                             0/1     ContainerCreating   0             1s
web-0                             1/1     Running             0             2s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1335425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

地图服务器GeoServer的安装与配置

文章目录 1.安装配置Java2.安装配置Tomcat3 安装配置GeoServer GeoServer提供了多种安装配置方式&#xff0c;但是本质上GeoServer是一个基于Java Web的项目&#xff0c;因此我们理论上只需要安装Java&#xff0c;并且将其放置在一个Web服务器&#xff08;例如Apache Tomcat&am…

Redis缓存穿透、缓存击穿、缓存雪崩介绍

一、Redis的缓存穿透 1.什么是缓存穿透&#xff1f; 缓存穿透是指&#xff1a;客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这时缓存就永远不会生效&#xff0c;这些请求都打到数据库从而导致数据库压力过大。 2.出现缓存穿透的解决方案&#xff0c;以下是常用的两…

解决远程操作报报错函数不支持问题

1、虚拟机远程里面勾了仅允许使用网络.....取消 2、检查虚拟机防火墙是不是没有添加入栈规则 一个ICMPv6一个ICMPv6要开放

SpringMVC:整合 SSM 下篇

文章目录 SpringMVC - 05整合 SSM 下篇一、设计页面1. 首页&#xff1a;index.jsp2. 展示书页面&#xff1a;showBooks.jsp3. 增加书页面&#xff1a;addBook.jsp4. 修改书页面&#xff1a;updateBook.jsp5. 总结 二、控制层1. 查询全部书2. 增加书3. 修改书4. 删除书5. 搜索书…

linux系统和网络(四):网络

本文主要探讨linux网络相关知识,详细介绍看本博客其他博文。 网络基础(参考本博客其他文章&#xff1a;基础网络知识&#xff0c;socket网络编程&#xff0c;基于socket的聊天室和简易ftp) 路由器是局域网和外部网络通信出入口 DNS实现域名和IP地址之间转换 …

Swagger快速入门

1、Swagger快速入门 1.1 swagger介绍 官网&#xff1a;https://swagger.io/ Swagger 是一个规范和完整的Web API框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 功能主要包含以下几点: A. 使得前后端分离开发更加方便&#xff0c;有利于团队协作…

软件测试面试八股文——基础篇

5&#xff09;错误推测法&#xff1a;是基于经验和直觉推测程序中所有可能存在的各种错误&#xff0c;从而有针对性的设计测试用例的方法 6&#xff09;正交实验法 7&#xff09;判定表法 8&#xff09;测试大纲法 3、提交缺陷的八大要素 1&#xff09;缺陷编号&#xff1a…

选择排序之C++实现

描述 选择排序&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。它的基本思想是&#xff1a;每一轮从待排序的数据中选择最小&#xff08;或最大&#xff09;的一个元素&#xff0c;然后与待排序数据的第一个元素交换位置。对剩余未排序的数据重复这个过程&a…

CentOS进入单用户模式

一、重启 二、出现内核选项 按“e” 三、编辑这一行 输入 rw init/sysroot/bin/sh 四、进入单用户模式 ctrlx 进入 五、切换目录 chroot /sysroot 六、然后你就操作你的系统了。 修改密码等等

OCP NVME SSD规范解读-1

OCP&#xff08;Open Compute Project&#xff09;是一个由Facebook于2011年发起的开源项目。其目标是重新设计和优化数据中心的硬件&#xff0c;包括服务器、存储、网络设备等&#xff0c;以提高效率&#xff0c;降低运营成本&#xff0c;并推动技术的创新和标准化。 在OCP中&…

count distinct在spark中的运行机制

文章目录 预备 数据和执行语句Expand第一次HashAggregateShuffle and Second HashAggregate最后结果性能原文 预备 数据和执行语句 SELECT COUNT(*), SUM(items), COUNT(DISTINCT product), COUNT(DISTINCT category) FROM orders;假设源数据分布在两个1核的结点上&#xff0…

Java Web基础详解

回顾 之前的两篇的文章已经大概的带我们了解了tomcat的一些基本的操作&#xff0c;比如从零搭建我们自己的调试环境以及官方文档构建的方式&#xff0c;接下来的话&#xff0c;我将带大家来了解一下tomcat的一些基础知识&#xff0c;这些基础知识将以问题的方式抛出&#xff0…

IDEA Maven Helper插件 解决jar冲突

Jar包冲突报错 程序抛出java.lang.ClassNotFoundException异常&#xff1b; 程序抛出java.lang.NoSuchMethodError异常&#xff1b; 程序抛出java.lang.NoClassDefFoundError异常&#xff1b; 程序抛出java.lang.LinkageError异常等&#xff1b;Maven Jar包管理机制 在Maven项…

《Halcon 100项目-2》Halcon查找零件个数

Halcon查找零件个数 read_image (Image20231225201927, D:/image/bilibili/photo/屏幕截图 2023-12-25 201927.png) rgb1_to_gray (Image20231225201927, GrayImage)threshold (GrayImage, Region, 0, 128) draw_rectangle1 (200000, Row1, Column1, Row2, Column2) gen_recta…

年龄相关的微环境变化突显了PDGF-C在ER+乳腺癌转移复发中的作用

今天给同学们分享一篇实验文章“Age-associated microenvironmental changes highlight the role of PDGF-C in ER breast cancer metastatic relapse”&#xff0c;这篇文章发表在Nat Cancer期刊上&#xff0c;影响因子为22.7。 结果解读&#xff1a; ER乳腺癌转移复发的同种…

三相电机转差率为负值的情形

1.电机开始发电的特征 注意&#xff0c;电机因为有输入频率对原始旋转磁场的影响&#xff0c;在正常工作时&#xff0c;应该处于稳态&#xff0c;因为旋转磁场决定了这个系统的运转方向和运转的大致频率区间。它会处于力矩平衡态。但是&#xff0c;如果&#xff0c;此时电机处…

帕累托森林CEO李朝政博士受邀「OSS-Compass」开源年会畅谈:开源框架下的奇异竞争规则

导语 “怎么在别人知道你的代码和战略时&#xff0c;你仍然拥有壁垒&#xff1f;”这是开源框架下&#xff0c;商业必须思考的问题。 软件驱动世界运转。但当基础层代码失去了有深度活力的“动态延伸”潜力&#xff0c;便会遭致市场“零定价”的宿命。动态延伸的效率&#xf…

MES系统是什么?MES系统的功能有哪些?

在现代制造业的快速发展中&#xff0c;所有规模的企业都面临着类似的挑战&#xff1a;如何提高生产效率、确保产品质量、减少浪费、降低成本&#xff0c;同时迅速响应市场变化。而在这个过程中&#xff0c;传统企业管理往往有以下几个典型痛点&#xff1a; 纸质文件堆叠如山&a…

【MATLAB库函数系列】线性调频Z(Chirp-Z,CZT)的MATLAB源码和C语言实现

在上一篇博客 【数字信号处理】线性调频Z(Chirp-Z,CZT)算法详解 已经详细介绍了CZT变换的应用背景和原理,先回顾一下: 回顾CZT算法 采用 FFT 算法可以很快计算出全部 N N N点 DFT 值,即Z变换 X ( z ) X(z) <

使用Visual Studio调试VisionPro脚本

使用Visual Studio调试VisionPro脚本 方法一 &#xff1a; 修改项目文件 csproj步骤&#xff1a; 方法二 &#xff1a; Visual Studio附加功能步骤&#xff1a; 方法一 &#xff1a; 修改项目文件 csproj 步骤&#xff1a; 开启VisionPro脚本调试功能 创建一个VisionPro程序…