亿琪软件-开源博客 - 开源
type: channel
link: https://www.yiqisoft.cn/blogs/category/open_source/
items: Kubeflow 在新的 Namespace 中修改默认的用户名和密码
items: 跳过 Knative-serving revision 针对私有 registry 证书认证问题
items: 如何在 KServe 的 InferenceService 中引用 S3(Minio) Secret 并注入到整个 pipeline？
items: Kubeflow Notebook 里映射 Minio secret 键值对 env 环境变量
items: 离线部署 k3s 集群和搭建管理环境
items: 自建 Registry 转发到指定的 Hub
items: C 语言应用开发中的注意事项
items: 如何在 helm chart 部署 ingress 时只启用 https？
items: EdgeX Foundry 开发设备服务的几个关键点
items: EdgeX Foundry 在 Docker 容器微服务下的相关使用技巧

Kubeflow 在新的 Namespace 中修改默认的用户名和密码
type: item
date: 2025-05-12T05:01:00+00:00
description: 1. Kubeflow 用户管理概述 2. 修改现有用户的 Email 或密码 步骤 1：访问 Dex 配置 3. 新增用户 步骤 1：添加用户到 Dex 步骤 2：创建 Profile 4. 删除用户 步骤 1：从 Dex 中删除用户 步骤 2：删除 Profile 和 Namespace 5. 其他用户管理操作 6. 注意事项与最佳实践 总结 在 Kubeflow 中，用户管理主要依赖其认证系统，通常通过 Dex（一个支持多种身份提供者的开源身份服务）与 Kubernetes 的 RBAC（基于角色的访问控制）结合实现。Kubeflow 支持多用户隔离，每个用户通常关联一个 Kubernetes Namespace（通过 Profile 资源实现）。以下是如何在 Kubeflow 中管理用户（包括修改现有用户的 email 或密码、新增用户等）的详细说明： 1. Kubeflow 用户管理概述 认证方式：Kubeflow 使用 Dex 提供认证，支持多种身份提供者（如 LDAP、OIDC、GitHub、Google 等）。用户登录后，Kubeflow 会自动为其创建对应的 Profile 和 Namespace（如果配置了自动创建）。 Profile 资源：Kubeflow 中的 Profile 是 Kubernetes 的自定义资源（CRD），用于定义用户及其关联的 Namespace。每个 Profile 通常对应一个用户或用户组，并绑定到 Kubernetes RBAC 策略。 权限管理：用户权限通过 Kubernetes RBAC 管理，管理员可以为用户的 Namespace 设置只读或可写权限。 用户数据存储：用户凭据（如 email 和密码）通常存储在 Dex 的配置文件中（静态用户）或外部身份提供者（如 LDAP）中。 2. 修改现有用户的 Email 或密码 在 Kubeflow 中，修改用户的 email 或密码需要根据使用的认证方式进行操作。以下以 Dex 的静态用户配置为例（如果使用 LDAP 或 OIDC，请参考对应身份提供者的文档）： 步骤 1：访问 Dex 配置 Dex 的用户数据存储在 Kubernetes ConfigMap 中，位于 auth Namespace 的 dex ConfigMap 内。 获取 Dex 配置： kubectl get configmap dex -n auth -o jsonpath='{.data.config\.yaml}' > dex-config.yaml 编辑 dex-config.yaml 文件，找到 staticPasswords 部分。示例： staticPasswords: - email: "user1@example.com" hash: "$2y$12$..." username: "user1" 修改 Email：直接更改 email 字段，例如将 user1@example.com 改为 newuser1@example.com。 修改密码： 使用 Python 的 passlib 库生成新的 bcrypt 密码哈希： python3 -c 'from passlib.hash import bcrypt; import getpass; print(bcrypt.using(rounds=12, ident="2y").hash(getpass.getpass()))' 输入新密码后，获取生成的哈希值。 将 hash 字段替换为新生成的哈希值。 更新 Dex ConfigMap： kubectl create configmap dex -n auth --from-file=config.yaml=dex-config.yaml --dry-run=client -o yaml | kubectl apply -f - 重启 Dex Pod 使配置生效： kubectl delete pod -n auth -l app=dex 注意事项 如果用户通过 LDAP 或 OIDC 认证，需在相应的外部身份提供者系统中修改 email 或密码，而不是直接修改 Dex 配置。 修改 email 后，可能需要更新对应的 Profile 资源（见下文）。 更新 Profile 的 Email 如果修改了用户的 email，需要同步更新 Kubeflow Profile 资源： 编辑 Profile： kubectl edit profile <profile-name> -n kubeflow 更新 spec.owner.name 字段为新的 email，例如： apiVersion: kubeflow.org/v1beta1 kind: P…

