OpenShift 4 - KubeVirt 虚机使用的磁盘和卷

news2025/1/14 2:25:15

《OpenShift / RHEL / DevSecOps 汇总目录》
说明:本文已经在 OpenShift 4.12 环境中验证

文章目录

  • KubeVirt 虚机的磁盘和卷
    • Disk 磁盘
    • Volume 卷
  • 磁盘和卷示例
    • containerDisk 卷示例
    • cloudInitNoCloud 卷示例
    • dataVolume 卷示例
      • 基于容器镜像
      • 基于 qcow2 文件
      • 基于 DataSource
    • persistentVolumeClaim 卷示例
  • 绑定和解绑虚机的 Disk
  • 删除虚机和删除 Disk
  • 参考

KubeVirt 虚机的磁盘和卷

KubeVirt 使用 VirtualMachine 类型的 CRD 用来描述一个 VM,其中在 spec.volumes 部分定义了 VM 使用的卷,在 spec.domain.devices.disks 部分定义了 VM 使用的磁盘,另外卷的名称必须和磁盘的名称保持一样。
在使用 OpenShift 控制台创建 VirtualMachine 的的磁盘时,会自动创建对应的卷,以及对应的 PVC/PV 资源。

Disk 磁盘

运行在 OpenShift 中的 VM 可以使用 2 类磁盘存放 VM 的数据:“基于 PVC 的持久性磁盘” 和 ”基于临时性的容器磁盘”。对于前一种,VM 可以直接使用已有的 PVC,也可以将已有 PVC 克隆一份使用,还可以将传统 VM 使用的磁盘文件(例如 qcow2 文件)或容器镜像中的数据导入到新建的 PVC 中。而对于后一种,所有写入磁盘的数据会在 VM 重启动后丢失,因此该磁盘是临时性的。

在 OpenShift 控制台上创建 VirtualMachine 的磁盘时候,可以使用以下几种目标作为 VM 磁盘的 Source:
在这里插入图片描述

Volume 卷

KubeVirt 的 VirtualMachine 可以使用以下几种常用的存储卷类型:

  1. ephemeral - 其对应的卷 (PVC) 的数据不会以发生变化,因为所有的写入都保存在位于本地存储的临时镜像中。当 VM 停止、重启或删除时,便会丢弃临时镜像。
  2. containerDisk - 从 registry 中拉取镜像到运行 VM 的主机节点上,并在 VM 启动时作为磁盘附加到 VM。containerDisk 提供了在容器镜像注册表中存储和分发 VM 磁盘的能力。不过 containerDisk 是临时的,数据将在 VM 停止、重启或删除时丢弃。
  3. dataVolume - 可动态创建 PVC 并将外部磁盘、镜像、容器数据导入到这些 PVC 中。为了使用 dataVolume 卷,必须借助 OpenShift Virtualization Operator 安装的 Containerized Data Importer (CDI) 功能。如果不使用 dataVolume 卷,那么可以使用 persistentVolumeClaim 卷,即将一个可用的 PVC 分配给 VM。
  4. persistentVolumeClaim - 将可用的 PVC 附加到 VM。将现有 VM 导入到 OpenShift 中的方法是使用 CDI 将现有 VM 的磁盘或容器镜像中的磁盘导入到 PVC 中,然后将 PVC 附加到 VM 实例。
  5. emptyDisk - 为 VM 创建额外的 qcow2 磁盘。当 VM 重启,数据会保留下来,但当重新创建 VM,数据将会被丢弃。
  6. cloudInitNoCloud - 将所引用的 cloudInitNoCloud 数据源附加给磁盘,以便在 VM 启动后自动执行脚本。VM 内部需要安装 cloud-init。

注意:containerDisk 卷必须对应容器镜像,而 dataVolume 卷可以对应容器镜像。如果需要用 containerDisk 和 dataVolume 对应的磁盘启动 VM,需要将 qcow2 封装到容器镜像中。可根据以下链接制作包含虚机磁盘的容器镜像:
https://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/#containerdisk-workflow-example

另外 KubeVirt 还提供 cloudInitConfigDrive、hostDisk、configMap、secret、serviceAccount、downwardMetrics 等类型的存储卷。详细说明可参见:https://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/

