K8S Storage

news2024/11/13 12:14:30

概述

一般情况下,K8S中的Pod都不应该将数据持久化到Pod中,因为Pod可能被随时创建和删除(扩容或缩容),即便是StatefulSet或Operator的Pod,也都不建议在Pod里存放数据,可以将数据持久化到Host上。K8S提供了非常丰富的存储相关的功能,使得我们可以方便的让Pod访问存储设备。K8S通过Volume挂载的方式让Pod来访问存储设备,Volume与Pod绑定并与Pod有相同的生命周期,Volume在Pod中定义,而Pod中的容器只需要使用volumeMounts就可以使用在Pod中定义的Volume。

Pod可以引用的Volume包含以下几类:

  • K8S内部的资源对象:ConfigMap,Secret,DownwardAPI,Projected Volume等。
  • Node上的资源:emptyDir,hostPath。
  • 持久化存储或网络存储:CephFS,FC,CSI,iSCSI,NFS,RBD等。
  • 存储厂商提供的存储卷:ScaleIO Volumes,StorageOS,VsphereVolume等。
  • 公有云提供的存储卷:AWS EBS,AzureDisk,AzureFile,GCE PersistentDisk等。

总之,在K8S Pod中能够使用几乎所有的存储类型和方式。特别的,通过K8S CSI(Container Storage Interface),我们还可以开发自己的存储访问插件,接入到特定的存储设备中。

Node本地存储

Node本地存储包含emptyDirhostPath两种类型。emptyDir用于存储临时数据,如缓存,删除Pod的时候会自动被清理,emptyDir可以指定成Memory类型,但会被统计成容器使用的内存。hostPath用于挂载Node的某个目录,对于大部分应用来说,都不应该直接使用hostPath,因为如果Pod被调度到了其它节点,其就无法访问到之前节点的hostPath中的数据。另外,hostPath上使用的数据不会被计算到存储资源使用统计,可能出现磁盘占满而没有提醒的情况。但如果Pod只会被调度到某个Node上,那么还是可以使用hostPath。

PV/PVC

PV是Persistent Volume,即持久化卷,是K8S最常用的存储访问方式,几乎所有的外部存储都可以通过PV来访问。

PVC是Persistent Volume Claim,即持久化卷声明,通过PVC来申请对PV的使用。PV和PVC是一一对应关系,PV只有通过PVC关联后,才能被使用。Pod通过volumeMounts来关联PVC。

PV通常由管理员来创建,管理员事先分配好一定数量的PV供Pod使用,不同的存储类别(NFS,Cloud,Ceph等)最后都对应成一系列的PV。

PVC通常由Pod来创建,在需要使用存储的时候通过PVC来申请PV。

以下是PV/PVC的关系图,

下面通过NFS来介绍PV/PVC的使用,

先搭建一个双节点的K8S集群(略),参考 K8S 概述。

接着在master节点上搭建NFS服务,主要命令如下,

# On Server:
sudo apt update
sudo apt install nfs-kernel-server
mkdir -p /home/sunny/nfs/root
echo "/home/sunny/nfs/root *(rw,sync,no_subtree_check)" | sudo tee -a /etc/exports
sudo exportfs -ra
sudo systemctl start nfs-kernel-server
sudo systemctl enable nfs-kernel-server

# On Client:
sudo apt install nfs-common
sudo mount 192.168.126.16:/home/sunny/nfs/root /mnt

创建PV,pv.yaml,这里会指定NFS IP和路径,

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
  labels:
    type: nginx-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /home/sunny/nfs/root
    server: 192.168.126.16
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl apply -f pv.yaml
persistentvolume/nginx-pv created
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nginx-pv   1Gi        RWX            Retain           Available                                   3s

创建PVC,pvc.yaml,

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
  namespace: default
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl apply -f pvc.yaml
persistentvolumeclaim/nginx-pvc created
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc   Bound    nginx-pv   1Gi        RWX                           2s
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
nginx-pv   1Gi        RWX            Retain           Bound    default/nginx-pvc                           2m59s

可以看出,此时PVC的状态是Bound,说明其已经找到了一个与此关联的PV,而PV的状态也由之前的Available变为Bound,且CLAIM是default/nginx-pvc,先就可以在Pod里使用这个PVC了。默认PV和PVC的回收策略都是Retain,需要手动删除数据,即便PV和PVC都被删除。