跳过 Knative-serving revision 针对私有 registry 证书认证问题
type: item
date: 2025-05-07T08:29:20+00:00
description: 问题现象 尝试方法 将私有 registry 证书导入 终极方法，还是在 GitHub issue 找到 问题现象 当使用私有 registry 的 image 作为 ClusterServingRuntime 时，启动 knative-serving revision 后，会出现以下错误，导致内网私有 registry 的证书不被信任，无法启动 kserve InferenceService 。困扰了我好久好久。 Unable to fetch image "hub.yiqisoft.cn/openvino/model_server:latest-gpu": failed to resolve image to digest: Get "https://hub.yiqisoft.cn/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority 尝试方法 将私有 registry 证书导入 虽然手动拉取 image 没问题，但是 knative-serving 还是 无效 终极方法，还是在 GitHub issue 找到 issue: https://github.com/knative/serving/issues/5126 需要修改 ConfigMaps , knative-serving namespace 下 config-deployment，增加一个 key/value registries-skipping-tag-resolving: kind.local,ko.local,dev.local,hub.yiqisoft.cn

如何在 KServe 的 InferenceService 中引用 S3(Minio) Secret 并注入到整个 pipeline？
type: item
date: 2025-05-06T11:16:00+00:00
description: 使用 Secret 直接注入 需要一个单独的 Secret 来管理 S3(Minio) 连接 创建 KServe 的 InferenceService 时需要引入注解 最后，在 pod 中就出现了这些 env 使用 ServiceAccount 注入 创建 S3(Minio) 连接 Secret 创建 ServiceAccount 并引用 上面的 Secret 创建 InferenceService 时引用 ServiceAccount 问题 使用 Secret 直接注入 需要一个单独的 Secret 来管理 S3(Minio) 连接 这里的注解千万不能少，否则 S3 连接信息不会注入到 pod 中，尤其是 storage-initializer 阶段需要用到 S3 连接信息从 模型仓库拿到模型文件。 尤其要注意：模型仓库的连接信息 uri 必须是以 / 结尾，比如：s3://models/ovms/yolo11n/，一定不能是 s3://models/ovms/yolo11n apiVersion: v1 data: AWS_ACCESS_KEY_ID: bWluaW8= AWS_SECRET_ACCESS_KEY: bWluaW8xMjM= kind: Secret metadata: annotations: serving.kserve.io/s3-endpoint: minio-service.kubeflow.svc.cluster.local:9000 serving.kserve.io/s3-region: east serving.kserve.io/s3-useanoncredential: 'false' serving.kserve.io/s3-usehttps: '0' name: minio-secret namespace: yiqisoft type: Opaque 创建 KServe 的 InferenceService 时需要引入注解 最关键的就是这个注解："serving.kserve.io/storageSecretName": "minio-secret" 完整的代码 from kubernetes import client import kserve isvc = kserve.V1beta1InferenceService( api_version=kserve.constants.KSERVE_GROUP + "/v1beta1", kind=kserve.constants.KSERVE_KIND, metadata=client.V1ObjectMeta( name=f"{DET_MODEL_NAME}", namespace=kserve.utils.get_default_target_namespace(), labels={ "modelregistry/registered-model-id": model.id, "modelregistry/model-version-id": version.id, }, annotations={ "serving.kserve.io/storageSecretName": "minio-secret" }, ), spec=kserve.V1beta1InferenceServiceSpec( predictor=kserve.V1beta1PredictorSpec( model=kserve.V1beta1ModelSpec( storage_uri=art.uri, model_format=kserve.V1beta1ModelFormat( name=art.model_format_name, version=art.model_format_version, ), runtime="kserve-ovms" ), ) ), ) ks_client = kserve.KServeClient() ks_client.create(isvc) 最后，在 pod 中就出现了这些 env 这些 env 怎么来的我还没有完全搞清楚。反正 secret 里面的内容都注入成功。 env: - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: key: AWS_ACCESS_KEY_ID name: minio-secret - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: key: AWS_SECRET_ACCESS_KEY name: minio-secret - name: S3_USE_HTTPS value…

