K8S 日志方案

目录

一、统一日志管理的整体方案

1、基础日志

2、Node级别的日志

3、集群级别的日志架构

二、安装统一日志管理组件

1、 部署Elasticsearch

2、部署Fluentd

3、部署Kibana

三、日志数据展示


一、统一日志管理的整体方案

通过应用和系统日志可以了解Kubernetes集群内所发生的事情,对于调试问题和监视集群活动来说日志非常有用。对于大部分的应用来说,都会具有某种日志机制。因此,大多数容器引擎同样被设计成支持某种日志机制。

对于容器化应用程序来说,最简单和最易接受的日志记录方法是将日志内容写入到标准输出和标准错误流。 但是,容器引擎或运行时提供的本地功能通常不足以支撑完整的日志记录解决方案。例如,如果一个容器崩溃、一个Pod被驱逐、或者一个Node死亡,应用相关者可能仍然需要访问应用程序的日志。

因此,日志应该具有独立于Node、Pod或者容器的单独存储和生命周期,这个概念被称为集群级日志记录。集群级日志记录需要一个独立的后端来存储、分析和查询日志。Kubernetes本身并没有为日志数据提供原生的存储解决方案,但可以将许多现有的日志记录解决方案集成到Kubernetes集群中。在Kubernetes中,有三个层次的日志:

  • 基础日志

  • Node级别的日志

  • 群集级别的日志架构

1、基础日志

kubernetes基础日志即将日志数据输出到标准输出流,可以使用kubectl logs命令获取容器日志信息。如果Pod中有多个容器,可以通过将容器名称附加到命令来指定要访问哪个容器的日志。例如,在Kubernetes集群中的kube-system命名空间下有一个名称为etcd-master的Pod,就可以通过如下的命令获取日志:

[root@master log]# kubectl logs etcd-master -n kube-system

2、Node级别的日志

容器化应用写入到stdout和stderr的所有内容都是由容器引擎处理和重定向的。例如,docker容器引擎会将这两个流重定向到日志记录驱动,在Kubernetes中该日志驱动被配置为以json格式写入文件。docker json日志记录驱动将每一行视为单独的消息。当使用docker日志记录驱动时,并不支持多行消息,因此需要在日志代理级别或更高级别上处理多行消息。 默认情况下,如果容器重新启动,kubectl将会保留一个已终止的容器及其日志。如果从Node中驱逐Pod,那么Pod中所有相应的容器也会连同它们的日志一起被驱逐。Node级别的日志中的一个重要考虑是实现日志旋转,这样日志不会消耗Node上的所有可用存储。Kubernetes目前不负责轮转日志,部署工具应该建立一个解决方案来解决这个问题。

在Kubernetes中有两种类型的系统组件:运行在容器中的组件和不在容器中运行的组件。例如:

  • Kubernetes调度器和kube-proxy在容器中运行。

  • kubelet和容器运行时,例如docker,不在容器中运行。

在带有systemd的机器上,kubelet和容器运行时写入journaId。如果systemd不存在,它们会在/var/log目录中写入.log文件。在容器中的系统组件总是绕过默认的日志记录机制,写入到/var/log目录,它们使用golg日志库。可以找到日志记录中开发文档中那些组件记录严重性的约定。 类似于容器日志,在/var/log目录中的系统组件日志应该被轮转。这些日志被配置为每天由logrotate进行旋转,或者当大小超过100mb时进行旋转。

3、集群级别的日志架构

Kubernetes本身没有为群集级别日志记录提供原生解决方案,但有几种常见的方法可以采用:

  • 使用运行在每个Node上的Node级别的日志记录代理;

  • 在应用Pod中包含一个用于日志记录的sidecar。

  • 将日志直接从应用内推到后端。