创建Nginx Pod,nginx.yaml,在配置文件中引用PVC,

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: nginx-pvc
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment created
sunny@xxx:~/k8s/storage/pvc_pv$ kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE                     NOMINATED NODE   READINESS GATES
nginx-deployment-574dc457cf-8ds25   1/1     Running   0          53s   10.244.96.163   r05u36-nex-wvie-spr-cd   <none>           <none>
nginx-deployment-574dc457cf-fnn9z   1/1     Running   0          53s   10.244.2.220    r05u30-nex-wvie-spr-cd   <none>           <none>
nginx-deployment-574dc457cf-h4kkk   1/1     Running   0          53s   10.244.96.162   r05u36-nex-wvie-spr-cd   <none>           <none>

在NFS服务器对应的路径上创建一个index.html文件,供Nginx使用,

sunny@r05u30-nex-wvie-spr-cd:~/nfs/root$ pwd
/home/sunny/nfs/root
sunny@r05u30-nex-wvie-spr-cd:~/nfs/root$ cat index.html
Hello Nginx with PV/PVC.
sunny@r05u30-nex-wvie-spr-cd:~/nfs/root$

由于3个Nginx Pod都关联到了同一个NFS路径,所以通过任何一个Pod都能访问到相同的index.html。如果Pod扩容,新的Pod使用的也是相同的NFS路径,所以这里就非常容易的实现了数据和代码的分离,无论代码部署到哪里,无论代码如何改变,数据都是统一存储的。

sunny@xxx:~/k8s/storage/pvc_pv$ wget 10.244.2.220
--2024-03-21 01:45:21--  http://10.244.2.220/
Connecting to 10.244.2.220:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 25 [text/html]
Saving to: ‘index.html’

index.html                                        100%[===========================================================================================================>]      25  --.-KB/s    in 0s

2024-03-21 01:45:21 (1.68 MB/s) - ‘index.html’ saved [25/25]

sunny@xxx:~/k8s/storage/pvc_pv$ cat index.html
Hello Nginx with PV/PVC.
sunny@xxx:~/k8s/storage/pvc_pv$ wget 10.244.96.163
--2024-03-21 01:47:36--  http://10.244.96.163/
Connecting to 10.244.96.163:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 25 [text/html]
Saving to: ‘index.html.1’

index.html.1                                      100%[===========================================================================================================>]      25  --.-KB/s    in 0s

2024-03-21 01:47:36 (79.9 KB/s) - ‘index.html.1’ saved [25/25]

sunny@xxx:~/k8s/storage/pvc_pv$ cat index.html
Hello Nginx with PV/PVC.

StorageClass/PVC

PV/PVC确实能实现几乎所有存储的统一访问,但有一个问题是PV需要由管理员事先创建好,如果创建PVC的时候没有可用的PV,则PVC的状态会一直是Pending。不同的Pod可能需要不同规格和类型的PV,管理员需要创建和维护数量巨大的PV,这无疑是增加了K8S集群管理员的负担。

StorageClass可以解决上面的问题。当我们在创建PVC的时候可以指定一个StorageClass,PVC在创建过程中会根据StorageClass的描述自动创建需要的PV,不用管理员手动创建。

以下是StorageClass/PVC的关系图,

下面通过NFS来介绍StorageClass/PVC的使用,

搭建K8S和NFS参考上面内容。

StorageClass通过Provisioner来创建PV,Provisioner有很多,不同的存储类别有不同的实现,是第三方的组件。Provisioner要创建PV,意味着其能访问K8S集群,需要为其分配权限。

创建RBAC(Role Based Access Control),rbac.yaml,

apiVersion: v1
kind: Namespace
metadata:
  name: nginxns
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: nginxns
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: managed-run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: nginxns
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: nginxns
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: nginxns
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: nginxns
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
sunny@xxxx:~/k8s/storage/storageclass$ kubectl apply -f rbac.yaml
namespace/nginxns created
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/managed-run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created

创建Storage Class, storage_class.yaml,这里会定义storage class名称,在创建PVC的时候会使用,以及与之关联的provisioner,

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
  namespace: nginxns
provisioner: provisioner-nfs-storage
parameters:
  archiveOnDelete: "false"
sunny@xxx:~/k8s/storage/storageclass$ kubectl apply -f storage_class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
sunny@r05u30-nex-wvie-spr-cd:~/k8s/storage/storageclass$

创建 NFS provisioner,nfs-provisioner.yaml,这里面会指定provisioner名称,NFS地址,路径,serviceAccountName等,

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  namespace: nginxns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          #image: quay.io/external_storage/nfs-client-provisioner:latest
          image: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: provisioner-nfs-storage
            - name: NFS_SERVER
              value: 192.168.126.16
            - name: NFS_PATH
              value: /home/sunny/nfs/root
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.126.16
            path: /home/sunny/nfs/root
