Kubernetes 多集群网络方案系列 2 -- Submariner 监控

news2024/11/16 23:57:55

Submariner 是一个用于连接 Kubernetes 集群的跨集群网络解决方案,可以实现集群之间的服务发现、网络通信等功能。

Prometheus 是一个开源的监控和告警系统,专门用于收集、存储和查询各种应用、系统和基础设施的实时指标数据。Prometheus 具备多维数据模型、灵活的查询语言(PromQL)、高效的存储等特点,广泛应用于 Kubernetes 集群监控、服务可用性监控、性能分析等场景。

Grafana 是一款流行的开源数据可视化工具,可以与 Prometheus 等各种数据源集成,为用户提供丰富、实用的监控图表和仪表盘。

在本文中,将介绍如何利用 Prometheus 对 Submariner 进行监控,并通过 Grafana 展示监控数据的图表。我们可以通过监控了解 Submariner 多集群的连接状态,连接延时等指标,并及时发现潜在的问题。

本文是 Kubernetes 多集群网络方案系列的第 2 篇文章:

  • Kubernetes 多集群网络方案系列 1 – Submariner 介绍
  • Kubernetes 多集群网络方案系列 2 – Submariner 监控(本文)

1 前提条件

在开始本实验前,请确保你已经安装了以下工具:

  • Kubectl:Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互和管理集群资源。
  • Subctl:Submariner 的命令行工具,用于简化 Submariner 的部署和管理过程。通过 subctl,可以快速部署 Submariner 到 Kubernetes 集群,以及查看集群和连接的状态。
  • Kind:Kubernetes in Docker(Kind)是一个用于在本地运行 Kubernetes 集群的工具,特别适合开发和测试环境。
  • Helm:Helm 是 Kubernetes 的包管理工具,用于简化 Kubernetes 应用的部署、升级和管理。

2 克隆代码

本实验相关的代码保存在 Github 上,执行以下命令获取。

git clone https://github.com/cr7258/hands-on-lab.git
cd hands-on-lab/multi-cluster/submariner/monitoring/

3 创建集群

首先执行以下命令,在本地使用 Kind 创建两个 Kubernetes 集群。这两个集群中,cluster-1 将充当 Broker 集群的角色,而所有需要相互通信的集群都将注册到 Broker 集群上。同时 cluster-1 自身也作为连接集群注册到 Broker 集群。

# 替换成服务器 IP
export SERVER_IP="10.138.0.11"

kind create cluster --config - <<EOF
kind: Cluster
name: cluster-1
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
networking:
  apiServerAddress: $SERVER_IP
  podSubnet: "10.8.0.0/16"
  serviceSubnet: "10.88.0.0/16"
EOF

kind create cluster --config - <<EOF
kind: Cluster
name: cluster-2
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
networking:
  apiServerAddress: $SERVER_IP
  podSubnet: "10.9.0.0/16"
  serviceSubnet: "10.99.0.0/16"
EOF

4 部署 Submariner

执行以下命令,在 cluster-1 集群上部署 Broker。部署完成后,会生成 broker-info.subm 文件,文件以 Base64 加密,其中包含了连接 Broker 集群 API Server 的地址以及证书信息,还有 IPsec 的密钥信息。

subctl --context kind-cluster-1 deploy-broker

在将集群注册到 Broker 之前,我们需要做两件事:

  • 1.(可选)分别在 cluster-1 和 cluster-2 集群中各选择一个点打上 submariner.io/gateway=true Label,Submariner 会将这些节点作为 Gateway 节点,用于建立跨集群通信的隧道。如果没有节点含有这个 Label,在执行 subctl join 加入集群时也会提示我们选择一个节点作为 Gateway 节点。
  • 2.在 cluster-1 和 cluster-2 集群的 Gateway 节点加上 gateway.submariner.io/public-ip=ipv4:<节点 IP> Annotation,用于设置 Gateway 节点的 Public IP。这里先解释一下 Submariner 中的 Private IP 和 Public IP:Private IP 是 Gateway 节点服务器的接口 IP,Public IP 是 Gateway 节点的公网 IP,Submariner 默认通过请求 ipify.org, my-ip.io, seeip.org 这几个网站来获取节点的 Public IP。由于我们的 Submariner 多集群是通过内网 IP 互相建立连接的,因此不需要通过公网暴露 Gateway 节点。但是 Submariner 目前只会将 Public IP 作为 Prometheus 指标中展示的端点地址,而不会考虑集群间究竟是通过公网 IP 还是内网 IP 建立连接的。因此,我们选择手动将 Public IP 标记为 Gateway 节点的 IP。