Kubeflow Notebook 里映射 Minio secret 键值对 env 环境变量
type: item
date: 2025-04-28T09:03:00+00:00
description: Secret 配置和绑定 Kubeflow 默认安装配置 Minio secret PodDefault 绑定 自定义配置 Minio secret PodDefault 绑定 secret Kubeflow Notebook 配置 metadata -> labels 加上你的 PodDefault name 即可 使用 PodDefault 绑定 label 即可实现 Secret 配置和绑定 Minio secret 肯定是保存在 secret 中 Kubeflow 默认安装配置 Minio secret 在自己的 namespace 中： mlpipelin-minio-artifact PodDefault 绑定 apiVersion: kubeflow.org/v1alpha1 kind: PodDefault metadata: name: add-minio-secret namespace: yiqisoft spec: envFrom: - secretRef: name: mlpipeline-minio-artifact selector: matchLabels: add-minio-secret: 'true' 自定义配置 Minio secret apiVersion: v1 kind: Secret metadata: name: s3creds namespace: yiqisoft data: AWS_ACCESS_KEY_ID: bWluaW8= AWS_SECRET_ACCESS_KEY: bWluaW8xMjM= type: Opaque PodDefault 绑定 secret apiVersion: kubeflow.org/v1alpha1 kind: PodDefault metadata: name: add-minio-secret namespace: yiqisoft spec: desc: add minio credential to env envFrom: - secretRef: name: s3creds selector: matchLabels: add-minio-secret: 'true' Kubeflow Notebook 配置 metadata -> labels 加上你的 PodDefault name 即可 apiVersion: kubeflow.org/v1 kind: Notebook metadata: labels: add-minio-secret: 'true'

离线部署 k3s 集群和搭建管理环境
type: item
date: 2025-04-27T01:46:00+00:00
description: 环境准备 下载离线安装文件 准备数据库 PostgreSQL 安装部署 k3s 准备服务器 导入镜像包 拷贝主程序 k3s 安装 安装 Helm 部署工具 部署 Cert Manager 部署 Rancher 集群管理工具 导入镜像 部署 Rancher 部署网络存储 使用 Ceph（推荐） 使用 NFS 网络文件系统 部署 Harbor 私有化仓库 部署 pv 和 pvc 安装 NFS 依赖 部署 Harbor 部署 ChartMuseum 管理工具 下载 ChartMuseum 镜像 部署 ChartMuseum Helm Chart 上传 Charts 到 ChartMuseum 部署 frps 反向代理 编译 frps 开发 frps Helm Chart 部署到 k3s 管理集群 验证结果 管理新的集群（业务集群） 环境准备 下载离线安装文件 本例子用 v1.30.4+k3s1 安装脚本 install.sh wget https://github.com/k3s-io/k3s/raw/refs/tags/v1.30.4+k3s1/install.sh 主程序 k3s wget https://github.com/k3s-io/k3s/releases/download/v1.30.4%2Bk3s1/k3s 镜像压缩包 wget https://github.com/k3s-io/k3s/releases/download/v1.30.4%2Bk3s1/k3s-airgap-images-amd64.tar 准备数据库 PostgreSQL 数据库 name ip notes database 192.168.100.100 PostgreSQL 创建 compose.yml services: postgres: image: postgres:alpine container_name: postgres restart: unless-stopped environment: POSTGRES_USER: k3s POSTGRES_PASSWORD: talent POSTGRES_DB: k3s ports: - "5432:5432" volumes: - ./data:/var/lib/postgresql/data - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh 创建脚本 init-db.sh #!/bin/bash set -e psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname=postgres <<-EOSQL CREATE DATABASE harbor; EOSQL 启动 PostgreSQL 数据库容器 docker compose up -d 验证数据库 docker exec -it postgres psql -U k3s -c '\l' List of databases Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges -----------+-------+----------+-----------------+------------+------------+--------+-----------+------------------- harbor | k3s | UTF8 | libc | en_US.utf8 | en_US.utf8 | | | k3s | k3s | UTF8 | libc | en_US.utf8 | en_US.utf8 | | | ... (5 rows) 安装部署 k3s 准备服务器 准备三台机器，都作为 master 运行，本节内容需要在三台都执行。 name ip notes master01 192.168.100.101 必须 master02 192.168.100.102 可选 master03 192.168.100.103 可选 cat <<EOF >> /etc/hosts 192.168.100.100 database 192.168.100.101 master01 192.168.100.102 master02 192.168.100.103 master03 EOF 导入镜像包 离线安装重要步骤 mkdir -p /var/lib/rancher/k3s/agent/images/ cp k3s-airgap-images-amd…

