【云原生-Kurbernetes篇】 玩转K8S不得不会的HELM

Helm

  • 一、Helm
    • 1.1 使用背景
    • 1.2 Helm简介
    • 1.3 Helm的几个概念
    • 1.4 helm2 和 helm3 的区别
    • 1.5 chart包的关键组成
  • 二、Helm相关命令
    • 2.1 应用管理操作
    • 2.2 Helm repository仓库管理命令
    • 2.2 Helm chart包管理命令
    • 2.3 Helm release(实例) 管理命令
    • 2.4 Helm私有仓库管理命令
  • 三、部署Helm
    • 3.1 安装 helm
    • 3.2 使用Helm构建应用(使用仓库)
  • 四、自定义 Chart
    • 4.1 具体步骤
    • 4.2 实例
      • Step1 创建自定义chart
      • Step2 部署chart
      • Step3 部署ingress,进行访问测试
    • 4.3 升级与回滚测试
      • 4.3.1 升级
      • 4.3.2 回滚
    • 补充:另一种升级方式
  • 五、Helm仓库
    • 5.1 安装harbor
    • 5.2 安装 push 插件

一、Helm

官方网站: [Helm]

1.1 使用背景

在这里插入图片描述

近些年随着容器技术的流行,容器编排管理也随之蓬勃发展,其中尤其以Kubernetes(以下均简称为K8s)最为著名。

作为DevOps开发人员,产品的容器化部署、发布和测试是我们关注的焦点。

随着业务的深入,配置的复杂性也随之增长,因此我们采用Helm来进行容器化应用的配置管理。

1.2 Helm简介

HelmK8S的软件包(chart)管理器,类似于apt,yum和homebrew。

在这里插入图片描述

Helm可以实现将软件应用所有需要的资源及配置打包在一起,让k8s的应用管理实现高度的可配置化,并可通过单个helm命令一键部署和管理应用

1.3 Helm的几个概念

在这里插入图片描述

Helm的三大概念: chart(软件包)release(基于chart运行的实例)repository(存放chart的仓库)

  • Charts: Helm使用的打包格式,一个Chart包含了一组K8s资源集合的描述文件。Chart有特定的文件目录结构,如果开发者想自定义一个新的 Chart,只需要使用Helm create命令生成一个目录结构即可进行开发。
  • Release: 通过Helm将Chart部署到 K8s集群时创建的特定实例,包含了部署在容器集群内的各种应用资源。
  • Chart Repository: Helm Chart包仓库,提供了很多应用的Chart包供用户下载使用,官方仓库的地址是https://hub.helm.sh,可以在上面发现很多有意思的项目。之后我们会在官方hub找一个应用做个简单的Demo。

总结:Helm 安装 charts 到 Kubernetes 集群中,每次安装都会创建一个新的 release。

1.4 helm2 和 helm3 的区别

功能Helm 3Helm 2
依赖关系无 Tiller,直接与 Kubernetes API 交互使用 Tiller 作为与 Kubernetes API 的代理
安全性直接使用 Kubernetes 的 RBACTiller 拥有 ClusterAdmin 权限
存储Values 存储在 release 对象中,无需 ConfigMapValues 存储在 Tiller 的 ConfigMap 中
配置文件仅需一个 Chart.yaml 文件来描述 Chart需要 Chart.yaml、values.yaml、requirements.yaml 文件来描述 Chart
CRD 支持支持使用 CRD (Custom Resource Definition)不支持使用 CRD
升级策略支持原子性升级,失败可以回滚支持原子性升级,失败不会回滚至上一版本
命名空间默认安装到 kube-system 命名空间默认安装到默认命名空间
插件系统插件架构更简单,更易于开发和维护插件系统相对复杂
API 版本支持最新的 Kubernetes API 版本仅支持 Helm 版本发布时所对应的 Kubernetes API 版本
安装配置去除了初始化、升级、删除等命令的需求,直接使用 Helm chart 安装需要先初始化并部署 Tiller,然后才能使用 Helm
社区支持新版本的默认版本,得到更多活跃社区的关注仍然有相关社区支持,但主要关注点已转向 Helm 3
兼容性在 Helm 3 中,可以通过 helm 2to3 插件进行迁移不支持向后兼容,需重新安装 Chart

1.5 chart包的关键组成

在这里插入图片描述

1)Chart.yaml

chart软件包的自描述文件。

描述chart的元数据信息,包括chart名称(name)chart版本(version)应用版本(appVersion)应用描述(description)

2)templates目录:

目录里包含部署应用所需要的各种资源对象的yaml配置模板文件

3)values.yaml