# 获取 cluster-1-worker 节点的 IP 地址
export CLUSTER_1_WORKER_IP=$(docker inspect --format '{{ .NetworkSettings.Networks.kind.IPAddress }}' cluster-1-worker)
# 设置 Gateway 节点 Public IP
kubectl --context kind-cluster-1 annotate node cluster-1-worker gateway.submariner.io/public-ip=ipv4:$CLUSTER_1_WORKER_IP --overwrite
# 标记 cluster-1-worker 为 Gateway 节点
kubectl --context kind-cluster-1 label node cluster-1-worker submariner.io/gateway=true --overwrite

# 获取 cluster-2-worker 节点的 IP 地址
export CLUSTER_2_WORKER_IP=$(docker inspect --format '{{ .NetworkSettings.Networks.kind.IPAddress }}' cluster-2-worker)
# 设置 Gateway 节点 Public IP
kubectl --context kind-cluster-2 annotate node cluster-2-worker gateway.submariner.io/public-ip=ipv4:$CLUSTER_2_WORKER_IP --overwrite
# 标记 cluster-2-worker 为 Gateway 节点
kubectl --context kind-cluster-2 label node cluster-2-worker submariner.io/gateway=true --overwrite

分别确认 cluster-1-worker 和 cluster-2-worker 节点已经添加了 gateway.submariner.io/public-ip=ipv4:<节点 IP> Annotation,并且设置了 submariner.io/gateway=true Label。

kubectl --context kind-cluster-1 get node cluster-1-worker -o yaml

kubectl --context kind-cluster-2 get node cluster-2-worker -o yaml

执行 subctl join 命令将 cluster-1 和 cluster-2 两个集群加入 Broker 集群。

  • 使用 --clusterid 参数指定集群 ID,每个集群 ID 需要唯一。
  • 提供上一步生成的 broker-info.subm 文件用于集群注册。
  • --air-gapped 参数表示集群是在内网环境进行连接的,Submariner 不会尝试通过节点公网 IP 进行连接。
subctl --context kind-cluster-1 join broker-info.subm --clusterid cluster-1 --air-gapped
subctl --context kind-cluster-2 join broker-info.subm --clusterid cluster-2 --air-gapped

5 部署 Prometheus

Prometheus Operator 是一个用于在 Kubernetes 集群上部署和管理 Prometheus 的开源项目。它使用 Kubernetes 的自定义资源定义 (CRDs) 来管理 Prometheus, ServiceMonitors 和 PodMonitors 等对象。

在本实验中,我们将使用 Prometheus Operator 来管理 Prometheus。执行以下命令使用 Helm 在 cluster-1 集群安装 Prometheus Operator。

wget https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.64.0/bundle.yaml
kubectl --context kind-cluster-1 create -f bundle.yaml

在开始部署 Prometheus 之前,需要先为 Prometheus 创建所需的 ServiceAccount 和 ClusterRole/ClusterRoleBinding。这些资源将确保 Prometheus 有足够的权限来访问 Kubernetes API。

# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/metrics
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: default

执行以下命令,在 cluster-1 集群创建 Prometheus 所需的 RBAC 资源。

kubectl --context kind-cluster-1 apply -f rbac.yaml

接下来在 cluster-1 集群上部署 Prometheus。每个 Prometheus CRD 资源会被 Prometheus Operator 部署为一个 StatefulSet,位于相同的命名空间下,并根据配置生成对应的资源。serviceMonitorNamespaceSelector: {} 表示允许选择所有 Namespace 的 ServiceMonitor。serviceMonitorSelector 则根据 Label 选择 Prometheus 实例应该包含哪些 ServiceMonitors。ServiceMonitors 将在稍后进行配置,其中具体定义了监控 Service 的规则,并添加 monitor: "true" Label。

# prometheus.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      monitor: "true"

执行以下命令,在 cluster-1 集群部署和配置 Prometheus。

kubectl --context kind-cluster-1 apply -f prometheus.yaml

6 创建 ServiceMonitor

虽然 Submariner 会自动为 Gateway Engine, Lighthouse DNS 等组件创建 ServiceMointor,但是在本实验中并不能完全满足我们的需求,因此这里选择另外创建 ServiceMonitor。