sunny@xxx:~/k8s/storage/storageclass$ kubectl apply -f nfs-provisioner.yaml
deployment.apps/nfs-client-provisioner created

创建PVC,pvc.yaml,在这里会指定storageClassName,

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
  namespace: nginxns
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: managed-nfs-storage
  resources:
    requests:
      storage: 5Mi
sunny@xxx:~/k8s/storage/storageclass$ kubectl apply -f pvc.yaml
persistentvolumeclaim/test-claim created
sunny@xxx:~/k8s/storage/storageclass$ kubectl get pvc -n nginxns
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
test-claim   Bound    pvc-03905a65-efe4-4a5d-a10c-f5b50f026c4c   5Mi        RWX            managed-nfs-storage   12s
sunny@xxx:~/k8s/storage/storageclass$ kubectl get pv -n nginxns
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS          REASON   AGE
pvc-03905a65-efe4-4a5d-a10c-f5b50f026c4c   5Mi        RWX            Delete           Bound    nginxns/test-claim   managed-nfs-storage            41s

创建完PVC以后,可以看到pv也自动创建好了,且NFS根目录下也创建了相关的供PV使用的目录,在该目录中增加index.html,

sunny@xxx:~/nfs/root$ pwd
/home/sunny/nfs/root
sunny@xxx:~/nfs/root$ ll
total 0
drwxrwxrwx 3 sunny  sunny   73 Mar 21 02:30 ./
drwxrwxrwx 3 sunny  sunny   18 Mar 20 02:06 ../
drwxrwxrwx 2 nobody nogroup  6 Mar 21 02:30 nginxns-test-claim-pvc-03905a65-efe4-4a5d-a10c-f5b50f026c4c/
sunny@xxx:~/nfs/root$ cd nginxns-test-claim-pvc-03905a65-efe4-4a5d-a10c-f5b50f026c4c/
sunny@xxx:~/nfs/root/nginxns-test-claim-pvc-03905a65-efe4-4a5d-a10c-f5b50f026c4c$ cat index.html
Hello Storage Class.

创建Nginx,nginx.yaml,

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-storageclass
  namespace: nginxns
spec:
  selector:
    matchLabels:
      app: nginx-storageclass
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx-storageclass
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: test-claim
sunny@xxx:~/k8s/storage/storageclass$ kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment-storageclass created
sunny@xxx:~/k8s/storage/storageclass$ kubectl get pod -n nginxns -o wide
NAME                                             READY   STATUS    RESTARTS   AGE   IP              NODE                     NOMINATED NODE   READINESS GATES
nfs-client-provisioner-7c5d5f57b-shrd8           1/1     Running   0          37m   10.244.96.164   r05u36-nex-wvie-spr-cd   <none>           <none>
nginx-deployment-storageclass-86bb9496f8-5mpvg   1/1     Running   0          18s   10.244.2.221    r05u30-nex-wvie-spr-cd   <none>           <none>
nginx-deployment-storageclass-86bb9496f8-c8zbp   1/1     Running   0          18s   10.244.96.166   r05u36-nex-wvie-spr-cd   <none>           <none>
nginx-deployment-storageclass-86bb9496f8-z4sxm   1/1     Running   0          18s   10.244.96.165   r05u36-nex-wvie-spr-cd   <none>           <none>

访问Pod,

sunny@xxx:~/k8s/storage/storageclass$ wget 10.244.2.221
--2024-03-21 03:06:12--  http://10.244.2.221/
Connecting to 10.244.2.221:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 21 [text/html]
Saving to: ‘index.html’

index.html                                        100%[===========================================================================================================>]      21  --.-KB/s    in 0s

2024-03-21 03:06:12 (53.6 KB/s) - ‘index.html’ saved [21/21]

sunny@xxx:~/k8s/storage/storageclass$ cat index.html
Hello Storage Class.

StorageClass确实能自动创建PV,减少管理员准备PV的工作,但是我们也发现StorageClass的配置多了不少,需要定义RBAC,StorageClass等资源对象,需要创建provisioner这个额外的Pod等。所以,如果在一些复杂场景下需要频繁创建和维护PV,我们可以使用StorageClass + PVC的模来使用存储,如果在一些简单的场景下只需要一些固定的PV,我们可以使用PV + PVC的模式来使用存储。

CSI