自建 Registry 转发到指定的 Hub
type: item
date: 2025-04-12T17:27:00+00:00
description: 创建 Namespace PVC 作为存储，其实不需要 上级 Registry/Hub 证书（私有证书的话） Deployment 部署 pod Service 部署 Ingress 配置 部署完成后，验证 创建 Namespace # Namespace apiVersion: v1 kind: Namespace metadata: name: registry PVC 作为存储，其实不需要 # PersistentVolumeClaim (PVC) for storage apiVersion: v1 kind: PersistentVolumeClaim metadata: name: registry-storage namespace: registry spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi # 根据缓存需求调整大小 storageClassName: local-path # 替换为你的 StorageClass 上级 Registry/Hub 证书（私有证书的话） # ConfigMap for CA certificate apiVersion: v1 kind: ConfigMap metadata: name: registry-ca-cert namespace: registry data: hub-yiqisoft-cert.pem: | # 替换为你的证书内容，或通过 kubectl create configmap 上传 -----BEGIN CERTIFICATE----- MIIDNDCCAhygAwIBAgIQJ6pOclGOhjgEFTkYFs4HcTANBgkqhkiG9w0BAQsFADAU MRIwEAYDVQQDEwloYXJib3ItY2EwHhcNMjUwMzE0MTAzOTU3WhcNMjYwMzE0MTAz ... [binary] -----END CERTIFICATE----- Deployment 部署 pod 要把上级证书导入 # Deployment apiVersion: apps/v1 kind: Deployment metadata: name: registry namespace: registry spec: replicas: 1 selector: matchLabels: app: registry template: metadata: labels: app: registry spec: initContainers: - name: update-ca-certificates image: hub.yiqisoft.cn/library/registry:2 command: ["/bin/sh", "-c", "cp /etc/certs/hub-yiqisoft-cn.crt /usr/local/share/ca-certificates/ && update-ca-certificates"] volumeMounts: - name: ca-cert mountPath: /etc/certs - name: ca-cert-dir mountPath: /usr/local/share/ca-certificates - name: ca-cert-system mountPath: /etc/ssl/certs containers: - name: registry image: hub.yiqisoft.cn/library/registry:2 ports: - containerPort: 5000 volumeMounts: - name: registry-data mountPath: /var/lib/registry - name: ca-cert mountPath: /etc/certs readOnly: true - name: ca-cert-system mountPath: /etc/ssl/certs readOnly: true env: - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY value: /var/lib/registry - name: REGISTRY_PROXY_REMOTEURL value: "https://hub.yiqisoft.cn" - name: REGISTRY_PROXY_USERNAME value: "admin" - name: REGISTRY_PROXY_PASSWORD value…