经过综合考虑,本文档采用通过在每个Node上包括Node级别的日志记录代理来实现群集级别日志记录。日志记录代理暴露日志或将日志推送到后端的专用工具。通常,logging-agent是一个容器,此容器能够访问该Node上的所有应用程序容器的日志文件。 因为日志记录必须在每个Node上运行,所以通常将它作为DaemonSet副本、或一个清单Pod或Node上的专用本机进程。然而,后两种方法后续将会被放弃。使用Node级别日志记录代理是Kubernetes集群最常见和最受欢迎的方法,因为它只为每个节点创建一个代理,并且不需要对节点上运行的应用程序进行任何更改。但是,Node级别日志记录仅适用于应用程序的标准输出和标准错误。 Kubernetes本身并没有指定日志记录代理,但是有两个可选的日志记录代理与Kubernetes版本打包发布:和谷歌云平台一起使用的Stackdriver和Elasticsearch,两者都使用自定义配置的fluentd作为Node上的代理。在本文的方案中,Logging-agent 采用 Fluentd,而 Logging Backend 采用 Elasticsearch,前端展示采用kibana。即通过 Fluentd 作为 Logging-agent 收集日志,并推送给后端的Elasticsearch;kibana从Elasticsearch中获取日志,并进行统一的展示。

三种收集方案的优缺点

二、安装统一日志管理组件

在本文中采用方案一,使用Node日志记录代理的方面进行Kubernetes的统一日志管理,相关的工具采用:

  • 日志记录代理(logging-agent):日志记录代理用于从容器中获取日志信息,使用Fluentd

  • 日志记录后台(Logging-Backend):日志记录后台用于处理日志记录代理推送过来的日志,使用Elasticsearch

  • 日志记录展示:日志记录展示用于向用户显示统一的日志信息,使用Kibana

在Kubernetes中通过了Elasticsearch 附加组件,此组件包括Elasticsearch、Fluentd和Kibana。Elasticsearch是一种负责存储日志并允许查询的搜索引擎。Fluentd从Kubernetes中获取日志消息,并发送到Elasticsearch;而Kibana是一个图形界面,用于查看和查询存储在Elasticsearch中的日志。

1、 部署Elasticsearch

Elasticsearch是一个基于Apache Lucene(TM)的开源搜索和数据分析引擎引擎,Elasticsearch使用Java进行开发,并使用Lucene作为其核心实现所有索引和搜索的功能。它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。Elasticsearch不仅仅是Lucene和全文搜索,它还提供如下的能力:

  • 分布式的实时文件存储,每个字段都被索引并可被搜索;

  • 分布式的实时分析搜索引擎;

  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据。

在Elasticsearch中,包含多个索引(Index),相应的每个索引可以包含多个类型(Type),这些不同的类型每个都可以存储多个文档(Document),每个文档又有多个属性。索引 (index) 类似于传统关系数据库中的一个数据库,是一个存储关系型文档的地方。Elasticsearch 使用的是标准的 RESTful API 和 JSON。此外,还构建和维护了很多其他语言的客户端,例如 Java, Python, .NET, 和 PHP。

下面是Elasticsearch的YAML配置文件,在此配置文件中,定义了一个名称为elasticsearch-logging的ServiceAccount,并授予其能够对命名空间、服务和端点读取的访问权限;并以StatefulSet类型部署Elasticsearch。

