KubeVela 插件指南:轻松扩展你的平台专属能力

news2024/11/30 10:47:26

KubeVela 插件(addon)可以方便地扩展 KubeVela 的能力。正如我们所知,KubeVela 是一个微内核高度可扩展的平台,用户可以通过模块定义(Definition)[1]扩展 KubeVela 的系统能力,而 KubeVela 插件正是方便将这些自定义扩展及其依赖打包并分发的核心功能。不仅如此,KubeVela 社区的插件中心也在逐渐壮大,如今已经有超过 50 款插件,涵盖可观测性、微服务、FinOps、云资源、安全等大量场景功能。

本文将会全方位介绍 KubeVela 插件的核心机制,教你如何编写一个自定义插件。在最后,我们将展示最终用户使用插件的体验,以及插件将如何融入到 KubeVela 平台,为用户提供一致的体验。

为什么要使用 KubeVela 插件

用户使用插件的一个典型方法是通过 KubeVela 团队维护的插件中心(addon catalog)[2] ,它包含了 KubeVela 团队与社区开发者精心编写的系统扩展功能,并以插件的形式发布于插件中心,这样你可以一键下载并安装这些插件。例如安装 FluxCD 可以快速给你的 KubeVela Application 提供部署 Helm Chart 的能力。

相较于使用 KubeVela 的插件功能,如果你自己的内部平台想要集成一个云原生的功能,你大概会这么做:

  1. 通过 Helm Chart 或者下载 yaml 文件手动安装 FluxCD 或类似的 CRD Operator。
  2. 编写系统集成的代码,让用户界面可以通过统一的方式使用 FluxCD 等 CRD 的功能,在 KubeVela 系统中就是通过编写模块定义(OAM Definition)完成。

实际上,在 KubeVela 1.1 版本之前,我们也是通过类似的方式完成的。这会带来如下问题:

  1. 操作繁琐:用户需要手动查阅文档如何安装 FluxCD 并处理可能发生的错误
  2. 资源分散:用户需要下载不同的文件,既需要安装 Helm 安装 FluxCD 还需要下载模块定义等系统扩展的集成配置
  3. 难以分发复用:用户需要手动下载模块定义就注定了这些资源难以以一个统一的方式分发给用户,也无法形成社区生态让不同的用户可以享受社区便利
  4. 缺少多集群支持:KubeVela 将多集群交付作为一等公民,而这样的手动安装系统扩展的方式显然难以维护多集群的环境
  5. 无版本管理:用户需要手动管理模块定义和 Controller 之间的版本

而 KubeVela 插件就是为了逐一解决这些问题而诞生的。

KubeVela 插件是如何工作的

KubeVela 的插件主要包含两部分:

  • 一部分是安装能力的提供者,通常是一个 CRD Operator/Controller。这个安装过程实质上就是运行一个 OAM 应用,addon 交付中所使用的功能与普通应用能力完全等价。
  • 另一部分就是扩展能力跟 KubeVela 体系的粘合层,也就是模块定义和其他的一些集成配置。OAM 模块定义为用户提供了插件扩展出的组件、运维特征以及工作流步骤等功能,也帮助 CRD Operator 提供用户友好的抽象,使得最终用户无需理解复杂的 CRD 参数,只需要根据最佳实践提供必要的参数。

插件的工作机制如上图所示,KubeVela 的应用具备多集群交付的能力,所以也能帮助插件中的 CRD Operator 部署到这些集群中。模块定义文件仅需要在控制面被 KubeVela 使用,所以无需部署到被管控的集群中。

提示

一旦插件被安装,就会创建一个 KubeVela 应用,包含所有的相关资源和配置,这些配置都会设置 KubeVela 应用对外作为 OwnerReference(父节点)。当我们想要卸载一个插件时,只需要删除这个应用,Kubernetes 提供的资源回收机制会自动将标记了 OwnerReference 的资源一并删除。