包含templates目录中的yaml配置模板文件所引用的变量的值

比如templates目录中的yaml配置模板文件中的变量 {{ .Values.busybox.image}} 引用的是 values.yaml 文件中的 busybox.image 字段值

二、Helm相关命令

2.1 应用管理操作

# 列出charts仓库中所有可用的应用
helm search

# 查询指定应用
helm search memcached

# 查询指定应用的具体信息
helm inspect stable/memcached

# 用helm安装软件包,--name:指定release名字
helm install --name memcached1 stable/memcached

# 查看安装的软件包
helm list

# 删除指定引用
helm delete memcached1

2.2 Helm repository仓库管理命令

#添加chart仓库
helm repo add <仓库名称> <仓库URI地址>   

#查看chart仓库列表
helm repo list

#更新chart仓库中的chart软件包列表
helm repo update

#删除chart仓库
helm repo remove  <仓库名称>

#查看仓库中可用的chart包列表
helm search repo <仓库名称>

#查看仓库中指定的chart包的所有历史版本列表
helm search repo <仓库名称/软件包> -l

#查看chart包的基本信息
helm show chart <仓库名称/软件包>   

#查看chart包的所有信息
helm show all <仓库名称/软件包>

2.2 Helm chart包管理命令

#从仓库拉取chart包
helm pull <仓库名称/软件包> 

#创建一个chart目录
helm create <软件包>  

#检查chart配置语法是否正确
helm lint <chart目录> 

#将chart目录打包成chart包(tar包格式)
helm package <chart目录>

2.3 Helm release(实例) 管理命令

#通过chart包安装实例
helm install <实例名称> <仓库名称/软件包> -n 命名空间 [--version=<chart版本>] 

#查看helm安装的实例
helm ls|list -n 命名空间

#查看实例的状态
helm status <实例名称> -n 命名空间

#卸载实例
helm uninstall <实例名称> -n 命名空间、

#升级实例
helm upgrade -n 命名空间 <实例名称> <chart包>

#查看实例的历史版本列表
helm history -n 命名空间 <实例名称>

#回滚实例到指定的chart历史版本
helm rollback -n 命名空间 <实例名称> <chart版本序号>    

2.4 Helm私有仓库管理命令

私有仓库地址格式: http://<私有仓库URL地址>/chartrepo/<项目名>

helm repo add <私有仓库名称> <私有仓库地址> --username=<仓库用户> --password=<用户密码>

helm push <chart包> <私有仓库名称>

三、部署Helm

3.1 安装 helm

下载二进制 Helm client 安装包

下载地址:https://github.com/helm/helm/tags

在这里插入图片描述

#解压
tar -zxvf helm-v3.6.0-linux-amd64.tar.gz

mv linux-amd64/helm /usr/local/bin/helm
#版本查看
helm version

在这里插入图片描述

#命令补全
source <(helm completion bash)

在这里插入图片描述

3.2 使用Helm构建应用(使用仓库)

添加常用的 chart 仓库

#添加 Bitnami 官方仓库
helm repo add bitnami https://charts.bitnami.com/bitnami

#添加 Azure 中国提供的稳定版 Helm Charts 仓库,该仓库中包含了丰富的 Kubernetes 应用的 Helm Charts
helm repo add stable http://mirror.azure.cn/kubernetes/charts

#阿里云提供的 Helm Charts 仓仓库
helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

helm repo add incubator https://charts.helm.sh/incubator

在这里插入图片描述

仓库(repository)相关操作

#更新仓库列表
helm repo update          
helm repo list

在这里插入图片描述

#查看stable仓库可用的 charts 列表(稳定版)
helm search repo stable

在这里插入图片描述

 #查看指定 chart 的基本信息
helm show chart stable/mysql 

#获取指定 chart 的所有信息
helm show all stable/mysql		 

在这里插入图片描述

Release的相关操作

##创建实例##
#指定 release 的名字为 my-redis,-n 指定部署到 k8s 的 namespace
helm install my-redis bitnami/redis [-n default]  

#不指定 release 的名字时,需使用 –generate-name 随机生成一个名字
helm install bitnami/redis --generate-name 

在这里插入图片描述
在这里插入图片描述

#查看所有 release
helm ls/list

在这里插入图片描述

#删除指定的 release
helm uninstall my-redis 

在这里插入图片描述

四、自定义 Chart

Charts 可以在 Helm 仓库中下载,也可以自己创建和定义。

4.1 具体步骤

  1. 创建 Chart 文件夹结构: 包括 Chart.yaml、values.yaml 以及 templates 文件夹等。
  2. 编写 Chart.yaml: 定义了 Chart 的名称、版本、描述信息等。
  3. 编写 values.yaml: 定义了用户可以定制化的变量,如应用名称、镜像版本、端口号等。
  4. 编写模板文件: 定义了实际的 Kubernetes 资源以及如何填充变量。