[root@master log]# vim es-statefulset.yaml
kind: Namespace
apiVersion: v1
metadata:name: logginglabels:k8s-app: loggingkubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcile
---
# RBAC authn and authz
apiVersion: v1
kind: ServiceAccount
metadata:name: elasticsearch-loggingnamespace: logginglabels:k8s-app: elasticsearch-loggingaddonmanager.kubernetes.io/mode: Reconcile
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: elasticsearch-logginglabels:k8s-app: elasticsearch-loggingaddonmanager.kubernetes.io/mode: Reconcile
rules:- apiGroups:- ""resources:- "services"- "namespaces"- "endpoints"verbs:- "get"
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: elasticsearch-logginglabels:k8s-app: elasticsearch-loggingaddonmanager.kubernetes.io/mode: Reconcile
subjects:- kind: ServiceAccountname: elasticsearch-loggingnamespace: loggingapiGroup: ""
roleRef:kind: ClusterRolename: elasticsearch-loggingapiGroup: ""
---
# Elasticsearch deployment itself
apiVersion: apps/v1
kind: StatefulSet
metadata:name: elasticsearch-loggingnamespace: logginglabels:k8s-app: elasticsearch-loggingversion: v7.10.2addonmanager.kubernetes.io/mode: Reconcile
spec:serviceName: elasticsearch-loggingreplicas: 2selector:matchLabels:k8s-app: elasticsearch-loggingversion: v7.10.2template:metadata:labels:k8s-app: elasticsearch-loggingversion: v7.10.2spec:serviceAccountName: elasticsearch-loggingcontainers:- image: quay.io/fluentd_elasticsearch/elasticsearch:v7.10.2name: elasticsearch-loggingimagePullPolicy: IfNotPresentresources:# need more cpu upon initialization, therefore burstable classlimits:cpu: 1000mmemory: 3Girequests:cpu: 100mmemory: 3Giports:- containerPort: 9200name: dbprotocol: TCP- containerPort: 9300name: transportprotocol: TCPlivenessProbe:tcpSocket:port: transportinitialDelaySeconds: 5timeoutSeconds: 10readinessProbe:tcpSocket:port: transportinitialDelaySeconds: 5timeoutSeconds: 10volumeMounts:- name: elasticsearch-loggingmountPath: /dataenv:- name: "NAMESPACE"valueFrom:fieldRef:fieldPath: metadata.namespace- name: "MINIMUM_MASTER_NODES"value: "1"volumes:- name: elasticsearch-loggingemptyDir: {}# Elasticsearch requires vm.max_map_count to be at least 262144.# If your OS already sets up this number to a higher value, feel free# to remove this init container.initContainers:- image: alpine:3.6command: ["/sbin/sysctl", "-w", "vm.max_map_count=262144"]name: elasticsearch-logging-initsecurityContext:privileged: true

通过执行如下的命令部署Elasticsearch:

[root@master log]# kubectl create -f es-statefulset.yaml

下面Elasticsearch的代理服务YAML配置文件,代理服务暴露的端口为9200。

[root@master log]# vim es-service.yaml
apiVersion: v1
kind: Service
metadata:name: elasticsearch-loggingnamespace: logginglabels:k8s-app: elasticsearch-loggingkubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcilekubernetes.io/name: "Elasticsearch"
spec:clusterIP: Noneports:- name: dbport: 9200protocol: TCPtargetPort: 9200- name: transportport: 9300protocol: TCPtargetPort: 9300publishNotReadyAddresses: trueselector:k8s-app: elasticsearch-loggingsessionAffinity: Nonetype: ClusterIP

通过执行如下的命令部署Elasticsearch的代理服务:

[root@master log]# kubectl create -f es-service.yaml

2、部署Fluentd

Fluentd是一个开源数据收集器,通过它能对数据进行统一收集和消费,能够更好地使用和理解数据。Fluentd将数据结构化为JSON,从而能够统一处理日志数据,包括:收集、过滤、缓存和输出。Fluentd是一个基于插件体系的架构,包括输入插件、输出插件、过滤插件、解析插件、格式化插件、缓存插件和存储插件,通过插件可以扩展和更好的使用Fluentd。

Fluentd的整体处理过程如下,通过Input插件获取数据,并通过Engine进行数据的过滤、解析、格式化和缓存,最后通过Output插件将数据输出给特定的终端。

在本文中, Fluentd 作为 Logging-agent 进行日志收集,并将收集到的日志推送给后端的Elasticsearch。对于Kubernetes来说,DaemonSet确保所有(或一些)Node会运行一个Pod副本。因此,Fluentd被部署为DaemonSet,它将在每个节点上生成一个pod,以读取由kubelet,容器运行时和容器生成的日志,并将它们发送到Elasticsearch。为了使Fluentd能够工作,每个Node都必须标记beta.kubernetes.io/fluentd-ds-ready=true。

[root@master log]# kubectl label nodes node1 beta.kubernetes.io/fluentd-ds-ready=true
​
[root@master log]# kubectl label nodes node2 beta.kubernetes.io/fluentd-ds-ready=true

下面是Fluentd的ConfigMap配置文件,此文件定义了Fluentd所获取的日志数据源,以及将这些日志数据输出到Elasticsearch中。