在 Kubernetes 中,存储插件的开发主要有以下几种方式:

  1. CSI插件:Container Storage Interface (CSI) 是 Kubernetes 的标准插件接口,是全新的插件方案,插件和驱动调用通过grpc协议,功能丰富,支持存储卷动态提供、快速、动态扩容等等。
  2. FlexVolume插件:FlexVolume 是 Kubernetes 的早期存储插件接口之一,它提供了一个简单的接口,但局限性却很大,用于将存储驱动程序接入到 Kubernetes 中。通过实现 FlexVolume 接口,可以将各种存储系统接入到 Kubernetes 集群中,包括 NFS、GlusterFS、Ceph 等等。
  3. in-tree插件:in-tree 存储插件是 Kubernetes 的早期存储插件接口之一,它将存储驱动程序嵌入到 Kubernetes 主体代码库中。in-tree 插件可以实现对本地存储、NFS、iSCSI 等存储系统的支持。不过,由于 in-tree 插件需要嵌入到 Kubernetes 主体代码库中,因此对于插件开发者而言,维护成本较高,并且需要适应 Kubernetes 主体代码库的版本变化。

CSI 全称 Container Storage Interface,是容器编排系统(CO)如k8s等扩展容器存储的一种实现方式,基于gRPC实现,是当前主流的存储扩展方式。为什么会使用CSI?首先,CSI 可以满足不同编排系统的需求,除了k8s,还可以比如 Mesos,Swarm。其次,CSI 是容器化部署,可以减少环境依赖,增强安全性,丰富插件的功能。CSI 的设计思想,把插件的职责从之前讲的 “两阶段处理”,扩展成了 Provision、Attach 和 Mount 三个阶段。

CSI 主要包含两个部分:CSI Controller Server 与 CSI Node Server。

  • Controller Server 是控制端的功能,负责将卷与具体节点进行配置,每个集群中只需要有一个Controller提供服务。
  • Node Server 负责k8s负载节点上的卷配置,每个节点都有一个Node提供服务。

CSI部署架构,

参考:

CSI规范

k8s-编写CSI插件

CSI 插件开发简介

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

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

相关文章

本地丐版运行xAI grok-1的尝试(失败版)

前言 xAI开源了包含3000多亿参数的grok-1&#xff0c;想试试在本地跑。试了半天结果内存不够&#xff0c;结果以失败告终&#xff0c;结论是机器丐不了一点&#xff0c;想要跑起来内存必须要管够&#xff0c;显存应该也是需要的&#xff08;xAI好像用的8*A100 80G NvLink&…

多数据源mybatisplus对sqlserver分页查询兼容

新增配置文件 package com.ruoyi.framework.config;import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor…

两个免费的wordpress主模板

wordpress免费网站主题 蓝色高端大气上档次的wordpress免费网站主题&#xff0c;首页大图wordpress模板。 https://www.wpniu.com/themes/31.html WP免费模板 用粉色高端大气上档次的WP免费模板&#xff0c;建个网站也不错的。 https://www.wpniu.com/themes/16.html

从后端获取文件数据并导出