创建完成 Chart 后,用户可以使用 Helm 将其部署到 Kubernetes 集群中,Helm 会按照 Chart 中定义的内容生成实际的 Kubernetes 资源并将其部署到集群中

4.2 实例

以nginx为例

Step1 创建自定义chart

创建 Chart 文件夹结构

#工作目录
mkdir -p /opt/helm
cd /opt/helm

helm create nginx

在这里插入图片描述

修改 Chart.yaml文件

vim nginx/Chart.yaml

apiVersion: v2
name: nginx                     #chart名字
description: A Helm chart for Kubernetes
type: application               #chart类型,application或library
version: 0.1.0                  #chart版本
appVersion: 1.16.0              #application部署版本

在这里插入图片描述

修改 values.yaml文件

vim nginx/values.yaml
replicaCount: 1

image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: "latest"                 #设置镜像标签

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  create: true
  annotations: {}
  name: ""

podAnnotations: {}

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true                 #开启 ingress
  className: ""
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: www.kgc.com         #指定ingress域名
      paths:
        - path: /
          pathType: Prefix      #指定ingress路径类型
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80
  # targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

在这里插入图片描述

在这里插入图片描述

打包 chart

#检查依赖和模版配置是否正确
helm lint nginx        

在这里插入图片描述

#打包 chart
helm package nginx   

在这里插入图片描述

Step2 部署chart

#使用 --dry-run 参数验证 Chart 的配置,并不执行安装
helm install nginx ./nginx --dry-run --debug

在这里插入图片描述

#部署 chart,release 版本默认为 1
helm install nginx ./nginx -n default           
或者
helm install nginx ./nginx-0.1.0.tgz

在这里插入图片描述

helm ls

kubectl get pod,svc

在这里插入图片描述

##补充##
#可根据不同的配置来 install,默认是 values.yaml
#values-prod.yaml为自定义的配置清单文件
helm install nginx ./nginx -f ./nginx/values-prod.yaml

Step3 部署ingress,进行访问测试

Ingress部署

#获取yaml文件
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml

wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml

在这里插入图片描述

#部署
kubectl apply -f mandatory.yaml
kubectl apply -f service-nodeport.yaml

#查看
kubectl get pod,svc -n ingress-nginx

kubectl get ingress

在这里插入图片描述

访问测试

在这里插入图片描述

curl http://www.byyb.com

在这里插入图片描述

4.3 升级与回滚测试

4.3.1 升级

修改为 NodePort 访问 后,进行升级

修改自定义chart

vim nginx/values.yaml
service:
  type: NodePort
  port: 80
  nodePort: 30080

ingress:
  enabled: false

在这里插入图片描述