例如一个 Redis 插件,它能让用户在自己的应用中使用 Redis 集群类型的组件(Component),这样可以快速创建 Redis 集群。那么这个插件至少会包括一个 Redis Operator 来提供创建 Redis 集群的能力(通过 Application 描述),还有一个组件的模块定义 (ComponentDefinition) 来提供 Redis 集群的组件类型。

所有整个插件的安装过程会将 Redis Operator 放在一个 KubeVela 应用中下发到多集群,而组件定义和 UI 扩展等配置文件则只部署到控制面集群并设置应用对象为 OwnerReference。

创建自己的插件

提示

为保证以下内容功能全部可用,请确保你的 KubeVela 版本 为 v1.5+。

我们将以 Redis 插件为例,讲解如何从头创建一个 KubeVela 插件的实际过程。本次完整的 Redis 插件代码见文末参考[3]

提示

在这里我们会尽可能全面的介绍制作插件中涉及的核心知识,但是作为一个介绍性博客,我们会尽量避免讨论过深的细节以免篇幅过于膨胀,了解完整的功能及细节可以参考自定义插件文档[4]

首先我们需要思考我们要创建的插件有什么作用?例如我们假设 Redis 插件可以提供 redis-failover 类型的 Component,这样用户只需在 Application 中定义一个redis-failover Component 即可快速创建 Redis 集群。