C 语言应用开发中的注意事项
type: item
date: 2025-04-12T15:55:44+00:00
description: C 语言应用开发中的注意事项 1.全局变量 2.源代码文件夹中 .c 模块文件的划分 3.多线程编程注意的问题 线程安全和互斥锁 线程间通信 4.深浅拷贝问题 总结 C 语言应用开发中的注意事项 C 语言作为一门经典的编程语言，广泛应用于系统编程、嵌入式开发和高性能计算等领域。然而，在进行 C 语言应用开发时，开发者需要关注一系列问题，以确保代码的正确性、性能和可维护性。 笔者在基于 C 语言开发 EdgeX Foundry 设备服务实践之中，遇到了一些问题，如全局变量的使用、.c 模块文件的划分、多线程编程注意事项、深浅拷贝问题以及编译链接时的多重定义问题。本文将对其展开讨论，并提供具体的代码示例和实用建议。 1.全局变量 全局变量是在函数外部定义的变量，其作用域从定义处开始到文件结束。它们在程序整个生命周期内存在，通常不会被轻易时放掉。可被程序中的任何函数访问。它能够方便多个函数共享数据，并减少函数参数传递的开销，但同时也不利于模块化编程和代码重用，增加调试难度。 以下展示的 global_pp 全局变量，在 EdgeX Foundry 设备服务中用于保存设备协议的详细信息，为部分关键代码： #include "device_openvino.h" #include "circular_buffer.h" /* protocols */ typedef struct { char *input_model; char *input_image_path; /* Uri */ char *device_name; /* CPU, GPU[0,1,...], NPU */ char *Score; } protocol_properties; protocol_properties *global_pp; // malloc a protocol_properties void func() { if (!global_pp) { iot_log_debug(driver->lc, "malloc a global_pp (protocol_properties)"); global_pp = (protocol_properties *)malloc(sizeof(protocol_properties)); global_pp->input_model = NULL; global_pp->input_image_path = NULL; global_pp->device_name = NULL; global_pp->Score = NULL; } } int main() { func(); return 0; } 注意事项： 尽量减少全局变量的使用，优先考虑局部变量或函数参数。 使用有意义的命名（如 g_config），避免冲突。 在多线程环境中，使用锁机制确保线程安全。 2.源代码文件夹中 .c 模块文件的划分 模块化编程将程序分解为独立的模块，每个模块负责特定功能。这种方法能提高代码的可读性、可维护性和可重用性，同时便于团队协作开发。划分 .c 文件的指导思想有以下几点： 每个 .c 文件应包含一组相关功能的实现，例如字符串处理或网络通信。 避免单个 .c 文件过大，建议控制在 1000 行以内。 使用头文件 (.h) 声明对外接口，.c 文件实现具体逻辑。 头文件用于声明函数、宏、类型和全局变量，供其他模块使用。 以下是 EdgeX Foundry 设备服务中环形 buffer 缓冲区的模块设计： //circular_buffer.h #pragma once #include <stddef.h> // 包含 size_t 的定义 // Circular buffer structure struct circular_buffer { struct infer_result* buffer; // storing data size_t capacity; // Maximum buffer capacity size_t size; // The current number of stored elements size_t head; // Head index (write location) size_t tail; // Tail index (read position) }; struct circular_buffer* create_circular_buffer(size_t capacity); ... //circular_buffer.c #include "circular_buffer.h" #include <stdlib.h> #include "edgex_comm…

如何在 helm chart 部署 ingress 时只启用 https？
type: item
date: 2025-04-10T11:37:00+00:00
description: 仅仅配置 HTTPS 自动跳转 HTTP 到 HTTPS 设置 ingress 优先级 仅仅配置 HTTPS 这里的值只填写 websecure 即可。打开 ingress 映射 http 时，就显示 404apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ .Values.fullnameOverride }}-ingress annotations: traefik.ingress.kubernetes.io/router.entrypoints: "websecure" 自动跳转 HTTP 到 HTTPS 增加这一条即可，适合那种更智能的跳转需求。metadata: annotations: traefik.ingress.kubernetes.io/router.middlewares: "redirect-https@kubernetescrd" 设置 ingress 优先级 优先级设置，数字越大，优先级越高metadata: annotations: traefik.ingress.kubernetes.io/router.priority: "1000"