磁盘和卷示例

执行命令创建一个项目:

$ oc new-project ocp-vm

containerDisk 卷示例

  1. 根据以下 YAML 创建一个 VM。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: cirros-vm-1
  labels:
    kubevirt.io/vm: cirros-vm-1
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: cirros-vm-1
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: containerdisk
          interfaces:
            - masquerade: {}
              model: virtio
              name: default
        resources:
          requests:
            memory: 128Mi
      hostname: cirros-vm-1
      networks:
        - name: default
          pod: {}
      volumes:
        - containerDisk:
            image: kubevirt/cirros-container-disk-demo:latest
          name: containerdisk
  1. 查看运行的 VM 实例。
$ oc get vmi
NAME          AGE   PHASE     IP             NODENAME             READY
cirros-vm-1   83s   Running   10.217.1.144   crc-rwwzd-master-0   True
  1. 访问 VM 实例的控制台,然后可根据提示登陆操作系统。注意,提示中还有退出 VM 实例控制台的方法。
$ virtctl console cirros-vm-1
Successfully connected to cirros-vm-1 console. The escape sequence is ^]
 
login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
cirros login: 
  1. 在 OpenShift 控制台上查看该 VM 实例的 Disks,确认只有一个 “Container (Ephemeral)” 的磁盘,它没有和 PVC 对应。
    在这里插入图片描述
  2. 在 VM 内部创建一个测试文件,然后退出 VM 实例的控制台。
$ echo hello > hello
  1. 执行命令重启 VM。注意:这里是重启 VM,而不是重启操作系统,因此不要在 VM 中通过 reboot 命令重启操作系统。
$ virtctl restart cirros-vm-1
VM cirros-vm-1 was scheduled to restart
  1. 执行命令查看运行 VM 的 Pod 实例,可以看到一个新的 Pod 会取代原有 Pod 来运行 VM。注意:通过 reboot 命令重启操作系统不会更换运行 VM 的 Pod。
$ oc get pod -w | grep cirros-vm-1
virt-launcher-cirros-vm-1-ghllv                             2/2     Terminating   0          10m
virt-launcher-cirros-vm-1-ghllv                             0/2     Terminating   0          10m
virt-launcher-cirros-vm-1-ghllv                             0/2     Terminating   0          10m
virt-launcher-cirros-vm-1-ghllv                             0/2     Terminating   0          10m
virt-launcher-cirros-vm-1-djchh                             0/2     Pending       0          0s
virt-launcher-cirros-vm-1-djchh                             0/2     Pending       0          0s
virt-launcher-cirros-vm-1-djchh                             0/2     Pending       0          0s
virt-launcher-cirros-vm-1-djchh                             0/2     Init:0/2      0          0s
virt-launcher-cirros-vm-1-djchh                             0/2     Init:0/2      0          2s
virt-launcher-cirros-vm-1-djchh                             0/2     Init:1/2      0          4s
virt-launcher-cirros-vm-1-djchh                             0/2     PodInitializing   0          10s
virt-launcher-cirros-vm-1-djchh                             2/2     Running           0          16s
  1. 在重启 VM 后再次进入 VM 的控制台,确认 hello 文件已经不存在了。

cloudInitNoCloud 卷示例

  1. 根据以下 YAML 创建一个 VM。它使用了 quay.io/containerdisks/fedora:36 容器镜像,并将其中内容复制到 PVC,然后作为 VM 的磁盘。注意:这里使用了 cloudInitNoCloud 卷可实现在 VM 启动完后运行初始化脚本。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: fedora-vm-1
  labels:
    kubevirt.io/vm: fedora-vm-1
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: fedora-vm-1
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - masquerade: {}
              model: virtio
              name: default
        resources:
          requests:
            memory: 2Gi
      hostname: fedora-vm-1
      networks:
        - name: default
          pod: {}
      volumes:
        - name: rootdisk
          containerDisk:
            image: 'quay.io/containerdisks/fedora:36'
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: fedora
              password: fedora
              chpasswd: { expire: False }
          name: cloudinitdisk
  1. 进入 fedora-vm-1 的 Console,确认只能用 fedora/fedora 登陆。