然后考虑如何达到这个目的?要提供 redis-failover 类型的 Component 我们需要定义一个 ComponentDefinition ;要提供创建 Redis 集群的能力支持,我们可以使用 Redis Operator[5]。那至此我们的大目标就明确了:

  • 编写插件的应用描述文件(OAM Application),这将会用于安装 Redis Operator (完整代码可以到插件中心的 template.cue[6]及resources/目录[7]查看。)
  • 编写 redis-failover 类型的 ComponentDefinition[8](完整代码请查看 definitions/目录[9]

不过在开始编写之前,我们首先需要了解一个 KubeVela 插件的目录结构。后续我们会在编写的过程中详细说明每个文件的作用,在这里只需大致了解有哪些文件即可。

提示

命令行工具 vela addon init 可以帮助你创建目录结构的初始化脚手架。

redis-operator/          
├── definitions           
│   └── redis-failover.cue 
├── resources              
│   ├── crd.yaml           
│   ├── redis-operator.cue
│   └── topology.cue       
├── metadata.yaml         
├── parameter.cue         
├── README.md             
└── template.cue

让我们逐一来解释它们:

1. redis-operator/ 是目录名,同时也是插件名称,请保持一致。

2. definitions/ 用于存放模块定义, 例如 TraitDefinition 和 ComponentDefinition。

3. redis-failover.cue 定义我们编写的 redis-failover 组件类型,包含了用户如何使用这个组件的参数以及这个组件与底层资源交互的细节。

4. resources/ 用于存放资源文件, 之后会在 template.cue 中使用他们共同组成一个 KubeVela 应用来部署插件。

5. crd.yaml 是 Redis Operator 的 Kubernetes 自定义资源定义,在 resources/ 文件夹中的 YAML 文件会被直接部署到集群中。

6. redis-operator.cue 一个 web-service 类型的 Component ,用于安装 Redis Operator。

7. topology.cue 是可选的,帮助 KubeVela 建立应用所纳管资源的拓扑关系。

8. metadata.yaml 是插件的元数据,包含插件名称、版本、维护人等,为插件中心提供了概览信息

9. parameter.cue 插件参数定义,用户可以利用这些参数在插件安装时做轻量级自定义

10. README.md 提供给最终用户阅读,包含插件使用指南等。

11. template.cue 定义插件最终部署时的完整应用形态,包含一个 OAM 应用模板以及对其他资源对象的引用。

提示

在插件中制作中我们会广泛使用 CUE 语言来编排配置,如果对 CUE 不熟悉,可以花 10 分钟快速查阅入门指南有一个基本了解。

parameter.cue

parameter: {
    //+usage=Redis Operator image.
    image: *"quay.io/spotahome/redis-operator:v1.1.0" | string
    // 其余省略
}

在 parameter.cue 中定义的参数都是用户可以自定义的(类似于 Helm Values),后续在 template.cue 或者 resources 中可以通过 parameter.<parameter-name> 访问参数。在我们的例子中,用户可以自定义 image ,这样后续我们创建 Redis Operator (redis-operator.cue) 的时候可以通过 parameter.image 使用用户指定的容器镜像。

参数不仅可以给用户预留安装时的自定义输入,还可以作为安装时的条件进行部分安装。比如fluxcd 插件有一个参数叫 onlyHelmComponents[10],它的作用就是可以帮助用户只部署用于安装 Helm Chart 的组件能力,而其他控制器就可以不安装。如果你对于实现细节感兴趣,可以参考fluxcd 插件的部分配置[11]

在设计提供什么参数供用户自定义插件安装时,我们也应该遵循一下这些最佳实践来为用户提供更好的使用体验。

最佳实践

  • 不要在 parameter.cue 中提供大量的细节参数,将大量细节抽象出少量参数供用户调节是一个更好的做法
  • 为参数提供默认值(如样例中的 image 参数)或将参数标记为可选(如样例的 clusters 参数),确保用户仅使用默认值可以得到一个可用的配置
  • 为参数提供使用说明(通过注释标记实现,见样例)
  • 尽量保持插件不同版本间的参数一致,防止因为升级导致不兼容

template.cue 和 resources/ 目录

这是存放我们应用描述文件的地方,即一个 OAM Application 。这描述了实际的插件安装过程。我们主要会在这里包含 Redis Operator ,给集群提供管理 Redis 集群的能力。

template.cue 和 resources/ 目录本质上是相同的,都是构成 KubeVela 应用的组成部分,且都是在同一个 package 下的 CUE 文件。

那为什么需要 resources 目录呢?除去历史原因,这主要是为了可读性的考虑,在 Application 中包含大量资源的时候 template.cue 可能变得很长,这时我们可以把资源放置在 resource 中增加可读性。一般来说,我们将 Application 的框架放在 template.cue 中,将 Application 内部的 Components、Traits 等信息放在 resource 目录中。

  • template.cue

template.cue 定义了应用的框架,绝大多数内容都是固定写法,具体的作用可以参考代码块中的注释。

// template.cue 应用描述文件

// package 名称需要与 resources 目录中 cue 的 package 一致,方便引用 resources 目录中的内容
package main

// Application 模板中多数字段均为固定写法,你需要注意的只有 spec.components

output: {
    // 这是一个经典的 OAM Application
    apiVersion: "core.oam.dev/v1beta1"
    kind:       "Application"
    // 不需要 metadata
    spec: {
        components: [
            // 创建 Redis Operator
            redisOperator // 定义于 resources/redis-operator.cue 中
        ]
        policies: [
        // 这里会指定安装插件的 namespace ,是否安装至子集群等
        // 多为固定写法,无需记忆,可查阅本次样例的完整代码
        // https://github.com/kubevela/catalog/blob/master/experimental/addons/redis-operator/template.cue
        // 文档可参照 https://kubevela.net/zh/docs/end-user/policies/references
        ]
    }
}
// 定义资源关联规则,用于将资源粘合在一起。后续会着重介绍
// Documentation: https://kubevela.net/zh/docs/reference/topology-rule
outputs: topology: resourceTopology // 定义于 resources/topology.cue 中

在插件安装时,系统主要关注两个关键字:

  • 一是 output 字段,定义了插件对应的应用,在应用内部 spec.components 定义了部署的组件,在我们的例子中引用了存放在 resources/ 目录中的 redisOperator 组件。output 中的 Application 对象不是严格的 Kubernetes 对象,其中 metadata 里的内容(主要是插件名称)会被插件安装的过程自动注入。
  • 另一个是 outputs 字段,定义了除了常规应用之外的配置,任何你想要跟插件一同部署的额外 Kubernetes 对象都可以定义在这里。请注意 outputs 中的这些对象必须遵循 Kubernetes API。
  • resources/ 资源文件

我们这里使用一个webservice类型的 Component 来安装 Redis Operator。当然,如果你可以接受依赖 FluxCD 的话,你也可以使用 helm 类型的 Component 直接安装一个 Helm Chart(因为 helm 类型的 Component 主要由 FluxCD 插件提供)。不过编写 addon 的一个原则是尽量减少外部依赖,所以我们这里使用 KubeVela 内置的 webservice 类型,而不是 helm。

// resources/redis-operator.cue

// package 名称与 template.cue 一致,方便在 template.cue 中引用以下的 redisOperator
package main

redisOperator: {
    // 这是 OAM Application 中的 Component ,它将会创建一个 Redis Operator
    // https://kubevela.net/zh/docs/end-user/components/references
    name: "redis-operator"
    type: "webservice"
    properties: {
        // Redis Operator 镜像名称,parameter.image 即在 parameter.cue 中用户可自定义的参数
        image:           parameter.image
        imagePullPolicy: "IfNotPresent"
    }
    traits: [
        // 略
    ]
}

你可以阅读代码块中的注释了解字段的具体作用。

  • KubeVela 提供的资源粘合能力

值得注意的一个功能是资源关联规则 (Resource Topology)[12]。虽然它不是必须的,但是它能帮助 KubeVela 建立应用所纳管资源的拓扑关系。这就是 KubeVela 如何将各种各样的资源粘合成 Application 的。这在我们使用 Kubernetes 自定义资源(CR)的时候特别有用。

// resources/topology.cue

package main

import "encoding/json"

resourceTopology: {
    apiVersion: "v1"
    kind:       "ConfigMap"
    metadata: {
        name:      "redis-operator-topology"
        namespace: "vela-system"
        labels: {
            "rules.oam.dev/resources":       "true"
            "rules.oam.dev/resource-format": "json"
        }
    }
    data: rules: json.Marshal([{
        parentResourceType: {
            group: "databases.spotahome.com"
            kind:  "RedisFailover"
        }
        // RedisFailover CR 会创建以下三类资源
        childrenResourceType: [
            {
                apiVersion: "apps/v1"
                kind:  "StatefulSet"
            },
            // KubeVela 内置 Deployment 等资源的拓扑,因此无需继续向下编写
            {
                apiVersion: "apps/v1"
                kind:  "Deployment"
            },
            {
                apiVersion: "v1"
                kind:  "Service"
            },
        ]
    }])
}

在本例中,redis-failover 类型的 Component 会创建一个 CR ,名为 RedisFailover 。但是在没有资源关联规则的情况下,假设在你的 Application 中使用了 RedisFailover ,虽然我们知道 RedisFailover 管控了数个 Redis Deployment ,但是 KubeVela 并不知道 RedisFailover 之下有 Deployment 。这时我们可以通过 资源关联规则 将我们对于 RedisFailover 的了解告诉 KubeVela,这样 KubeVela 可以帮助我们建立起整个应用下面纳管资源的拓扑层级关系。此时你将获得 KubeVela 提供的许多有用功能,效果见运行插件[13]

提示

资源的拓扑关联功能给我们带来了许多有用的功能,最重要的是为 KubeVela 最终用户使用扩展能力提供了统一体验:

  • VelaUX 资源拓扑视图,从应用到底层资源 Pod 的关联关系一应俱全,包括多集群
  • 统一的 vela exec 命令可以在不同应用组件类型关联的底层容器中执行命令,包括多集群
  • 统一的 vela port-forward 转发不同类型应用组件关联的底层容器端口,包括多集群
  • 统一的 vela log 查看不同类型应用组件关联的底层容器日志,包括多集群
  • 统一的 vela status --pod/--endpoint 查看不同类型应用组件关联的底层容器日志,获得可供访问的地址等,包括多集群

definitions/ 目录

Definitions 目录存放 KubeVela 模块定义(Definition)[14],包括组件定义(ComponentDefinition)、策略定义(TraitDefinition)等。这是插件中最重要的部分,因为它包含了最终用户安装这个插件以后可以获得哪些功能。有了这里定义的组件、运维特征、工作流等类型,最终用户就可以在应用中使用他们了。

在插件中编写模块定义跟常规的编写流程一致,这是一个很大的话题,在这里我们就不详细展开了。你可以通过阅读模块定义对应的文档了解其中的细节:

  • 自定义组件 Component Definition[15]
  • 自定义运维特征 Trait Definition[16]
  • 自定义策略 Policy Definition[17]
  • 自定义工作流步骤 Workflow Step Definition。[18]

在本例中,我们编写 Redis 组件类型主要参照自定义组件[19]与 Redis Operator 使用文档[20],我们将组件类型命名为 redis-failover,它会创建一个 RedisFailover 的 CR ,这样刚刚添加的 Redis Operator 就可以帮助创建 Redis 集群,见文末完整代码[21]

metadata.yaml

这里包含了插件的元数据,即插件的名称、版本、系统要求等,可以参考文末文档[22]。需要注意的是,本次介绍的为 KubeVela v1.5 之后的新写法,因此需要避免使用某些不兼容的元数据字段,以下样例中包含了所有的可用元数据。

提示

例如传统的 deployTo.runtimeCluster (安装至子集群)等元数据在新写法中已有代替(使用 topology Policy),应当使用新写法。可见完整代码中的 template.cue[23]

# 插件名称,与目录名一致
name: redis-operator
# 插件描述
description: Redis Operator creates/configures/manages high availability redis with sentinel automatic failover atop Kubernetes.
# 展示用标签
tags:
- redis
# 插件版本
version: 0.0.1
# 展示用图标
icon: https://xxx.com
# 插件所包含项目的官网地址
url: https://github.com/spotahome/redis-operator
# 可能依赖的其他插件,例如 fluxcd
dependencies: []

# 系统版本要求
system:
  vela: ">=v1.5.0"
  kubernetes: ">=1.19"

运行插件

至此我们已经将插件的主要部分编写完成,下载文末完整代码[24]补全部分细节后,即可尝试运行。

下载得到 redis-operator 目录后,我们可以通过 vela addon enable redis-operator 安装本地的 redis-operator 插件,这种本地安装插件的方式也可以方便你再制作时做一些调试。安装完成后就可以参考插件的 README[25]试用我们的 Redis 插件了!

提示

这里也体现出插件的 README 的重要性,其中需要包括插件的作用、详细使用指南等,确保用户可以快速上手。

在用户使用你编写的插件时,只需如下 4 行 yaml 即可在 Application 中创建包含 3 个 Node 的高可用 Redis 集群!相比于手动安装 Redis Operator 并创建 CR ,甚至逐一手动配置 Redis 集群,插件的方式极大地方便了用户。

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: redis-operator-sample
spec:
  components:
    # This component is provided by redis-operator addon.
    # In this example, 2 redis instance and 2 sentinel instance
    # will be created.
    - type: redis-failover
      name: ha-redis
      properties:
        # You can increase/decrease this later to add/remove instances.
        replicas: 3

只需 apply 仅仅数行的 yaml 文件,我们就轻松创建了如下图所示的整个复杂的资源。并且由于我们编写了资源关联规则 (Resource Topology) ,用户可以通过 VelaUX 轻松获得刚刚创建的 Redis 集群的资源拓扑状态,了解 Application 底层资源的运行状况,不再受限于 Application Component 级别的可观测性。如图我们能直接观测到整个 Application 的拓扑,直至每个 Redis Pod ,可见图中部分 Pod 仍在准备中:

在执行 vela exec/log/port-forward 等命令时也可以精确地看到 Application 底层包含的资源(即支撑 Redis 集群的 3 个 Redis Pod 和 3 个 Sentinel Pod)。

如果你在使用单集群,乍一看你可能不会觉得 exec 进一个 Pod 是很特殊的功能。但是一旦考虑到多集群,能够在横跨多个集群的资源中跟单集群一样以统一的方式进行选择查看能够极大的节省时间。

使用 vela status 命令能获取这个 Application 的运行状态,有了资源关联规则后可以更进一步,直接通过 vela 寻找出 Redis Sentinel 的 Endpoint 来访问 Redis 集群:

结语

通过本文,相信你已经了解插件的作用及制作插件的要点。通过插件体系,我们将获得如下优势

  1. 将平台的能力打包成一个易于安装、便于分发复用、且可以形成社区生态的插件市场。
  2. 充分复用 CUE 和 KubeVela 应用通过的强大能力,将基础设施资源灵活定义并进行多集群分发。
  3. 无论扩展的资源类型是什么,均可以接入应用体系,为最终用户提供一致的体验。

最后,如果你成功制作了属于自己的插件,KubeVela 社区非常欢迎开发者贡献插件至插件中心[26],这样你的插件还能够被其他 KubeVela 社区用户发现并使用!

戳此处:查看 KubeVela 项目官网!!

相关链接

[1] 模块定义(Definition)

https://kubevela.net/zh/docs/platform-engineers/oam/x-definition

[2] 插件中心(addon catalog)

https://github.com/kubevela/catalog

[3] catalog/redis-operator

https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator

[4] 自定义插件文档

https://kubevela.net/zh/docs/platform-engineers/addon/intro

[5] Redis Operator

https://github.com/spotahome/redis-operator

[6] template.cue

https://github.com/kubevela/catalog/blob/master/experimental/addons/redis-operator/template.cue

[7] resources/

https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator/resources

[8] ComponentDefinition

https://kubevela.net/zh/docs/platform-engineers/components/custom-component

[9] definitions/目录

https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator/definitions

[10] onlyHelmComponents

https://github.com/kubevela/catalog/blob/master/addons/fluxcd/parameter.cue

[11] fluxcd 插件部分配置

https://github.com/kubevela/catalog/blob/master/addons/fluxcd/template.cue#L25

[12] 资源关联规则 (Resource Topology)

https://kubevela.net/zh/docs/reference/topology-rule

[13] 运行插件

https://kubevela.io/zh/blog/2022/10/18/building-addon-introduction#%E8%BF%90%E8%A1%8C%E6%8F%92%E4%BB%B6

[14] 模块定义(Definition)

https://kubevela.io/docs/getting-started/definition

[15] 自定义组件 Component Definition

https://kubevela.io/docs/platform-engineers/components/custom-component

[16] 自定义运维特征 Trait Definition

https://kubevela.io/docs/platform-engineers/traits/customize-trait

[17] 自定义策略 Policy Definition

https://kubevela.io/docs/platform-engineers/policy/custom-policy

[18] 自定义工作流步骤 Workflow Step Definition

https://kubevela.io/docs/platform-engineers/workflow/workflow

[19] 自定义组件

https://kubevela.net/zh/docs/platform-engineers/components/custom-component

[20] Redis Operator 使用文档

https://github.com/spotahome/redis-operator/blob/master/README.md

[21] 完整代码

https://github.com/kubevela/catalog/blob/master/experimental/addons/redis-operator/definitions/redis-failover.cue

[22] 文档

https://kubevela.net/zh/docs/platform-engineers/addon/intro#%E6%8F%92%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF%E6%96%87%E4%BB%B6

[23] template.cue

https://github.com/kubevela/catalog/blob/958a770a9adb3268e56ca4ec2ce99d2763617b15/experimental/addons/redis-operator/template.cue#L28

[24] 完整代码

https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator

[25] README

https://github.com/kubevela/catalog/tree/master/experimental/addons/redis-operator/README.md

[26] 插件中心

https://github.com/kubevela/catalog

作者:姜洪烨

原文链接

本文为阿里云原创内容,未经允许不得转载。

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

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

相关文章

C# Winform程序开发笔记

C#d的开发发展到今天,已经改进了不少,对于非常多的应用可以使用C#进行开发,也非常方便,希望以下笔记对于高级开发者(网络通信、线程应用)而言能有所帮助吧。 1、INI文件的读写操作 1.1 类文件 using System; using System.Collections.Generic; using System.IO; usin…

【SpringBoot笔记21】SpringBoot框架使用AOP + 自定义注解实现请求日志记录

这篇文章&#xff0c;主要介绍SpringBoot框架使用AOP 自定义注解实现请求日志记录。 目录 一、SpringBoot记录日志 1.1、环境搭建 1.2、配置FastJson 1.3、自定义LogRecord注解 1.4、定义日志实体类 1.5、创建HttpRequestUtil工具类 1.6、定义AOP切面 1.7、编写测试类…

arm服务器运行onlyoffice

公司的arm服务器上运行onlyoffice报错 是x86_64架构的镜像在arm服务器下不兼容 需要下载兼容arm架构的docker镜像 在dockerhub上 onlyoffice地址 Docker Hubhttps://hub.docker.com/r/onlyoffice/documentserver 下载兼容arm架构的镜像版本 # docker --version Docker ver…

《从0开始写一个微内核操作系统》5-页表映射

ChinOS https://github.com/jingjin666/GN-base/tree/chinos 页表需要多少空间 在第4节中&#xff0c;我们了解到&#xff0c;每一级页表实际上就是一个512大小的unsigned long数组&#xff0c;一个页表本身占用512*84K空间 /* PGD */ /* 每个ENTRY包含512G内存区域 */ typed…

JavaWeb传统商城(MVC三层架构)的促销功能模块【进阶版】

文章目录一.JavaWeb商城项目的促销功能模块【进阶版】开发过程记录1.1 项目背景1.2 需求分析1.3 开发流程/顺序二.促销页面(0.1颗星)2.1 需求介绍2.2 JSP页面2.3效果展示三,商品详情页面(0.2颗星)3.1 需求介绍和效果图3.2 数据库分析3.2 Servlet层3.3 Service层3.4 DAO层3.5 JS…

一本通1064;奥运奖牌计数

#include <iostream> using namespace std; int main() {int n, Jin, Yin, Tong;int JinSum 0, YinSum 0, TongSum 0, sum;cin >> n;for (int i 1; i < n; i) // 循环n次{cin >> Jin >> Yin >> Tong; // 输入一天获得的金银铜牌数JinSum …

InfluxDB学习记录(三)——influxdb的flux语法

什么是Flux Flux 是 InfluxData 的功能性数据脚本语言&#xff0c;设计用于查询、分析和处理数据&#xff0c;它是InfluxQL 和其他类似 SQL 的查询语言的替代品。 每个 Flux 查询都需要以下内容&#xff1a; 数据源时间范围数据过滤器 Flux代码示例 from(bucket:"example…

重装系统后打印机状态已暂停如何恢复

​当我们在使用打印机打印文件的时候&#xff0c;有时候会发现打印机状态已暂停&#xff0c;打印不下去了&#xff0c;这时候怎么恢复呢&#xff0c;其实只需要取消掉打印暂停就可以了&#xff0c;下面就和大家讲讲重装系统后打印机状态已暂停如何恢复吧。 打印机状态已暂停怎…

【前端】Vue+Element UI案例:通用后台管理系统-Home组件:卡片、表格

文章目录目标代码0.布局1.左上User卡片2.左下table卡片2.1数据&#xff1a;TableData.js2.2table2.3代码优化&#xff1a;循环3.右上数据卡片3.1数据&#xff1a;CountData3.2结构3.3布局3.4样式总代码Home.vue参考目标 红框内部分都是卡片&#xff0c;鼠标悬停会有阴影左下是表…

java计算机毕业设计基于安卓Android的天文观星系统app uniapp 小程序

项目介绍 信息技术的发展带来了大量的数据内容,在这些数据中,想要找到自己需要的只有通过搜索引擎。如今,通过百度去查找信息成为大众的首选,然而在经济利益的驱动下,许多百度来的信息都是商业内容,很难找到真实有用的实际信息。在互联网中平台,天文信息交流和资源共享是一个非…

【每日训练】进制转换

目录 题目链接&#xff1a; 测试用例&#xff1a; 解析&#xff1a; 程序&#xff1a; 题目链接&#xff1a; 进制转换_牛客题霸_牛客网 (nowcoder.com) 测试用例&#xff1a; 解析&#xff1a; 题目描述&#xff1a; 输入一个十进制数&#xff0c;转化为对应输入的几进制数…

微服务及其在app自动化领域的应用

微服务是一种软件开发技术- 面向服务的体系结构&#xff08;SOA&#xff09;架构样式的一种变体&#xff0c;它提倡将单一应用程序划分成一组小的服务&#xff0c;服务之间互相协调、互相配合&#xff0c;为用户提供最终价值。每个服务运行在其独立的进程中&#xff0c;服务与服…

5款可视化工具优缺点比对,谁赢了?

利用Excel表格进行汇报&#xff0c;底下坐着的领导可能会看起来眼花缭乱&#xff0c;但如果是以图表可视化的形式展现出来&#xff0c;那可简洁明了多了&#xff0c;不仅仅可以看到某个项目近几个月的走势&#xff0c;并且还能知道之后的决策。 可视化图表用什么工具做&#xf…

FP8训练调研

FP8训练调研 一、FP8训练相关技术要点总结 1、基于块的累加技术&#xff0c;减小低精度数之间相加的累积误差 2、随机舍入技术代替四舍五入&#xff0c;降低舍入误差 3、混合FP8技术&#xff0c;用1-4-3进行前向&#xff0c;1-5-2进行反向 4、设置指数偏移&#xff0c;使F…

windows搭建WebDAV服务,并内网穿透公网访问【无公网IP】

自己用Windows Server搭建了家用NAS主机&#xff0c;WebDAV的文件共享方式当然也是必不可少的。 本文使用的是WIN10 专业版。 1. 安装IIS必要WebDav组件 1.1 打开控制面板&#xff0c;查看方式改为“类别”&#xff0c;进入“程序”&#xff0c;“启用或关闭Windows功能” 1…

数据结构链表之无头单向循环链表的实现

文章目录前言1.链表的相关介绍1.什么是节点2.链表和顺序表的对比3.链表的种类2.链表的实现1.节点的定义和创建2.链表的相关函数接口的实现1.链表的创建2.数据的插入头插尾插指定位置插入3.数据的删除头删尾删指定位置删除4.打印显示节点数据5.数据查找6.链表销毁3.总结前言 之…

2022新版加壳工具-支持.NET虚拟化加密

.NET 虚拟化保护 .NET 程序的保护技术在对抗中不断演进&#xff0c;出现了控制流混淆、名称混淆、文件加壳、动态方法、JIT 加密等保护技术&#xff0c;这些保护技术都有其各自的优缺点&#xff0c;虽然组合起来也能达到一定的效果&#xff0c;但近几年已经流传出一些脱壳机和…

单点架构、集群架构、服务化架构、SOA、微服务到底有什么联系和关系?

本篇参考总结 IT老齐的学习笔记 原视频SOA面向服务架构 原视频智慧城市实践指南 &#xff08;书籍-SOA概述&#xff09; 最近我在负责研发智慧园区的智慧平台产品&#xff0c;目前需求阶段和设计阶段已经完成&#xff0c;正式开始开发阶段&#xff0c;但是作为一个算法类学习者…

redies基本数据结构

nosql数据库 和sql结构的数据库 1.结构化的&#xff0c;不设置表之间的结构 2.没有主外键约束&#xff0c;之间没有关联 3.nosql&#xff0c;其他的数据库不能使用redies的语法 4.没有事务&#xff0c;不符合ACID 5.redies存储在内存中&#xff0c;速度非常快 是一个键值…

Docker入门学习:基本概念、安装、命令、简单使用

前言 一、基本概念 1、Docker镜像 镜像就是一个文件&#xff0c;例如我们的应用镜像、环境镜像&#xff08;例如nginx、mysql等&#xff09;&#xff0c;镜像是创建Docker容器的基础。 2、Docker容器 Docker容器类似于一个沙箱&#xff08;例如做支付的时候的支付宝的沙箱…