vim nginx/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ include "nginx.fullname" . }}
  labels:
    {{- include "nginx.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
      nodePort: {{ .Values.service.nodePort }}              #指定 nodePort
  selector:
    {{- include "nginx.selectorLabels" . | nindent 4 }}

在这里插入图片描述

升级release

#升级 release,release 版本加 1
helm upgrade nginx nginx 

在这里插入图片描述

kubectl get svc

curl 192.168.2.105:31134

在这里插入图片描述

4.3.2 回滚

根据 release 版本回滚。

#查看 release 版本历史
helm history nginx             

helm rollback nginx 1           #回滚 release 到版本1

helm history nginx           #nginx release 已经回滚到版本 1

#通常情况下,在配置好 templates 目录下的 kubernetes 清单文件后,后续维护一般只需要修改 Chart.yaml 和 values.yaml 即可。

在这里插入图片描述

补充:另一种升级方式

在命令行使用 --set 指定参数来部署(install,upgrade)release

注:此参数值会覆盖掉在 values.yaml 中的值,如需了解其它的预定义变量参数,可查看 helm 官方文档。

helm upgrade nginx nginx --set image.tag='1.15'

五、Helm仓库

helm 可以使用 harbor 作为本地仓库,将自定义的 chart 推送至 harbor 仓库。

5.1 安装harbor

#上传 harbor离线安装包 和 docker-compose 文件到 /opt 目录
cd /opt

cp docker-compose /usr/local/bin/

chmod +x /usr/local/bin/docker-compose

tar zxf harbor-offline-installer-*
cd harbor/

在这里插入图片描述

vim harbor.yml
hostname: 192.168.2.106
harbor_admin_password: Harbor12345     #admin用户初始密码
data_volume: /data                     #数据存储路径,自动创建
chart:
  absolute_url: enabled                #在chart中启用绝对url
log:
  level: info
  local:
    rotate_count: 50
    rotate_size: 200M
    location: /var/log/harbor          #日志路径

在这里插入图片描述

#安装带有 Clair service 和 chart 仓库服务的 Harbor
./install.sh --with-clair --with-chartmuseum

在这里插入图片描述

5.2 安装 push 插件

push插件有两种安装方式,在线安装和离线安装,由于网络原因,本次选择离线安装的方式。

补充一下在线安装的方法:helm plugin install https://github.com/chartmuseum/helm-push

离线安装

#获取源码包
wget https://github.com/chartmuseum/helm-push/releases/download/v0.8.1/helm-push_0.8.1_linux_amd64.tar.gz
#新建工作目录
mkdir ~/.local/share/helm/plugins/helm-push

#解压
tar -zxvf helm-push_0.8.1_linux_amd64.tar.gz -C 
~/.local/share/helm/plugins/helm-push

helm repo ls

在这里插入图片描述

#登录 Harbor WEB UI 界面,创建一个新项目
浏览器访问:http://192.168.2.100 
默认的管理员用户名和密码是 admin/Harbor12345

点击 “+新建项目” 按钮

填写项目名称为 “chart_repo”,访问级别勾选 “公开”,点击 “确定” 按钮,创建新项目

在这里插入图片描述
在这里插入图片描述

#添加仓库
helm repo add harbor http://192.168.2.100/chartrepo/chart_repo --username=admin --password=Harbor12345
#注:这里的 repo 的地址是<Harbor URL>/chartrepo/<项目名称>,Harbor 中每个项目是分开的 repo。如果不提供项目名称, 则默认使用 library 这个项目。

在这里插入图片描述

#推送 chart 到 harbor 中
cd /opt/helm
helm push nginx harbor

在这里插入图片描述

查看 chart_repo 项目中的 Helm Charts

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

react大文件上传

目录 大文件上传优点&#xff1a; 大文件上传缺点: 大文件上传原理&#xff1a; 为什么要用md5 实现流程&#xff1a; 部分代码1&#xff1a; 部分代码2&#xff1a;​ 大文件上传优点&#xff1a; 文件太大分片上传能加快上传速度,提高用户体验能断点续传 如果上次上传失败…

C++:继承

一、继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保 持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象 程序设计的层次结构&#xff0c…

网络异常检测

随着社交网络、视频流、点对点技术、云计算和 SaaS 的出现&#xff0c;可以肯定地说&#xff0c;现代企业的好坏取决于他们的网络&#xff0c;尤其是在它们提供的带宽和安全性方面。无论是银行保护其数据免遭盗窃&#xff0c;还是商业组织保护其网络免受安全威胁和攻击&#xf…

Linux 中 .tar 和 tar.gz 的区别

1、前言 有时候你会发现&#xff0c;即便是有些拥有 3 年左右工作经验的运维或开发工程师对 .tar 和 .tar.gz 的区别并不是很清楚。.tar 和 .tar.gz 是在 Linux 系统中用于打包和压缩文件的两种常见格式。它们之间的主要区别在于压缩算法和文件扩展名。 2、区别 .tar .tar 是…

python练习题(markdown中的60道题)

1.Demo01 摄氏温度转化为华氏温度 celsius float(input(输入摄氏温度&#xff1a;)) fahrenheit (9/5)*celsius 32 print(%0.1f 摄氏温度转为华氏温度为 %0.1f % (celsius, fahrenheit))结果&#xff1a; 2.Demo02 计算圆柱体的体积 h, r map(float, input().split())# …

581. 最短无序连续子数组

581. 最短无序连续子数组 题目&#xff1a; 给你一个整数数组 nums &#xff0c;你需要找出一个 连续子数组 &#xff0c;如果对这个子数组进行升序排序&#xff0c;那么整个数组都会变为升序排序。 请你找出符合题意的 最短 子数组&#xff0c;并输出它的长度。 示例&…

【Android】声浪 UI 效果并附上详细代码

声浪效果是基于第三方实现的。 https://github.com/xfans/VoiceWaveView 将三方的 Kotlin 代码转 java 使用&#xff08;按照他的readme 进行依赖&#xff0c;好像少了点东西&#xff0c;至少本项目跑不起来&#xff09; 声浪效果在android 8 以上都是比较好的&#xff0c;不会…

【JavaEE】操作系统与进程

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

Oracle的控制文件多路复用,控制文件备份,控制文件手工恢复

一.配置控制文件多路复用 1.查询Oracle的控制文件所在位置 SQL> select name from v$controlfile;NAME -------------------------------------------------------------------------------- /u01/app/oracle/oradata/orcl/control01.ctl /u01/app/oracle/fast_recovery_a…

规划类3d全景线上云展馆帮助企业轻松拓展海外市场

科技3D线上云展馆作为一种基于VR虚拟现实和互联网技术的新一代展览平台。可以在线上虚拟空间中模拟真实的展馆&#xff0c;让观众无需亲自到场&#xff0c;即可获得沉浸式的参观体验。通过这个展馆&#xff0c;您可以充分、全面、立体展示您的产品、服务以及各种创意作品&#…

实用篇 | T-SNE可视化工具详情及代码示例

本文主要是为了快速的了解t-sne和如何快速使用&#xff01; 简要了解TSNE TSNE&#xff0c;降维方法之一。降维在机器学习中非常重要。这是因为如果使用高维数据创建模型&#xff0c;则很容易欠拟合。换句话说&#xff0c;有太多无用的数据需要学习。可以通过从各种数据中仅…

Golang版本处理Skywalking Trace上报数据

Tips: 中间记录了解决问题的过程&#xff0c;如不感兴趣可直接跳至结尾 首先去es里查询skywalking trace的元数据 可以拿到一串base64加密后的data_binary(直接解密不能用&#xff0c;会有乱码&#xff0c;可参考https://github.com/apache/skywalking/issues/7423) 对data_b…

第四代智能井盖传感器:智能井盖位移怎么进行监测

井盖是城市基础设施的一个重要组成部分&#xff0c;若井盖出现移位等现象&#xff0c;可能会对路过的车辆和行人造成潜在危险。特别是那些含有甲烷气体的井盖&#xff0c;一旦气体超过阈值且被意外踩踏&#xff0c;可能会导致气体的释放&#xff0c;这便会引发一系列安全事故&a…

Linux wait函数用法

wait 函数是用于等待子进程结束并获取子进程的终止状态的系统调用。它在父进程中使用&#xff0c;用于等待其子进程终止并获得子进程的退出状态。 函数原型&#xff1a; pid_t wait(int *status);status 是一个指向整型的指针&#xff0c;用于存储子进程终止时的退出状态&…

clang+llvm多进程gdb调试

clangllvm多进程gdb调试 前言1. 命令行gdb2. 父进程调试3. 子进程调试4. 返回父进程 前言 在学习新增llvm的优化pass时&#xff0c;需要跟踪clang及llvm的调用栈。然而llvm通过posix_spawn()创建了新进程&#xff0c;这使得gdb调试必须有一定的技巧了。 1. 命令行gdb 以下命…

小红书干货类笔记怎么写?建议收藏

小红书干货类笔记是指在小红书这个社交平台上&#xff0c;用户分享的各种实用、有价值的生活技巧、经验、心得等内容的笔记。这类笔记通常具有以下特点&#xff1a;内容详实、实用性强、独特见解、图文并茂。 比如&#xff1a;某个妆要怎么化、某种技能该怎么学、某个城市该怎…

详细梳理山姆·奥特曼离职闹剧 仍试图重返OpenAI

大家好,我是极智视界,欢迎关注我的公众号,获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq OpenAI 与微软围绕 Sam Altman 的离职风波,这场肥皂剧似乎还没到终结的样子。目前 …

跨越行业边界,CodeMeter护航AI领域安全与合规

在人工智能&#xff08;AI&#xff09;技术如ChatGPT的推动下&#xff0c;工业视觉、医疗诊断和智能驾驶等领域正在经历重大变革。这些技术不仅扩大了应用范围&#xff0c;也带来了数据安全、软件授权保护和合规性等新挑战。 AI工业视觉正在推动制造和自动化的快速发展&#x…

YOLOv5结合华为诺亚VanillaNet Block模块

🗝️YOLOv5实战宝典--星级指南:从入门到精通,您不可错过的技巧   -- 聚焦于YOLO的 最新版本, 对颈部网络改进、添加局部注意力、增加检测头部,实测涨点 💡 深入浅出YOLOv5:我的专业笔记与技术总结   -- YOLOv5轻松上手, 适用技术小白,文章代码齐全,仅需 …

出海企业首选的免费开源财务管理系统解决方案

计费与订阅管理 Odoo计费与订阅管理解决方案可帮助您同步从订单、计费到收入确认的复杂流程 Odoo Subscriptions将计费与订阅置于核心业务流程中&#xff0c;将其从普通的后端功能转化为具有决定性意义的战略性业务工具。Odoo统一计费框架支持根据事务、订阅、使用量计费以及…