dataVolume 卷示例

基于容器镜像

本示例使用了包含 qcow2 的 quay.io/dawnskyliu/rhel-guest-image 容器镜像作为 dataVolume。

  1. 根据以下 YAML 创建一个 VM。注意:该 VM 是通过 dataVolume 卷使用的容器镜像 quay.io/dawnskyliu/rhel-guest-image,即是先将容器镜像中在 qcow2 或 RAW 包含内容导入到一个 PV,然后 VM 在使用 PV 启动,因此该 VM 中被修改的内容不会因为重启而丢失。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: rhel8-vm-1
  labels:
    kubevirt.io/vm: rhel8-vm-1
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        name: rhel8-vm-1
      spec:
        source:
          registry:
            url: 'docker://quay.io/dawnskyliu/rhel-guest-image'
        storage:
          resources:
            requests:
              storage: 30Gi
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: rhel8-vm-1
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - masquerade: {}
              model: virtio
              name: default
        resources:
          requests:
            memory: 2Gi
      networks:
        - name: default
          pod: {}
      volumes:
        - dataVolume:
            name: rhel8-vm-1
          name: rootdisk
        - cloudInitNoCloud:
            userData: |
              #cloud-config
              user: rhel
              password: password
              chpasswd:
                expire: false
          name: cloudinitdisk
  1. 运行命令,确认有以下 Pod,该 Pod 会将将容器镜像中的 disk/rhel-guest-image-8.7-1826.x86_64.qcow2 导入到 PV。
$ oc get pod importer-rhel8-vm-1
NAME                  READY   STATUS    RESTARTS   AGE
importer-rhel8-vm-1   1/1     Running   0          84s
 
$ oc logs pod/importer-rhel8-vm-1
I0408 10:31:52.123937       1 importer.go:104] Starting importer
I0408 10:31:52.124039       1 importer.go:171] begin import process
I0408 10:31:52.124225       1 registry-datasource.go:173] Copying proxy certs
I0408 10:31:52.124262       1 registry-datasource.go:58] Error creating allCertDir open /proxycerts/: no such file or directory
I0408 10:31:52.124517       1 data-processor.go:379] Calculating available size
I0408 10:31:52.124567       1 data-processor.go:391] Checking out file system volume size.
I0408 10:31:52.124588       1 data-processor.go:399] Request image size not empty.
I0408 10:31:52.124624       1 data-processor.go:404] Target size 34087042032.
I0408 10:31:52.124802       1 data-processor.go:282] New phase: TransferScratch
I0408 10:31:52.124870       1 registry-datasource.go:93] Copying registry image to scratch space.
I0408 10:31:52.124912       1 transport.go:176] Downloading image from 'docker://quay.io/dawnskyliu/rhel-guest-image', copying file from 'disk' to '/scratch'
I0408 10:31:55.330906       1 transport.go:200] Processing layer {Digest:sha256:32dafd2b928f720b5b234cf4a73e9c8ad30794523dff90c53acb33393513e91c Size:839850948 URLs:[] Annotations:map[] MediaType:application/vnd.docker.image.rootfs.diff.tar.gzip CompressionOperation:0 CompressionAlgorithm:<nil> CryptoOperation:0}
I0408 10:31:58.126354       1 transport.go:152] File 'disk/rhel-guest-image-8.7-1826.x86_64.qcow2' found in the layer
I0408 10:31:58.126952       1 util.go:192] Writing data...

$ oc get pvc
NAME                 STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                   AGE
rhel8-vm-1           Bound     pvc-08595a65-a2c6-4c20-af66-0d2d153f6eea   199Gi      RWO            crc-csi-hostpath-provisioner   95s
rhel8-vm-1-scratch   Bound     pvc-51b1c5ab-88d3-4886-9186-cb63da8bdd7c   199Gi      RWO            crc-csi-hostpath-provisioner   85s
  1. 进入 rhel8-vm-1 的 Console,确认只能用 rhel/password 登陆。
  2. 在 VM 中的缺省目录中创建一个测试文件。
  3. 重启 VM,确认可继续在该 VM 中访问测试文件。