在 ServiceMonitor 中定义 Prometheus 监控规则:

  • 使用 selector 来根据 Label 来选择要监控 Service。
  • 为每个 ServiceMonitor 添加 relabelings 配置,为 cluster-1 集群的 Prometheus 指标加上 cluster: cluster-1 Label。在后面我们会在 cluster-1 集群中通过 Prometheus Federation 来采集 cluster-2 集群的指标进行统一的展现,因此这里打上 cluster Label 来区分不同的集群。
  • 为每个 ServiceMonitor 添加 monitor: "true" Label 匹配上面在 Prometheus CRD 设置的 serviceMonitorSelector 的配置。
# servicemonitor-cluster-1.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-gateway-servicemonitor
  namespace: submariner-operator
  labels:
    app: submariner-gateway
    monitor: "true"
spec:
  selector:
    matchLabels:
      app: submariner-metrics-proxy
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-lighthouse-agent-servicemonitor
  namespace: submariner-operator
  labels:
    app: submariner-lighthouse-agent
    monitor: "true"
spec:
  selector:
    matchLabels:
      app: submariner-lighthouse-agent
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-lighthouse-coredns-servicemonitor
  namespace: submariner-operator
  labels:
    app: submariner-lighthouse-coredns
    monitor: "true"
spec:
  selector:
    matchLabels:
      app: submariner-lighthouse-coredns
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-operator-servicemonitor
  namespace: submariner-operator
  labels:
    name: submariner-operator
    monitor: "true"
spec:
  selector:
    matchLabels:
      name: submariner-operator
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1

执行以下命令,在 cluster-1 集群创建 Submariner 服务相关的 ServiceMonitor 资源。

kubectl --context kind-cluster-1 apply -f servicemonitor-cluster-1.yaml

通过 kubectl port-forward 命令将 Prometheus Service 转发到本机 9090 端口提供访问。

kubectl port-forward --context kind-cluster-1 --address 0.0.0.0 svc/prometheus-operated 9090:9090

浏览器输入 http://<服务器 IP>:9090 访问 Prometheus Web 界面。可以看到 Prometheus 已经自动发现了 Submariner 相关的组件。

尝试查询一条指标,当前在 Prometheus 中只有 cluster-1 集群的数据。

7 Prometheus Federation 设置

Prometheus Federation 允许用户将多个 Prometheus 实例的指标汇总到主 Prometheus Server 上(本实验中是 cluster-1 的 Prometheus)进行分析和查询。在 Submariner 的多集群环境中,建立 Prometheus Federation 变得更加容易,我们可以轻松地导出集群中的 Prometheus 服务,并将其配置为主 Prometheus 的抓取目标。

接下来,我们将在 cluster-2 集群中部署 Prometheus,以收集该集群的 Submariner 指标。然后,通过 Prometheus Federation 在 cluster-1 集群中收集 cluster-2 集群的指标,并将其统一展示。

7.1 Cluster2 部署 Prometheus 并设置 ServiceMonitor

执行以下命令,在 cluster-2 集群部署 Prometheus。

kubectl --context kind-cluster-2 create -f bundle.yaml
kubectl --context kind-cluster-2 create -f rbac.yaml
kubectl --context kind-cluster-2 create -f prometheus.yaml

执行以下命令,在 cluster-2 集群创建 Submariner 服务相关的 ServiceMonitor 资源。和 cluster-1 集群的 ServiceMonitor 有所不同,cluster-2 集群的 ServiceMonitor 没有为指标添加 cluster: cluster-1 Label,因为我们后面可以在 cluster-1 的 Prometheus Federation job 中统一为从其他集群抓取的指标添加 cluster Label 来标识集群信息。

kubectl --context kind-cluster-2 apply -f servicemonitor.yaml

使用 Submariner 将 cluster-2 集群的 Prometheus 服务发布出来,使得 cluster-1 集群能够访问该服务。

subctl --context kind-cluster-2 export service prometheus-operated --namespace default 

7.2 Cluster1 设置 Federation

为了实现 Prometheus Federation,我们需要向主 Prometheus Server (cluster-1 的 Prometheus)添加额外的抓取配置。

  • targets 中设置 cluster-2 集群 Prometheus 的地址。跨集群场景下,Submariner 通过 <pod-name>.<cluster-id>.<svc-name>.<ns>.svc.clusterset.local 的格式来解析 Headless Service + StatefulSet 的域名。
  • 为来着 cluster-2 集群的指标添加 cluster: 'cluster-2' Label。