导出文件的公共方法 export const download (res, tools) > {const { message, hide } tools;const fileReader: any new FileReader();console.log(fileReader-res>>>, res);fileReader.onload (e) > {if (res?.data?.type application/json) {try {co…

WM8978 —— 带扬声器驱动程序的立体声编解码器(4)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;3&#xff09; 九、寄存器概览与详解 1. 整体概览 WM8978芯片共有58个寄存器&#xff0c;整体总表如下&#xff1a; 2. 详细说明 在此&#xff0c;只介绍WM8978较为常用的那些寄存器。 &…

嵌入式典型总线及协议

在嵌入式系统中&#xff0c;各种总线和通信协议扮演着关键的角色&#xff0c;它们连接和协调系统中的各种硬件组件&#xff0c;实现数据传输和控制。本文将介绍一些典型的嵌入式总线及其通信协议&#xff0c;以及它们在嵌入式系统中的应用。 以下是我整理的关于嵌入式开发的一…

Java-SSM电影购票系统

Java-SSM电影购票系统 1.服务承诺&#xff1a; 包安装运行&#xff0c;如有需要欢迎联系&#xff08;VX:yuanchengruanjian&#xff09;。 2.项目所用框架: 前端:JSP、layui、bootstrap等。 后端:SSM,即Spring、SpringMvc、Mybatis等。 3.项目功能点: 3-1.后端功能: 1.用户管…

深入理解:蓝绿部署与金丝雀部署

深入理解&#xff1a;蓝绿部署与金丝雀部署 深入理解&#xff1a;蓝绿部署与金丝雀部署蓝绿部署&#xff08;Blue-Green Deployment&#xff09;原理优缺点适用场景 金丝雀部署&#xff08;Canary Deployment&#xff09;原理优缺点适用场景 总结 深入理解&#xff1a;蓝绿部署…

机器学习——决策树特征选择准则

机器学习——决策树特征选择准则 决策树是一种强大的机器学习模型&#xff0c;它可以用于分类和回归任务。决策树通过树状结构对数据进行分类&#xff0c;每个内部节点表示一个特征&#xff0c;每个叶节点表示一个类别或一个数值。在决策树构建的过程中&#xff0c;特征的选择…

Avalonia(11.0.2)+.NET6 打包运行到银河麒麟V10桌面系统

操作系统配置 项目结构 .net版本 这次我们是在银河麒麟V10系统上打包运行Avalonia(11.0.2)+.NET6.0的程序 开始打包 准备Linux下的桌面快捷方式以及图标 调整AvaloniaApplication2.Desktop.csproj的配置项,重点看下图红色线圈出来的部分,里面涉及到了LinuxPath的设置。完整的配…

【论文精读】OTA: Optimal Transport Assignment for Object Detection(物体探测的最优传输分配)

OTA最优传输 &#x1f680;&#x1f680;&#x1f680;摘要一、1️⃣ Introduction---介绍二、2️⃣Related Work---相关工作2.1 &#x1f393; Fixed Label Assignment--静态标签分配2.2 ✨Dynamic Label Assignment--动态标签分配 三、3️⃣Method---论文方法3.1 &#x1f39…

深度学习基础知识概述

深度学习理论 神经网络基础&#xff1a;感知机、前向传播、反向传播、激活函数 神经网络是深度学习的基础&#xff0c;它受到人脑结构的启发而设计。神经网络由许多相互连接的单元或节点组成&#xff0c;这些单元模拟生物神经元的功能。下面&#xff0c;我们将详细讲解神经网…

个人网站制作 Part 14 添加网站分析工具 | Web开发项目

文章目录 &#x1f469;‍&#x1f4bb; 基础Web开发练手项目系列&#xff1a;个人网站制作&#x1f680; 添加网站分析工具&#x1f528;使用Google Analytics&#x1f527;步骤 1: 注册Google Analytics账户&#x1f527;步骤 2: 获取跟踪代码 &#x1f528;使用Vue.js&#…

java.lang.String final

关于String不可变的问题&#xff1a;从毕业面试到现在&#xff0c;一个群里讨论的东西&#xff0c;反正码农面试啥都有&#xff0c;这也是我不咋喜欢面试代码&#xff0c;因为对于我而言&#xff0c;我并不喜欢这些面试。知道或不知道基本没啥含氧量&#xff0c;就是看看源代码…

【java】10.面向对象

一、类和对象 1.1 类和对象的理解 客观存在的事物皆为对象 &#xff0c;所以我们也常常说万物皆对象。 * 类 * 类的理解 * 类是对现实生活中一类具有共同属性和行为的事物的抽象 * 类是对象的数据类型&#xff0c;类是具有相同属性和行为的一组对象的集合 * 简单理解&am…

PHP连接达梦数据库

PDO是一种在PHP中连接数据库的接口&#xff0c;可以通过PDO接口使用PHP连接达梦数据库。 1、安装PHP环境 检查当前环境是否安装PHP [rootlocalhost ~]# php -v 当前环境并未安装PHP&#xff0c;需要进行安装&#xff0c;选择安装PHP7.3版本。 2、安装 epel-release源和源管…

2024.03.21作业

自由发挥实现一个登录窗口的应用场景 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QPen> #include <QBrush> #include <QPainter> #include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; class Painter; } QT_END_NAMESPACE…

C语言:自定义类型:结构体

目录 1. 前言 2. 结构体初识 3. 结构体创建变量 3.1 方法一 3.2 方法二 4. 结构体初始化 5. 结构体自引用 6. 结构体的大小 6.1 结构体对齐规则 6.2 常规结构体 6.3 结构体成员含数组 6.4 结构体嵌套结构体 6.5 为什么存在结构体对齐&#xff1f; 6.6 修改默认对…

软考高级:软件架构评估-质量属性:可用性概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

Golang Gorm 自动分批查询

场景&#xff1a; 目标查询全量数据&#xff0c;但需要每次Limit分批查询&#xff0c;保护数据库 文档&#xff1a; https://gorm.io/zh_CN/docs/advanced_query.html // Param: // dest 目标地址 // batchSize 大小 // fc 处理函数func (db *DB) FindInBatc…