基于 qcow2 文件

本示例使用了 https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2.xz 文件作为 dataVolume。

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  labels:
    kubevirt.io/vm: centos7-vm-1
  name: centos7-vm-1
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        name: centos7-vm-1
      spec:
        pvc:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 30Gi
        source:
          http:
            url: "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2.xz"
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/vm: centos7-vm-1
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
            - name: datavolumedisk
              disk:
                bus: virtio
            - name: cloudinitdisk
              disk:
                bus: virtio
          interfaces:
            - masquerade: {}
              model: virtio
              name: default
        resources:
          requests:
            memory: 2Gi
      hostname: centos7-vm-1
      networks:
        - name: default
          pod: {}
      volumes:
        - dataVolume:
            name: centos7-vm-1
          name: datavolumedisk
        - cloudInitNoCloud:
            userData: |
              #cloud-config
              user: centos
              password: password
              chpasswd:
                expire: false
          name: cloudinitdisk

基于 DataSource

本示例使用了名为 centos-stream8 的 DataSource 作为 dataVolume。一个 DataSource 其实就是一个关联好容器镜像的 PVC。
在这里插入图片描述

  1. 执行命令查看名为 centos-stream9 的 datasource 对应的 PVC。
$ PVC_NAME=$(oc get datasource centos-stream9 -n openshift-virtualization-os-images -o jsonpath='{.spec.source.pvc.name}')
  1. 根据 PVC 查看对应使用的容器镜像。
$ oc get pvc $PVC_NAME -n openshift-virtualization-os-images -o go-template=$'{{index .metadata.annotations "cdi.kubevirt.io/storage.import.endpoint"}}\n'
docker://quay.io/containerdisks/centos-stream@sha256:5a2cd12e0ea1667e0fc55cca09957e310fbabfb91438736d00ebff1d60d4e2c4
  1. 根据 centos-stream8 的 DataSource 创建 VM。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  labels:
    kubevirt.io/vm: centos-stream8-vm-1
  name: centos-stream8-vm-1
spec:
  dataVolumeTemplates:
  - apiVersion: cdi.kubevirt.io/v1beta1
    kind: DataVolume
    metadata:
      name: centos-stream8-vm-1-dv
    spec:
      sourceRef:
        kind: DataSource
        name: centos-stream8
        namespace: openshift-virtualization-os-images
      storage:
        resources:
          requests:
            storage: 30Gi
  running: false
  template:
    metadata:
      labels:
        kubevirt.io/domain: centos-stream8-vm-1
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
          - disk:
              bus: virtio
            name: rootdisk
          - disk:
              bus: virtio
            name: cloudinitdisk
          interfaces:
          - masquerade: {}
            name: default
        resources:
          requests:
            memory: 2Gi
      networks:
      - name: default
        pod: {}
      volumes:
      - dataVolume:
          name: centos-stream8-vm-1-dv
        name: rootdisk
      - cloudInitNoCloud:
          userData: |-
            #cloud-config
            user: centos
            password: 'password' 
            chpasswd: { expire: False }
        name: cloudinitdisk

persistentVolumeClaim 卷示例

  1. 根据以下 YAML 创建 cirros-vm-2 虚机。它直接使用了引用 http://download.cirros-cloud.net/0.5.2/cirros-0.5.2-x86_64-disk.img 文件的 dataVolume 作为 VM 的 volume 的源。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: cirros-vm-2
  labels:
    kubevirt.io/vm: cirros-vm-2
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        name: cirros-vm-2-dv
      spec:
        pvc:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 120M
        source:
          http:
            url: http://download.cirros-cloud.net/0.5.2/cirros-0.5.2-x86_64-disk.img
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: cirros-vm-2
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: cirros-vm-2
          interfaces:
            - masquerade: {}
              name: default
        resources:
          requests:
            memory: 128M
      networks:
        - name: default
          pod: {}
      volumes:
        - dataVolume:
            name: cirros-vm-2-dv
          name: cirros-vm-2
  1. 为了对比,我们可先以下 YAML 创建 PVC,然后再在后面创建的 VM 中使用这个 PVC。注意:在创建使用该 PVC 的 VM 时候,KubeVirtl 的 CDI 组建会将该 PVC 的 annotations 引用的 img 文件所包含的内容导入到该 PVC 中。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: "cirros-vm-2-pvc"
  labels:
    app: containerized-data-importer
  annotations:
    cdi.kubevirt.io/storage.import.endpoint: "http://download.cirros-cloud.net/0.5.2/cirros-0.5.2-x86_64-disk.img"
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 120Mi
  1. 查看 PVC 的状态。在它没有被使用之前,PVC 是 Pending 状态。