EdgeX Foundry 开发设备服务的几个关键点
type: item
date: 2025-04-10T07:45:00+00:00
description: EdgeX Foundry 开发设备服务的几个关键点 1.设备服务工作流 2.设备服务示例模板 2.1 SDK 相关工作流 2.2 template.c 的细节 3.删除设备的处理逻辑 4.增加设备 4.1 增加设备的方式 4.2 增加设备的处理逻辑 总结 EdgeX Foundry 开发设备服务的几个关键点 EdgeX Foundry 设备服务是与传感器/设备或物联网对象 (“物”) 交互的边缘连接器，它需要与各种设备交互，将数据传输到边缘计算系统，并根据需求执行控制命令。EdgeX Foundry 通过其模块化设计和丰富的工具集，使得设备服务的开发变得更加简单高效。我们还可以使用设备服务 SDK 来创建您自己的 EdgeX 设备服务，本文重点介绍使用 C-SDK 开发设备服务源代码的几个必须明确的关键点 。 1.设备服务工作流 以 设备服务 template.c 为例，作为一个虚拟设备服务，它可以将数据发送到核心数据微服务，用户可以通过命令和控制微服务发送命令并获得响应，虚拟设备服务的这些功能在执行功能或性能测试时不需要任何实际设备就可以使用。 注意点： 虚拟设备服务对核心数据和元数据微服务具有依赖性，因为初始化过程需要检查或注册配置文件，设备和值描述符，因此，核心数据和元数据服务必须在设备服务初始化之前完全启动。 服务启动时，服务会通过从 YAML 文件加载“值描述符”,“设备服务”,“设备描述”来初始化，并登记在元数据微服务中，YAML文件默认存在，也可以自行创建。虚拟设备服务为元数据微服务提供回调API来管理设备实例。 2.设备服务示例模板 2.1 SDK 相关工作流 EdgeX Foundry 的 C-SDK 提供了一个设备服务模板（位于 examples/template.c 强烈推荐先看一遍代码），它提供了一套规范化的开发示例，包括自定义回调函数、设备服务启动关闭、内存开辟释放等，是我们初次接触设备服务开发的良好开端。设备服务工作流在上一节有了一个大致的介绍，结合官方的指导文档 servicewritersguide.md (强烈推荐先阅读一遍)，这里进一步描述设备服务内部 SDK 相关的工作流，展示如下： 从根本上说，设备服务由多个回调组成，上图中的 SDK 内部工作流均在一系列回调函数中作处理。一个设备服务只有一个设备服务实例结构体指针 Implementation 每次调用回调时，该指针都会被传递，如初始化回调函数的第一个参数 (template_driver *) impl。 /* --- template.c ---- */ /* Initialize performs protocol-specific initialization for the device * service. */ static bool template_init ( void *impl, struct iot_logger_t *lc, const iot_data_t *config ) { template_driver *driver = (template_driver *) impl; iot_log_debug (lc, "Template Init."); return true; } 2.2 template.c 的细节 一个设备服务必须要自定义好的回调函数如下：每一个回调函数的实现正如上面提到的 template_init 那样。 /* Device Callbacks */ devsdk_callbacks *templateImpls = devsdk_callbacks_init ( template_init, template_get_handler, template_put_handler, template_stop, template_create_addr, template_free_addr, template_create_resource_attr, template_free_resource_attr ); 同时设备服务 SDK 还提供了一些非必要的回调函数，以便于开发者实现更灵活的需求，在 servicewritersguide.md 的 Optional handlers 部分有提到。举一个例子，一个设备服务实例可以实现 device_added、device_updated 和 device_removed 处理程序，然后它将收到服务管理的设备范围的更改通知。如果需要特殊的初始化/关闭操作来优化设备的使用，这可能会有所帮助。只需要将该函数实现，并注册进设备服务的回调初始化函数即可： //device_added 的具体实现 static void device_a…