在Fluented配置文件中,有下面的一些关键指令:

  • source指令确定输入源。

  • match指令确定输出目标。

  • filter指令确定事件处理管道。

  • system指令设置系统范围的配置。

  • label指令将输出和过滤器分组以进行内部路由

  • @include ** **指令包含其他文件。

[root@master log]# fluentd-es-configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:name: fluent-bit-confignamespace: logginglabels:k8s-app: fluent-bit
data:# Configuration files: server, input, filters and output# ======================================================fluent-bit.conf: |[SERVICE]Flush         1Log_Level     infoDaemon        offParsers_File  parsers.confHTTP_Server   OnHTTP_Listen   0.0.0.0HTTP_Port     2020
​@INCLUDE input-kubernetes.conf@INCLUDE filter-kubernetes.conf@INCLUDE output-elasticsearch.conf
​input-kubernetes.conf: |[INPUT]Name              tailTag               kube.*Path              /var/log/containers/*.logParser            dockerDB                /var/log/flb_kube.dbMem_Buf_Limit     20MBSkip_Long_Lines   OnRefresh_Interval  10
​filter-kubernetes.conf: |[FILTER]Name                kubernetesMatch               kube.*Kube_URL            https://kubernetes.default.svc:443Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crtKube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/tokenKube_Tag_Prefix     kube.var.log.containers.Merge_Log           OnMerge_Log_Key       log_processedK8S-Logging.Parser  OnK8S-Logging.Exclude Off
​output-elasticsearch.conf: |[OUTPUT]Name            esMatch           *Host            ${FLUENT_ELASTICSEARCH_HOST}Port            ${FLUENT_ELASTICSEARCH_PORT}Logstash_Format OnReplace_Dots    OnRetry_Limit     False
​parsers.conf: |[PARSER]Name   apacheFormat regexRegex  ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$Time_Key timeTime_Format %d/%b/%Y:%H:%M:%S %z
​[PARSER]Name   apache2Format regexRegex  ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$Time_Key timeTime_Format %d/%b/%Y:%H:%M:%S %z
​[PARSER]Name   apache_errorFormat regexRegex  ^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$
​[PARSER]Name   nginxFormat regexRegex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$Time_Key timeTime_Format %d/%b/%Y:%H:%M:%S %z
​[PARSER]Name   jsonFormat jsonTime_Key timeTime_Format %d/%b/%Y:%H:%M:%S %z
​[PARSER]Name        dockerFormat      jsonTime_Key    timeTime_Format %Y-%m-%dT%H:%M:%S.%LTime_Keep   On
​[PARSER]# http://rubular.com/r/tjUt3Awgg4Name criFormat regexRegex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$Time_Key    timeTime_Format %Y-%m-%dT%H:%M:%S.%L%z
​[PARSER]Name        syslogFormat      regexRegex       ^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$Time_Key    timeTime_Format %b %d %H:%M:%S

通过执行如下的命令创建Fluentd的ConfigMap:

[root@master log]# kubectl create -f fluentd-es-configmap.yaml

Fluentd本身的YAML配置文件如下所示:

[root@master log]# vim fluentd-es-ds.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: fluent-bitnamespace: logging
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: fluent-bit-read
rules:
- apiGroups: [""]resources:- namespaces- podsverbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: fluent-bit-read
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: fluent-bit-read
subjects:
- kind: ServiceAccountname: fluent-bitnamespace: logging
---
apiVersion: apps/v1
kind: DaemonSet
metadata:name: fluent-bitnamespace: logginglabels:k8s-app: fluent-bit-loggingversion: v1kubernetes.io/cluster-service: "true"
spec:selector:matchLabels:k8s-app: fluent-bit-loggingtemplate:metadata:labels:k8s-app: fluent-bit-loggingversion: v1kubernetes.io/cluster-service: "true"annotations:prometheus.io/scrape: "true"prometheus.io/port: "2020"prometheus.io/path: /api/v1/metrics/prometheusspec:containers:- name: fluent-bitimage: fluent/fluent-bit:1.5imagePullPolicy: Alwaysports:- containerPort: 2020env:- name: FLUENT_ELASTICSEARCH_HOSTvalue: "elasticsearch-logging.logging.svc.cluster.local"- name: FLUENT_ELASTICSEARCH_PORTvalue: "9200"volumeMounts:- name: varlogmountPath: /var/log- name: varlibdockercontainersmountPath: /var/lib/docker/containersreadOnly: true- name: fluent-bit-configmountPath: /fluent-bit/etc/terminationGracePeriodSeconds: 10volumes:- name: varloghostPath:path: /var/log- name: varlibdockercontainershostPath:path: /var/lib/docker/containers- name: fluent-bit-configconfigMap:name: fluent-bit-configserviceAccountName: fluent-bittolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedule- operator: "Exists"effect: "NoExecute"- operator: "Exists"effect: "NoSchedule"

通过执行如下的命令部署Fluentd:

[root@master log]# kubectl create -f fluentd-es-ds.yaml

3、部署Kibana

Kibana是一个开源的分析与可视化平台,被设计用于和Elasticsearch一起使用的。通过kibana可以搜索、查看和交互存放在Elasticsearch中的数据,利用各种不同的图表、表格和地图等,Kibana能够对数据进行分析与可视化。Kibana部署的YAML如下所示,通过环境变量ELASTICSEARCH_URL,指定所获取日志数据的Elasticsearch服务,此处为:http://elasticsearch-logging:9200,elasticsearch.cattle-logging是elasticsearch在Kubernetes中代理服务的名称。

[root@master log]# vim kibana-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: kibana-loggingnamespace: logginglabels:k8s-app: kibana-loggingaddonmanager.kubernetes.io/mode: Reconcile
spec:replicas: 1selector:matchLabels:k8s-app: kibana-loggingtemplate:metadata:labels:k8s-app: kibana-loggingspec:securityContext:seccompProfile:type: RuntimeDefaultcontainers:- name: kibana-loggingimage: docker.elastic.co/kibana/kibana-oss:7.10.2resources:# need more cpu upon initialization, therefore burstable classlimits:cpu: 1000mrequests:cpu: 100menv:- name: ELASTICSEARCH_HOSTSvalue: http://elasticsearch-logging:9200- name: SERVER_NAMEvalue: kibana-logging- name: SERVER_BASEPATHvalue: ""#   value: /api/v1/namespaces/logging/services/kibana-logging/proxy# - name: SERVER_REWRITEBASEPATH#   value: "false"ports:- containerPort: 5601name: uiprotocol: TCP#livenessProbe:#  httpGet:#    path: /api/status#    port: ui#  initialDelaySeconds: 5#  timeoutSeconds: 10#readinessProbe:#  httpGet:#    path: /api/status#    port: ui#  initialDelaySeconds: 5#  timeoutSeconds: 10

通过执行如下的命令部署Kibana的代理服务:

[root@master log]# kubectl create -f kibana-deployment.yaml

下面Kibana的代理服务YAML配置文件,代理服务的类型为NodePort。

[root@master log]# vim kibana-service.yaml
---
apiVersion: v1
kind: Service
metadata:name: kibana-loggingnamespace: logginglabels:k8s-app: kibana-loggingkubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcilekubernetes.io/name: "Kibana"
spec:type: NodePortports:- port: 5601protocol: TCPtargetPort: uiselector:k8s-app: kibana-logging

通过执行如下的命令部署Kibana的代理服务:

[root@master log]# kubectl create -f kibana-service.yaml

三、日志数据展示

获取Kibana的对外暴露的端口

[root@master log]# kubectl get svc --namespace=kube-system

从输出的信息可以知道,kibana对外暴露的端口为32639,因此在Kubernetes集群外可以通过:http://{NodeIP}:32639 访问kibana

通过点击"Discover",添加索引就能够实时看到从容器中获取到的日志信息:

例如添加索引logstash-*,添加完成效果如下:

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速学习 webpack

目录 1. webpack基本概念 webpack能做什么&#xff1f; 2. webpack的使用步骤 2.1_webpack 更新打包 3. webpack的配置 3.1_打包流程图 3.2_案例-webpack隔行变色 3.3_插件-自动生成html文件 3.4_加载器 - 处理css文件问题 3.5_加载器 - 处理css文件 3.6_加载器 - 处…

红队攻防实战之DC1

如果额头终将刻上皱纹&#xff0c;你只能做到&#xff0c;不让皱纹刻在你的心上 0x01 信息收集: 1.1 端口探测 使用nmap工具 端口扫描结果如下&#xff1a; 由nmap扫描可以知道&#xff0c;目标开放了22,80,111,46204端口&#xff0c;看到端口号22想到ssh远程连接&#xff…

五、交换机基础配置实验

文章目录 实验内容实验拓扑配置交换机双工模式 实验内容 某公司刚成立&#xff0c;新组建网络&#xff0c;购置了 3 台交换机。其中 S1和 S2为接入层交换机&#xff0c;S3 为汇聚层交换机。现在网络管理员需要对3 台新交换机进行基本配置&#xff0c;保证交换机间的接口使用全…

超维空间S2无人机使用说明书——21、VINS视觉定位仿真

引言&#xff1a;为了实现室内无人机的定位功能&#xff0c;S系列无人机配置了VINS-FUSION定位环境&#xff0c;主要包含了仿真跑数据集和实际操作部分。为了提前熟悉使用原理&#xff0c;可以先使用仿真环境跑数据集进行学习和理解 硬件&#xff1a;1080P显示器、Jetson orin…

Cisco 将收购 Cilium 母公司 Isovalent,预计 2024 年第 3 季度完成

本文地址&#xff1a;Cisco 将收购 Cilium 母公司 Isovalent&#xff0c;预计 2024 年第 3 季度完成 | 深入浅出 eBPF 2023 年 12 月 21 日&#xff0c;Isovalent 公司 CTO & 联合创始人 Thomas Graf 和 Cisco 安全业务集团高级副总裁兼总经理 Tom Gillis 分别在各自公司网…

贝叶斯球快速检验条件独立

贝叶斯球 定义几个术语&#xff0c;描述贝叶斯球在一个结点上的动作&#xff1a; 通过&#xff08;pass through&#xff09;&#xff1a;从当前结点的父结点方向过来的球&#xff0c;可以访问当前结点的任意子结点&#xff08;父->子&#xff09;。从当前节点的子结点方向…

【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据

注&#xff1a;本文所用技术栈为&#xff1a;springbootjdbcTemplatesqliteOkHttp 前面的文章我们获取过沪深300指数的成分股所属行业以及权重数据&#xff0c;本文我们来获取个股的详细数据。 我们的数据源是某狐财经&#xff0c;接口的详细信息在下面的文章中&#xff0c;本…

Python小细节之代码极致简化到一行(2)(技法慎用)

一行代码合并字典&#xff08;新字典&#xff09; 引言开整一行代码合并字典普通方法举例 简化高级方法举例 总结&#xff1a;结尾 引言 上次的极简化&#xff0c;看起来大家反应还不错 所以继续肝&#xff0c;但是我觉得这种讲细一点会比较好 所以&#xff0c;每次就KO一个…

Point-BERT:一种基于Transformer架构的点云深度网络

目录 1. 前言 2. Point Tokenization 3. Transformer Backbone 4. Masked Point Modeling 5. Experiments Reference 1. 前言 从PointNet [1] 开始&#xff0c;点云深度网络逐渐成为解决点云特征提取与语义分析的主要研究方向。尤其在OpenAI的GPT模型获得了突破性成果后&#…

CleanMyMac X 4.14.6最新版本使用实用技巧

我们称赞 Mac 的设计、简单性和安全性&#xff0c;却常常忽视了它们的功能。有如此之多的功能、快捷方式和技巧&#xff0c;一旦理解&#xff0c;就可以简化您的生活&#xff0c;让使用 Mac 变得更加有趣。你对学习这些感到兴奋吗&#xff1f;以下是 5 个简单的Mac实用技巧分享…

CDA数据分析师备考必看,L1L2通用

CDA数据分析师L1,L2均可 可安排当月月底的线上考试 线上考的为双机位监考&#xff0c;但是不用担心 安全无隐患&#xff0c;需要联系 当月拿证

如何使用固定二级子域名公网访问多个本地Windows Web网站

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…