$ oc get pvc
NAME              STATUS    VOLUME                 CAPACITY   ACCESS MODES   STORAGECLASS                   AGE
cirros-vm-2-pvc   Pending                                                    crc-csi-hostpath-provisioner   34s
  1. 创建一个 VM,它通过 persistentVolumeClaim 类型的 volume 使用了上面创建的 PVC。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  labels:
    kubevirt.io/vm: cirros-vm-3
  name: cirros-vm-3
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: cirros-vm-3
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
          - disk:
              bus: virtio
            name: cirros-vm-3
          interfaces:
          - masquerade: {}
            name: default
        resources:
          requests:
            memory: 128M
      networks:
      - name: default
        pod: {}
      volumes:
      - name: cirros-vm-3
        persistentVolumeClaim:
          claimName: cirros-vm-3-pvc
  1. 确认 PVC 已经和 PV 绑定。
$ oc get pvc
NAME              STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                   AGE
cirros-vm-2-pvc   Bound     pvc-107fe367-41e5-44f5-9617-0cfd7841b2ff   199Gi      RWO            crc-csi-hostpath-provisioner   34s
  1. 确认可以登陆本节创建的 2 个 VM。

绑定和解绑虚机的 Disk

可以为虚机添加 Disk,在控制台添加 Disk 的窗口如下,可以看出大部分 Disk 使用的都是 PVC 存储数据。
在这里插入图片描述
默认情况,当删除 VM 的时候会自动删除用到的 PVC 和 PV。如果需要保存 PVC 和 PV,需要先将 VM 和用到的 Disk 解绑后再删除 VM。在 OpenShift 控制台的 VM 管理页面的 Disks 中使用 Detach 解绑 Disk 和 VM。解绑后再删除 VM 就不会自动删除 PVC 和 PV。
在这里插入图片描述

删除虚机和删除 Disk

  1. 如果通过控制台删除 VM,可以选择是否删除对应的 Disk。而删除 Disk 会删除对应的 PVC 和 PV。
    在这里插入图片描述
  2. 如果通过命令删除 VM,默认会确认对应的 PVC 和 PV 都会被自动删除。
$ oc get pvc rhel8-vm-1 
rhel8-vm-1               Bound    pvc-107fe367-41e5-44f5-9617-0cfd7841b2ff   199Gi      RWO            crc-csi-hostpath-provisioner   14h

$ oc delete vm rhel8-vm-1 
virtualmachine.kubevirt.io "rhel8-vm-1" deleted

$ oc get pvc rhel8-vm-1 
Error from server (NotFound): persistentvolumeclaims "rhel8-vm-1" not found
  1. 可以查看 PV 的 persistentVolumeReclaimPolicy 配置,确认是缺省是 “Delete”。
$ oc get pv <pv_name> -o yaml | grep 'persistentVolumeReclaimPolicy'
  persistentVolumeReclaimPolicy: Delete
  1. 执行命令,可将 PV 的 persistentVolumeReclaimPolicy 默认配置改为 “Retain“。
$ oc patch pv <pv_name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
  1. 这样再删除 VM 就不会自动删除对应的 PVC 和 PV 了。

参考

https://kubevirt.io/2018/CDI-DataVolumes.html
https://liujinye.gitbook.io/openshift-docs/kubevirt/kubebirt-zhong-shi-yong-cloudinit
https://cloud.redhat.com/blog/openshift-virtualization-containers-kvm-and-your-vms
https://github.com/kubevirt/containerized-data-importer

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

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

相关文章

放大招:三步搞定ChatGPT提示词,轻松写出高质量提问,最新经验分享