EdgeX Foundry 在 Docker 容器微服务下的相关使用技巧
type: item
date: 2025-04-02T06:31:00+00:00
description: EdgeX Foundry 在 Docker 容器微服务下的相关使用技巧 1.Device Services 注册问题 2.数据库服务的操作工具 3.docker-compose.yml 用法 4.Docker Network 容器互联 总结 EdgeX Foundry 在 Docker 容器微服务下的相关使用技巧 EdgeX Foundry 是一个开源的边缘计算框架，广泛用于物联网设备的开发与管理。它高度依赖 Docker 来实现服务的容器化部署。本文将分享一些在 Docker 容器中使用 EdgeX Foundry 的实用技巧，包括 Device Services 的注册、数据库服务操作、docker-compose.yml 的用法以及网络管理等方面的经验总结。希望能为开发者提供参考。 1.Device Services 注册问题 在开发或调试 EdgeX Foundry 的 Device Services 时，可能会遇到设备服务配置残留或配置未正确加载的问题，默认情况下在官方 UI 界面（如下图所示）中没有删除具体一个 Device Service 的接口。 这会导致我们在加载 修改后的设备服务(关键是 /res/configration.yml 文件)时很麻烦，Device Service 的配置信息是存放在官方数据库服务容器 postgres:16.3 中的，最简单干脆的清理办法是清除所有Docker 卷： 清理容器和卷 # 删除所有已停止和运行中的容器 docker rm -f $(docker ps -a -q) # 删除所有未使用的 Docker 卷 docker volume rm -f $(docker volume ls -q) 启动 EdgeX 服务 假设你已经下载了 EdgeX 的 edgex-compose 仓库，可以通过以下步骤重新启动服务，此时获得了全新的一套 EdgeX 微服务： # 进入 compose-builder 目录 cd /home/ubuntu/edgex/edgex-compose/compose-builder/ # 后台启动所有服务 docker compose up -d root@ubuntu:/home/ubuntu/edgex/edgex-compose/compose-builder# docker compose up -d [+] Running 17/17 ✔ Volume "edgex_db-data" Created 0.0s ✔ Volume "edgex_kuiper-data" Created 0.0s ... ✔ Container edgex-support-scheduler Started 2.4s ✔ Container edgex-app-rules-engine Started 2.6s ✔ Container edgex-core-command Started 2.6s 注意： 在执行清理命令前，建议检查是否有重要数据未备份。 如果遇到权限问题，可使用 sudo 提升权限。 2.数据库服务的操作工具 EdgeX 的 Compose 文件仓库会为我们生成数据库服务容器如下： ID IMAGE COMMAND PORTS NAMES ... 8xxx7a postgres:16.3-alpine3.20 "docker-entrypoint.s…" 127.0.0.1:5432->5432/tcp edgex-postgres ... 为了方便查看数据库内部一些关键数据表的状态和信息，建议把 Postgres 端口映射到本地，用 SQL 工具（推荐 DBeaver）连接上，进行增删改查 : 注意： 首次使用需要登陆数据库，在 docker-compose.yml 文件中有数据库用户名和密码： database: container_name: edgex-postgres environment: POSTGRES_DB: edgex_db POSTGRES_PASSWORD: postgres ... 3.docker-compose.yml 用法 Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose，您可以使用 YML 文件来配置应用程序需要的所有服务。然后，使用一个命令，就可以从 YML 文件配置中创建并启动所有服务。 EdgeX Foundry 部署服务的核心配置文件正是 docker-compose.yml , 同时也是自定义设备服务的重要部署工具。以下是一些常用操作和注意事项 : （在 docker-compose.yml 同级文件夹下运行） 停止并删除所有服务容器： docker c…