# additional-scrape-configs.yaml
- job_name: 'prometheus-federate'
  honor_labels: true
  metrics_path: '/federate'
  params:
   'match[]':
      - '{__name__=~"submariner.*"}'
  static_configs:
  - targets:
     - 'prometheus-prometheus-0.cluster-2.prometheus-operated.default.svc.clusterset.local:9090'
    labels:
      cluster: 'cluster-2'
  metric_relabel_configs:
    - regex: 'prometheus.*'
      action: labeldrop

根据以上配置文件创建 Secert 清单文件,并应用到 cluster-1 集群中。

kubectl --context kind-cluster-1 create secret generic additional-scrape-configs --from-file=prometheus-additional.yaml --dry-run=client -oyaml > additional-scrape-configs.yaml
kubectl --context kind-cluster-1 apply -f additional-scrape-configs.yaml

修改 cluster-1 的 Prometheus CRD,additionalScrapeConfigs 引用附加的抓取配置。

# prometheus-federate.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      monitor: "true"
  additionalScrapeConfigs:
    name: additional-scrape-configs
    key: prometheus-additional.yaml

执行以下命令,在 cluster-1 集群中更新 Prometheus 配置。

kubectl --context kind-cluster-1 apply -f prometheus-federate.yaml

等待 Prometheus 重新加载配置后,可以在 Prometheus 界面中看到新增了 Federation 的抓取配置。

此时 cluster-1 集群的 Prometheus 包含了来自两个集群的指标。

8 部署 Grafana

和 Prometheus Operator 类似,Grafana 同样也提供了 Operator 来简化 Grafana 的安装,以及仪表盘和数据源的管理。执行以下命令使用 Helm 在 cluster-1 集群安装 Grafana Operator。

helm --kube-context kind-cluster-1 upgrade -i grafana-operator oci://ghcr.io/grafana-operator/helm-charts/grafana-operator --version v5.0.0-rc0

使用 Grafana CRD 可以方便地在 Kubernetes 中安装 Grafana,这里设置 Grafana 的用户名为 root,密码为 root123。在 GrafanaDatasource CRD 中,将集群中的 Prometheus 作为数据源,以便 Grafana 连接并显示 Prometheus 的监控数据。

# grafana.yaml
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
  name: grafana
  labels:
    dashboards: "grafana"
spec:
  config:
    log:
      mode: "console"
    auth:
      disable_login_form: "false"
    security:
      admin_user: root
      admin_password: root123
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
  name: grafanadatasource
spec:
  datasource:
    access: proxy
    type: prometheus
    jsonData:
      timeInterval: 5s
      tlsSkipVerify: true
    name: Prometheus
    url: http://prometheus-operated:9090
    isDefault: true
  instanceSelector:
    matchLabels:
      dashboards: "grafana"

执行以下命令,在 cluster-1 集群中部署 Grafana 并配置数据源。

kubectl apply --context kind-cluster-1 -f grafana.yaml

通过 kubectl port-forward 命令将 Grafana Service 转发到本机 3000 端口提供访问。

kubectl port-forward --context kind-cluster-1 --address 0.0.0.0 svc/grafana-service 3000:3000

浏览器输入 http://<服务器 IP>:3000 访问 Grafana Web 界面。

可以看到 Grafana 已经添加了 Prometheus 作为数据源。

检查数据源是否连接正常。

接下来可以直接导入我制作好的 Submariner Dashboard 文件 dashboard.json。

复制并黏贴 dashboard.json 的内容,然后点击 Load 导入。

确认 Dashboard 信息,点击 Import 导入。

Grafana 展示的最终效果如下:你可以查看 Submariner 集群的连接状态和端点信息,有多少导入和导出的 Service,Gateway 节点的连接延迟情况,以及 Lighthouse DNS 的请求情况等等。

9 总结

在这篇文章里,我们向大家展示了如何运用 Prometheus 来收集与 Submariner 相关的监控指标,并利用 Grafana 以可视化的方式展示监控数据,包括 Submariner 集群间的连接状态、连接延迟以及 DNS 请求等各项指标。此外,我们还借助 Operator 简化了 Prometheus 和 Grafana 的配置与管理过程。最后,文章还阐述了如何通过 Prometheus Federation 将多个集群中的 Prometheus 实例指标汇聚到一个中心集群,以方便查询和展示。