在撰写ChatGPT提示语的时候&#xff0c;有一个基本的三层结构&#xff0c;经过在工作和生活上的实践&#xff0c;有助于解决大多数不同类型的任务。 尤其在你的问题有点复杂&#xff0c;想不清楚要怎么问比较好的时候&#xff0c;通过三层结构&#xff0c;让我们有结构的提出问…

力扣简单题

目录 9、回文数 13、罗马数字转整数 14、最长公共前缀 20、有效的括号 58、最后一个单词的长度 66、加一 69、x的平方根 94、二叉树的中序遍历 100、相同的树 202、快乐数 205、同构字符串 242、有效的字母异位词 258、各位相加 268、丢失的数字 290、单词…

Github 使用教学

&#x1f4ad; 写在前面&#xff1a;本章我们将介绍 Git 的基本使用方法&#xff0c;包括注册 GitHub 账号、设置 Git、创建本地存储库、复制本地存储库、导入远程存储库、追加、提交、合并等常用操作。我们还会教你如何在 GitHub 上创建项目&#xff0c;使用 git clone 命令克…

盘“底座”,盘出新生意经

本文转自首席信息官 作者 徐蕊 导读 卖“底座”&#xff0c;这是一门新的生意&#xff0c;也是用友与友商差异化的商业竞争优势所在。 大型企业都在建“数智化底座” 有这样两类企业&#xff0c;他们截然不同&#xff0c;但在数智化的建设上殊途同归。 随着中国经济的发展&a…

SLAM论文速递:经典动态SLAM解析—(2021)DP-SLAM:面向动态环境的移动概率视觉SLAM—5.08(1)

论文信息 题目&#xff1a; DP-SLAM:A visual SLAM with moving probability towards dynamic environments DP-SLAM:面向动态环境的移动概率视觉SLAM论文地址&#xff1a; 发表期刊&#xff1a; 标签 语义分割几何约束、动态概率传播、 摘要 文中提出了一种基于稀疏特征的视觉…

DDD分层架构浅析

大家好&#xff0c;我是易安&#xff01;今天我们聊下DDD分层架构 微服务架构模型有好多种&#xff0c;例如整洁架构、CQRS和六边形架构等等。每种架构模式虽然提出的时代和背景不同&#xff0c;但其核心理念都是为了设计出“高内聚低耦合”的架构&#xff0c;轻松实现架构演进…

【P12】JMeter 准确的吞吐量定时器(Precise Throughput Timer)

&#xff08;1&#xff09;、测试计划右键 <<< 添加 <<< 定时器 <<< 准确的吞吐量定时器&#xff08;Precise Throughput Timer&#xff09; 目标吞吐量&#xff08;每个“吞吐期”的样本&#xff09;&#xff1a;15.0 吞吐量周期&#xff08;秒&a…

ArcGIS植被覆盖度计算与栅格计算

遥感&#xff0c;顾名思义就是遥远的感知。就是利用飞机、卫星等平台对地球进行观测并获取数据。这里的数据可以使光谱数据、磁场数据等。今天我们就用一个简单的例子来说明ArcGIS对遥感数据的处理&#xff0c;但是ArcGIS处理遥感并没有其他专业遥感软件如ENVI那样强大&#xf…

(转载)04.Matplotlib-文本注释数学表达式设置

1. matplotlib.pyplot.text 文本基本参数设置 2. matplotlib.pyplot.annotate 注释基本参数设置 Matplotlib 支持绘制 TeX 包含的数学符号。TeX 是一套功能强大、十分灵活的排版语言&#xff0c;它可以用来绘制文本、符号、数学表达式等。通过下表中的方法可以绘制出相应的内容…

Java基础学习(13)

Java基础学习 一、File1.1 File详情1.2 File常见的成员方法1.2.1 判断获取1.2.2 创建删除1.2.3 获取遍历 二、IO流2.1 IO流体系2.2 FileOutputStream2.2.1 FileOutputStream写数据的3种方式2.2.2 FileOutputStream换行写:2.2.3 FileOutputStream续写 2.3 FilelnputStream拷贝文…