10 参考资料

  • Kubernetes Multi-Cluster monitoring with Prometheus and Submariner: https://medium.com/@danielbachar/multi-cluster-monitoring-with-prometheus-and-submariner-f89ff733e7ec
  • Prometheus Operator: https://prometheus-operator.dev/
  • API Docs: https://github.com/prometheus-operator/prometheus-operator/blob/ca400fdc3edd0af0df896a338eca270e115b74d7/Documentation/api.md#prometheusspec
  • Grafana-Operator: https://grafana-operator.github.io/grafana-operator/
  • A Beginner’s Guide to Using the Prometheus Operator: https://blog.container-solutions.com/prometheus-operator-beginners-guide

11 欢迎关注

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

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

相关文章

Java开发 - MySQL主从复制初体验

前言 前面已经学到了很多知识&#xff0c;大部分也都是偏向于应用方面&#xff0c;在应用实战这条路上&#xff0c;博主一直觉得只有实战才是学习中最快的方式。今天带来主从复制给大家&#xff0c;在刚刚开始动手写的时候&#xff0c;才想到似乎忽略了一些重要的东西&#xf…

面试篇-揭开Spring Bean加载的神秘面纱

SpringBean加载完整过程 启动spring容器&#xff08;创建beanfactory&#xff09;->加载配置(注解、xml)->实例化bean(执行构造方法)->注入依赖->初始化bean&#xff08;设置属性值&#xff09;->使用->销毁 解析和读取 XML 配置文件或注解配置类&#xff0…

Linux嵌入式学习之Ubuntu入门(五)汇编语法学习

系列文章目录 一、Linux嵌入式学习之Ubuntu入门&#xff08;一&#xff09;基本命令、软件安装及文件结构 二、Linux嵌入式学习之Ubuntu入门&#xff08;二&#xff09;磁盘文件介绍及分区、格式化等 三、Linux嵌入式学习之Ubuntu入门&#xff08;三&#xff09;用户、用户组…

synchronized原理、偏向锁、轻量级锁、重量级锁、锁升级

文章目录Synchronized概念自增自减字节码指令临界区竞态条件基本使用原理查看synchronized的字节码指令序列Monitor对象的内存布局Mark Word是如何记录锁状态的偏向锁什么是偏向锁偏向锁延迟偏向偏向锁状态跟踪偏向锁撤销之调用对象HashCode偏向锁撤销之调用wait/notify轻量级锁…

Qt Quick - Drawer

Qt Quick - Drawer使用总结一、概述二、使用1、基础使用2、特点空间运行3、与内容转换相互挤占一、概述 Drawer提供了一个基于滑动的侧边面板&#xff0c;类似于经常在触控界面中使用的侧边面板&#xff0c;为导航提供了一个位置。 二、使用 1、基础使用 抽屉可以放置在内…

springcloud深度探索

中文官方文档&#xff1a;project - Spring Cloud Config - 《Spring Cloud中文文档》 - 书栈网 BookStackSpring Cloud ConfigFeaturesQuick StartSample Projects Spring Cloud为开发人员提供了工具&#xff0c;用以快速的在分布式系统中建立一些通用方案&#xff08;例如配…

CDP思科发现协议解析及C/C++代码实现

通常&#xff0c;大多数网络都有几个路由器或交换机&#xff0c;为了便于网络管理&#xff0c;使用网络图或网络图来告诉网络中存在什么类型的设备&#xff0c;以及所有设备如何相互连接&#xff0c;使用的IP地址以及它们属于哪个VLAN的信息。 CDP是一种专有的第二层思科网络协…

Table Transformer做表格检测和识别实践

计算机视觉方面的三大顶级会议&#xff1a;ICCV,CVPR,ECCV.统称ICE CVPR 2022文档图像分析与识别相关论文26篇汇集简介 论文&#xff1a; PubTables-1M: Towards comprehensive table extraction from unstructured documents是发表于CVPR上的一篇论文 作者发布了两个模型&…

22级ACM 4.16 周赛 题解

这场能题解写的感觉没多少其实&#xff08;真的不是因为懒&#xff09;&#xff0c;既然有人想要题解&#xff0c;那么就随便写一下吧&#xff0c;其实大部分的题都有人写出来&#xff0c;感觉这场真的不需要。 A 题 题解 Count Interval AtCoder - abc233_d_霾まる的博客-CS…

AI绘画王炸功能Control Net安装教程