Go语言中的流程控制语句

目录 流程控制语句 if语句 ifelse语句 switch语句 for循环 break语句 continue语句 goto语句 流程控制语句 if语句 在Go语言中&#xff0c;可以在if后面加上一段执行语句&#xff0c;执行语句也可以用作对if条件的判断。它的语法格式为&#xff1a; if a : conditio…

MySQL_3 数据库的“CRUD“

目录 一、添加数据 1.基本语法 : 2.代码演示 : 二、查找数据 1.基本语法 : 2.代码演示 : 3.查询中的计算 : 4.WHERE子句的扩展 : 5.排序查询 : 三、修改数据 1.基本语法 : 2.代码演示 : 四、删除数据 1.基本语法 : 2.代码演示 : 一、添加数据 1.基本语法 : INS…

吹爆,全网第一个手把手教你从零开始搭建Spring Cloud Alibaba的笔记

Spring Cloud Alibaba 是阿里巴巴提供的微服务开发一站式解决方案&#xff0c;是阿里巴巴开源中间件与 Spring Cloud 体系的融合。 Springcloud 和 Srpingcloud Alibaba 区别&#xff1f; SpringCloud&#xff1a; 部分组件停止维护和更新&#xff0c;给开发带来不便;SpringCl…

stm32103ZET6使用编码器(磁电增量式)

这里写目录标题 磁电增量式编码器介绍TIM定时器&#xff08;编码器接口模式&#xff09;一些用到的算法均值滤波冒泡排序&#xff08;从小到大&#xff09;一阶低通滤波 编码器测数代码编码器接口HAL库函数 正点原子的电机例程(原例程用的是stm32f407&#xff0c;我这里改成用s…

ClickHouse:对不同类型Join的支持

ClickHouse 是一个流行的开源实时分析数据库&#xff0c;旨在为需要在大量数据上进行超低延迟分析查询的用例提供最佳性能。为了在分析应用程序中实现最佳性能&#xff0c;通常需要将表组合在一起进行数据非规范化处理。扁平化表通过避免联接来帮助最小化查询延迟&#xff0c;以…

从零开始学【网络安全】

前言&#xff1a;网络安全如何从零开始学习&#xff0c;少走弯路&#xff1f; 目录&#xff1a; 一&#xff0c;怎么入门&#xff1f; 1、Web 安全相关概念&#xff08;2 周&#xff09;2、熟悉渗透相关工具&#xff08;3 周&#xff09;3、渗透实战操作&#xff08;5 周&…

DevData Talks | 思码逸陆春蕊:研发效能度量落地的难点与计策

本期 DevData Talks 直播活动邀请到的重磅嘉宾是思码逸高级咨询专家陆春蕊老师。陆春蕊老师曾就职于Oracle&#xff0c;在软件质量、项目管理方面有着丰富的经验&#xff0c;在思码逸为上百家客户提供了研发效能体系、数据分析、实践落地等方面的咨询。 陆春蕊老师与我们聊了聊…

QML绘图便捷接口类Convenient API

在绘制矩形时&#xff0c;我们提供了一个便捷的接口&#xff0c;而不需要调用stroke或者fill来完成。 3.import QtQuick 2.0 4. 5.Canvas { 6. id: root 7. width: 120; height: 120 8. onPaint: { 9. var ctx getContext("2d") 10. ctx.fi…

了解进程控制

目录 1、基本概念 2、操作系统内核 2.1支撑功能 2.2资源管理功能 3、进程的创建 3.1进程的层次结构 3.2进程图 3.3引起创建进程的事件 3.4进程的创建 4、进程的终止 4.1引起进程终止的事件 4.2进程的终止过程 5、进程阻塞与唤醒 5.1引起进程阻塞和唤醒的事件 5.2进…

老测试告诉你自动化测试需要考虑什么?

写在前面 这篇文章译自著名测试专家James Bach的《Test Automation Snake Oil》一文&#xff0c;是笔者在学习和研究探索性测试时偶然发现的一篇较有意义的文章&#xff0c;很好地解答了我们对自动化测试的疑惑。 比如万能的自动化测试是否可以替代一切&#xff0c;还给我们提…