原文&#xff1a;AI绘画王炸功能Control Net安装教程 - 知乎 AI绘画&#xff0c;最近两大王炸功能出圈了。 一个就是超真实超细节的美女图片&#xff0c;已经快和照片无异了&#xff0c;甚至有人用AI绘画的“女仆照片”开始招募游艇会了&#xff0c;具体教程可以查看Lora这篇…

一键生成元宇宙 AI又杀疯了

人类十几年的进步水平&#xff0c;AI用几个月就能轻易实现。在展示了超强的文本对话能力和一键生图功能后&#xff0c;AI大模型不打算停下&#xff0c;开始挑战搭建3D空间这一更高难度的动作。 这次&#xff0c;Facebook母公司Meta想当一把主导者。几天前&#xff0c;它的首席…

185-二35

Java185-二35单列集合顶层接口collection迭代器增强forlambda表达式list特有方法遍历数据结构数组Linkedlist集合泛型类&#xff0c;泛型方法&#xff0c;泛型结构泛型方法泛型的通配符泛型总结数据结构数据结构&#xff08;二叉树&#xff09;前序遍历数据结构&#xff08;二叉…

crm系统有哪些?具体的功能有哪些?

市面上的CRM系统有很多&#xff0c;例如简道云、销售易、salesforce、纷享销客、SugarCRM等等&#xff0c;这些都是比较知名的&#xff0c;前面也有写过很多关于CRM选型的内容&#xff0c;大家可以点进我的主页翻阅一下。 那么&#xff0c;CRM具体的功能有哪些&#xff1f;下面…

计算机网络 - UDP协议 与 TCP协议可靠性(传输层)

前言 本篇介绍UDP报文格式&#xff0c;认识UDP报文&#xff0c;介绍TCP报文格式&#xff0c;了解TCP可靠性的核心机制&#xff0c;TCP通信中三次握手与四次挥手&#xff1b;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&#xff01; 文…

EDA基础概念

EDA基础概念EDA和CADCAD工具EDA工具EDA技术实现目标可编程逻辑器件简称PLD发展历程FPGA简介CPLD简介FPGA和CPLD区别是否需要同时学习FPGA和CPLDXilinx&#xff08;赛灵思&#xff09;公司介绍&#xff08;AMD收购&#xff09;开发工具Xilinx产品Altera&#xff08;阿尔特拉&…

Qt关于QPainter绘制1px宽度图形带来的问题思考

前言 前段时间遇到这样一个问题&#xff0c;使用QPainter绘制直线的时候&#xff0c;设置了笔宽为1像素&#xff0c;但是绘制出来的线条却是2px宽度&#xff0c;而且设置的画笔颜色很明显是降低了透明度&#xff0c;不是最“纯正”的颜色。 当时就感觉非常奇怪&#xff0c;明明…

【FPGA实验1】FPGA点灯工程师养成记

对于FPGA几个与LED相关的实验&#xff08;包括按键点灯、流水灯、呼吸灯等&#xff09;的记录&#xff0c;方便日后查看。这世界上就又多了一个FPGA点灯工程师了&#x1f60f; 成为一个FPGA点灯工程师分三步&#xff1a;一、按键点灯1、按键点灯程序2、硬件实现二、流水灯1、流…

Vue2-黑马(二)

目录&#xff1a; &#xff08;1&#xff09;vue2-基础-属性绑定 &#xff08;2&#xff09;vue2-事件绑定 &#xff08;3&#xff09;vue2-双向绑定 &#xff08;4&#xff09;vue2-计算属性 &#xff08;1&#xff09;vue2-基础-属性绑定 属性与js数据绑定&#xff1a; …

react-router原理

前端路由的原理 自己来监听URL的改变&#xff0c;改变url&#xff0c;渲染不同的组件(页面)&#xff0c;但是页面不要进行强制刷新&#xff08;a元素不行&#xff09;。 hash模式&#xff0c;localhost:3000/#/abc 优势就是兼容性更好&#xff0c;在老版IE中都可以运行缺点是…

DNS配置

TCP/IP提供了通过IP地址来连接到设备的功能&#xff0c;但对用户来讲&#xff0c;记住某台设备的IP地址是相当困难的&#xff0c;因此专门设计了一种字符串形式的主机命名机制&#xff0c;这些主机名与IP地址相对应。 在IP地址与主机名之间需要有一种转换和查询机制&#xff0c…