Chemmy's Blog

chengming0916@outlook.com

目标检测模型的效果高度依赖三个核心参数的调优:置信度阈值、IoU 阈值和图像尺寸。本文详细解析这三个参数的作用、推荐值及实战组合。


一、置信度阈值(Confidence Threshold)

定义

置信度是模型对「检测框内存在目标」的确信程度,取值范围 0~1

  • 值越高 → 模型越自信,框越可靠
  • 值越低 → 可能包含噪声或模糊目标

作用

过滤低置信度预测框,减少误报。

示例

1
results = model(img, conf=0.5)
  • 只保留置信度 ≥ 0.5 的检测结果
  • 置信度 0.4 的头盔会被丢弃

推荐值

场景 推荐值 说明
高召回(不漏检) 0.3~0.4 安防监控,宁可误报不漏检
平衡精度与召回 0.5 通用推荐
高精度(少误报) 0.6~0.7 自动报警系统

⚠️ 太高漏检,太低误报


二、IoU 阈值(Intersection over Union)

定义

IoU 是两个边界框的重叠程度:

$$IoU = \frac{交集面积}{并集面积}$$

  • 0 → 完全不重叠
  • 1 → 完全重合

作用

用于非极大值抑制(NMS),去除重复检测框。

示例

1
results = model(img, iou=0.45)
  • 两个框 IoU > 0.45 → 认为是同一目标,只保留置信度高的

推荐值

IoU 值 效果
0.2~0.3 严格,易漏检
0.4~0.5 推荐,平衡去重与保留
0.6~0.7 宽松,可能保留多框

⚠️ 太低过度去重,太高重复框多


三、图像尺寸(Image Size)

定义

推理时输入模型的图像尺寸,如 640x640。训练时固定尺寸,推理时自动缩放。

作用

  • 决定模型看到的分辨率
  • 影响检测精度和推理速度

示例

1
results = model(img, imgsz=640)

图像保持比例缩放,短边拉伸,长边补灰边。

推荐值

imgsz 精度 速度 适用场景
320 较低 实时性高、大目标
480 中等 小目标不多
640 一般 通用推荐
800~960 更高 小目标多(远处物体)

⚠️ 太小小目标丢失,太大计算慢


四、参数对比总结

参数 全称 作用 默认值 推荐值
conf Confidence 过滤低置信预测 0.25 0.5
iou Intersection over Union 去除重复框 0.45 0.45
imgsz Image Size 输入分辨率 640 640

五、实战代码

1
2
3
4
5
6
7
8
9
10
from ultralytics import YOLO

model = YOLO('yolov8n.pt')

results = model(
img, # 输入图像
conf=0.5, # 置信度阈值
iou=0.45, # NMS IoU 阈值
imgsz=640 # 输入图像大小
)

六、场景组合推荐

场景 conf iou imgsz 说明
通用检测 0.5 0.45 640 推荐起点
安全报警 0.6 0.45 640 减少误报
小目标检测 0.4 0.45 800 提高召回率
实时检测 0.5 0.45 480 提升速度

七、调优建议

  1. 先用默认值测试conf=0.5, iou=0.45, imgsz=640
  2. 根据结果微调
    • 漏检 → 降低 conf 或增大 imgsz
    • 多框 → 降低 iou
    • 太慢 → 降低 imgsz
  3. 可视化验证:保存带标签图像观察效果

一、SWAP 空间基础概念

1.1 什么是 SWAP?

当 Linux 系统的物理内存(RAM)耗尽时,内核会将内存中不活跃的“页面”移动到硬盘上的一个预配置区域,这个区域就是 SWAP 空间。物理内存与 SWAP 空间的总和称为虚拟内存

1.2 SWAP 的两种形式

  • SWAP 分区:硬盘上一个独立的、专门用于交换的分区。
  • SWAP 文件:文件系统中的一个特殊文件,功能与分区相同。

注意:在虚拟机中安装 Ubuntu 时,系统通常不会自动创建 SWAP 空间,需要手动配置。

1.3 为什么需要 SWAP?

  • 内存溢出保护:当 RAM 完全占满时,系统可将非关键数据移至 SWAP,防止系统崩溃(对小内存系统尤其重要)。
  • 释放物理内存:将启动后很少使用的程序“页面”交换出去,为更活跃的程序腾出 RAM。
  • 休眠支持:系统休眠(Hibernate)功能需要 SWAP 空间来保存内存状态。

1.4 SWAP 的潜在缺点

  • 速度差异:RAM 的访问速度是纳秒级,而硬盘(即使是 SSD)是毫秒级,速度相差数个数量级。
  • 系统变慢:频繁的交换操作(称为“Thrashing”)会导致系统响应迟缓。

二、检查现有 SWAP 空间

在开始操作前,首先检查系统当前的 SWAP 配置。

2.1 查看所有活动的 SWAP 空间

1
sudo swapon --show

如果输出为空,则表示系统未启用任何 SWAP 空间

2.2 查看内存与 SWAP 使用概况

1
sudo free -h

该命令会显示物理内存和 SWAP 的总量、已用量及空闲量。


三、创建 SWAP 文件(推荐方法)

与分区相比,SWAP 文件更灵活,可以轻松调整大小,且不涉及磁盘分区操作。以下是创建 2GB SWAP 文件的完整步骤。

3.1 步骤 1:创建空白文件

1
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
  • if=/dev/zero:输入源,一个输出全零字节的特殊设备。
  • of=/swapfile:输出文件路径。
  • bs=1M:块大小为 1MB。
  • count=2048:块数量。计算:1MB × 2048 = 2GB

    提示:要创建不同大小的文件,只需修改 count 值(例如 count=1024 为 1GB)。

3.2 步骤 2:设置正确的文件权限

SWAP 文件必须严格限制访问权限,防止被普通用户读取。

1
sudo chmod 600 /swapfile

3.3 步骤 3:将文件格式化为 SWAP 空间

1
sudo mkswap /swapfile

此命令会在文件上设置特殊的 SWAP 签名。

3.4 步骤 4:激活 SWAP 文件

1
sudo swapon /swapfile

现在,SWAP 文件已加入系统交换池并立即生效。

3.5 步骤 5:配置永久生效(开机自动启用)

编辑 /etc/fstab 文件,在末尾添加一行:

1
sudo nano /etc/fstab

添加以下内容:

1
/swapfile swap swap defaults 0 0

保存并退出(Ctrl+X,然后按 Y 确认)。

3.6 步骤 6:验证创建结果

再次运行检查命令,确认 SWAP 文件已成功激活:

1
2
3
sudo swapon --show
# 或
sudo free -h

四、优化 SWAP 使用行为:调整 Swappiness

4.1 什么是 Swappiness?

swappiness 是一个内核参数(范围 0-100),用于控制内核使用 SWAP 空间的积极程度

  • 值越低(如 10):内核尽量避免使用 SWAP,除非绝对必要。
  • 值越高(如 80):内核更积极地将内存页面交换出去。
  • Ubuntu 默认值60

4.2 查看当前 Swappiness 值

1
cat /proc/sys/vm/swappiness

4.3 临时调整 Swappiness 值

例如,设置为 40(对服务器更友好):

1
sudo sysctl vm.swappiness=40

4.4 永久调整 Swappiness 值

编辑 /etc/sysctl.conf 文件:

1
sudo nano /etc/sysctl.conf

在文件末尾添加或修改以下行:

1
vm.swappiness=40

保存后,运行以下命令使更改立即生效:

1
sudo sysctl -p

最佳实践建议

  • 桌面系统30-60(平衡响应性与内存使用)。
  • 服务器/数据库10-30(减少慢速交换,优先使用 RAM)。
  • 高性能计算/内存充足时1-10(几乎禁用交换,除非紧急)。

五、删除 SWAP 文件

如果您不再需要某个 SWAP 文件,请按以下步骤安全移除。

5.1 步骤 1:停用 SWAP 文件

1
sudo swapoff -v /swapfile

-v 参数显示详细过程。

5.2 步骤 2:从 /etc/fstab 中移除配置

编辑 /etc/fstab 文件,删除或注释掉之前添加的 /swapfile 那一行。

1
2
3
sudo nano /etc/fstab
# 在行首添加 # 号注释掉,例如:
# /swapfile swap swap defaults 0 0

5.3 步骤 3:删除物理文件

1
sudo rm /swapfile

六、调整 SWAP 空间大小

6.1 调整 SWAP 分区大小(复杂)

调整分区大小通常需要:

  1. 使用 swapoff 停用分区。
  2. 使用 GParted 等图形化分区工具或 parted 命令行工具调整分区边界。
  3. 使用 mkswap 重新格式化。
  4. 使用 swapon 重新激活。

    注意:此操作有风险,且需要分区后方有未分配的连续空间。

6.2 调整 SWAP 文件大小(简单推荐)

这是 SWAP 文件的最大优势。例如,将现有的 2GB 文件扩容到 4GB:

步骤 1:停用当前 SWAP 文件

1
sudo swapoff /swapfile

步骤 2:调整文件大小

1
2
3
4
5
# 方法A:使用 dd 追加 2GB(总大小变为 4GB)
sudo dd if=/dev/zero of=/swapfile bs=1G count=2 oflag=append conv=notrunc

# 方法B:直接创建指定大小的新文件(会覆盖旧文件)
# sudo dd if=/dev/zero of=/swapfile bs=1G count=4

步骤 3:重新设置权限并格式化

1
2
sudo chmod 600 /swapfile
sudo mkswap /swapfile

步骤 4:重新激活 SWAP 文件

1
sudo swapon /swapfile

步骤 5:验证新大小

1
sudo swapon --show

七、SWAP 空间大小规划建议

系统物理内存 (RAM) 推荐 SWAP 大小 休眠支持所需 SWAP
≤ 2 GB RAM 的 2 倍 RAM 的 2-3 倍
2 - 8 GB 等于 RAM 大小 RAM 的 1.5 倍
8 - 64 GB 至少 4 GB RAM 的 1 倍
> 64 GB 至少 4 GB(主要用于休眠) RAM 的 0.5 倍

说明

  • 对于现代拥有大容量 RAM(如 16GB+)的系统,SWAP 的主要作用已从“内存溢出缓冲”转变为支持系统休眠
  • 如果完全不需要休眠功能,且内存充足,可以设置一个较小的 SWAP(如 1-2GB)作为安全缓冲。

八、总结与最佳实践

  1. 检查先行:操作前务必使用 swapon --showfree -h 了解当前状态。
  2. 首选文件:对于大多数用户,创建 SWAP 文件 比调整分区更安全、灵活。
  3. 合理规划大小:根据你的 RAM 大小和用途(是否休眠)参考上表。
  4. 优化 Swappiness:为你的工作负载(桌面/服务器)设置合适的值,以平衡性能。
  5. 持久化配置:任何更改都要记得更新 /etc/fstab/etc/sysctl.conf
  6. 监控使用:定期使用 free -hhtop 监控 SWAP 使用率。如果 SWAP 被频繁使用(>20%),应考虑增加物理内存。

一、使用linuxdeployqt拷贝依赖文件

1. 下载linuxdeployqt

GitHub Releases 下载:

1
2
3
4
5
6
7
8
# 重命名简化
mv linuxdeployqt-6-x86_64.AppImage linuxdeployqt
# 添加执行权限
chmod 777 linuxdeployqt
# 移至系统路径
mv linuxdeployqt /usr/local/bin
# 验证安装
linuxdeployqt --version

2. 配置Qt环境变量

编辑 ~/.bashrc,添加Qt路径(根据实际安装路径调整):

1
2
3
4
5
#add qt env
export PATH=/opt/Qt5.13.0/5.13.0/gcc_64/bin:$PATH
export LIB_PATH=/opt/Qt5.13.0/5.13.0/gcc_64/lib:$LIB_PATH
export PLUGIN_PATH=/opt/Qt5.13.0/5.13.0/gcc_64/plugins:$PLUGIN_PATH
export QML2_PATH=/opt/Qt5.13.0/5.13.0/gcc_64/qml:$QML2_PATH

使配置生效:

1
2
3
source ~/.bashrc
# 验证
qmake -v

注意:最关键的是 PATH 环境变量,其他变量可能非必需。

3. 拷贝依赖文件

准备目录结构:

1
2
mkdir -p TestSetup/Test
cp YourApp TestSetup/Test/ # 替换为你的应用

执行依赖拷贝:

1
2
cd TestSetup/Test
linuxdeployqt Test -appimage

重要提示

  • 确保应用为 Release 版本
  • linuxdeployqt 内部使用 ldd,仅能处理隐式加载.so 文件
  • 对于显式加载.so(如 dlopen),需手动处理其依赖:
    1
    2
    3
    # 示例:若 A.so 显式加载 B.so,而 B.so 隐式依赖 C.so
    # 需对 B.so 单独执行:
    linuxdeployqt B.so -appimage

4. 验证应用运行

清除Qt环境变量后测试:

1
2
3
4
5
6
7
# 清除环境变量(仅当前终端)
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
export LIB_PATH=
export PLUGIN_PATH=
export QML2_PATH=
# 运行应用
./Test

二、打包为.deb安装包

1. 目录结构规划

1
2
3
4
5
6
7
8
TestSetup/
├── output/ # 存放生成的.deb包
└── source/ # 打包源文件
├── DEBIAN/ # 控制文件目录(固定名称)
└── opt/Test/ # 安装目标路径(对应系统/opt/Test/)
├── Test # 应用程序
├── lib/ # 依赖库
└── ... # 其他资源

创建目录:

1
2
3
mkdir -p TestSetup/{output,source/{DEBIAN,opt/Test}}
# 移动依赖文件
mv TestSetup/Test/* TestSetup/source/opt/Test/

2. 配置桌面快捷方式

编辑 TestSetup/source/opt/Test/Test.desktop

1
2
3
4
5
6
7
[Desktop Entry]
Type=Application
Name=My Test # 应用显示名称
Exec=/opt/Test/Test # 绝对执行路径
Icon=/opt/Test/Test.png # 绝对图标路径
Comment=This is my test # 描述信息
Terminal=false # 是否启动终端(false=仅应用窗口)

注意

  • 路径必须是安装后的绝对路径(非打包路径)
  • 需赋予执行权限:chmod +x Test.desktop
  • 准备图标文件:Test.png

3. 创建DEBIAN控制文件

control(包元数据)

TestSetup/source/DEBIAN/control

1
2
3
4
5
6
7
8
9
Package: mytest                 # 包名(卸载时使用)
Version: 0.1.0
Section: utils
Priority: optional
Architecture: amd64
Depends: # 依赖包(留空或填写)
Installed-Size: 512
Maintainer: 123@163.com
Description: my test package

postinst(安装后脚本)

TestSetup/source/DEBIAN/postinst

1
2
3
4
#!/bin/sh
chmod 777 /opt/Test/Test.desktop
cp /opt/Test/Test.desktop /usr/share/applications/ # 开始菜单
cp /opt/Test/Test.desktop ~/Desktop/ # 桌面快捷方式

postrm(卸载后脚本)

TestSetup/source/DEBIAN/postrm

1
2
3
4
5
#!/bin/sh
rm -f /usr/share/applications/Test.desktop
rm -f ~/Desktop/Test.desktop
# 若需删除应用生成的日志,添加:
# rm -rf ~/.config/YourApp/ # 根据实际日志路径调整

脚本要求

  • 首行必须为 #!/bin/sh
  • 赋予执行权限:chmod +x DEBIAN/{postinst,postrm}

4. 构建.deb包

1
2
cd TestSetup/source
dpkg -b . ../output/test_amd64_0.1.0.deb

三、安装与卸载

1. 安装

1
2
cd TestSetup/output
sudo dpkg -i test_amd64_0.1.0.deb

验证效果

  • 桌面出现快捷方式
  • 开始菜单 → Other 中出现应用
  • 应用文件位于 /opt/Test/

2. 卸载

1
2
# 使用control文件中的Package字段值
sudo apt-get remove mytest

卸载效果

  • 删除 /opt/Test/ 目录
  • 自动移除桌面和开始菜单快捷方式
  • (若在 postrm 中配置)删除应用日志

关键注意事项

  1. 依赖完整性:显式加载的 .so 需单独处理依赖
  2. 路径一致性.desktop 文件中的路径必须匹配安装路径
  3. 脚本权限DEBIAN 目录下的脚本必须有执行权限
  4. 包名唯一性control 中的 Package 字段需全局唯一

相关笔记与链接建议

  • 当前笔记引用:Linux下Qt打包发布
  • 建议补充双向链接:
    • [[Qt应用部署最佳实践]] - 跨平台部署策略
    • [[Linux软件包管理]] - deb/rpm 包机制对比
    • [[CMake构建系统]] - Qt项目自动化构建
    • [[AppImage打包指南]] - 替代打包方案

总结

通过 linuxdeployqt + dpkg 组合,可高效生成符合 Linux 发行版规范的安装包,实现依赖自动管理、快捷方式集成和干净卸载。

1. K3s指定集群管理IP

在k3s.service中添加启动参数

1
--advertise-address=<192.168.x.x>

详细参考官方文档以及 基于K3s搭建GitOps环境1-K3s安装

查看当前Context

1
kubectl config current-context

2. 配置集群信息

查看context列表

1
kubectl config get-contexts

输出中带有*的Context表示当前活动的Context

切换到指定Context

1
2
3
4
5
kubectl config use-context <context_name>

# 示例:切换到dev-ctx
kubectl config use-context dev-ctx

在指定Context中执行命令,一般用于临时使用

1
2
3
4
kubectl  --context=<context_name> <exec_cmd>

# 示例:在dev-ctx下执行get pods
kubectl --context=dev-ctx get pods

3. 合并配置文件

在 Kubernetes 环境中,使用 kubectl 管理多个集群非常常见。通过配置 kubeconfig 文件,可以轻松切换和管理多个集群。以下是实现方法的详细步骤。

方法 1: 合并多个配置文件

  • 准备配置文件 假设已有两个集群的配置文件:_/.kube/config1_ 和 _/.kube/config2_。

  • 合并配置文件 使用以下命令将多个配置文件合并为一个:

KUBECONFIG=/.kube/config1:/.kube/config2 kubectl config view –merge –flatten > ~/.kube/config

  • 验证合并结果 查看合并后的配置:

kubectl config view

方法 2: 配置环境变量

  • 设置环境变量 将多个配置文件路径添加到 KUBECONFIG 环境变量中:

export KUBECONFIG=/.kube/config:/.kube/test-config

  • 验证配置 执行以下命令查看所有集群信息:

kubectl config get-contexts

方法 3: 手动编辑配置文件

  • 打开配置文件 编辑 ~/.kube/config 文件,将其他集群的 cluster_、_context 和 user 信息粘贴到现有配置中。

  • 格式示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

apiVersion: v1

clusters:

- cluster:

server: https://127.0.0.1:6443

name: cluster1

- cluster:

server: https://192.168.0.1:6443

name: cluster2

contexts:

- context:

cluster: cluster1

user: user1

name: context1

- context:

cluster: cluster2

user: user2

name: context2

current-context: context1

切换集群上下文

  • 查看当前上下文:

    1
    kubectl config current-context
  • 切换到其他上下文:

    1
    2

    kubectl config use-context <context_name>

    最佳实践

  • 使用合并或环境变量的方法更高效,避免手动编辑出错。

  • 定期备份 kubeconfig 文件,防止误操作导致数据丢失。

  • 确保每个集群的访问凭证和权限正确无误。

通过以上方法,您可以轻松管理多个 Kubernetes 集群,提高运维效率。

大家好!在 云原生 的世界里,和 Kubernetes 打交道是家常便饭。如果我们像我一样,需要同时管理多个 Kubernetes 集群——比如一个用于严谨发布的 生产环境 ,一个用于大胆实验的 测试环境 ,甚至还有本地开发环境——那么高效、安全地在它们之间切换就成了必备技能。

很多朋友(包括我自己有时也会!)可能会因为一段时间没用而忘记 kubectl 中那些用于切换配置的命令。别担心,这很正常!今天,我们就来系统地回顾一下 kubectl 配置管理的核心概念—— 上下文(Context) ,以及如何利用它在不同集群间自如切换。

核心概念:kubeconfig 文件与上下文(Context)

kubectl 的所有配置信息都存储在一个或多个 YAML 文件中,默认情况下是 $HOME/.kube/config 。这个文件我们通常称为 kubeconfig 文件。把它想象成我们的 Kubernetes “护照”,里面记录了我们能访问哪些集群,用什么身份访问。

一个 kubeconfig 文件通常包含三个主要部分:

  1. Clusters(集群) :定义了我们要连接的 Kubernetes 集群的信息,比如 API Server 的地址和集群的 CA 证书。
  2. Users(用户) :定义了访问集群所使用的凭证,可能是用户名/密码、Token 或客户端证书。
  3. Contexts(上下文) :这是连接 集群用户 的桥梁。一个 Context 定义了使用哪个 User 凭证去访问哪个 Cluster。

关键点: 我们可以通过切换 Context 来改变 kubectl 当前操作的目标集群和使用的身份。

管理 kubeconfig 的常用 kubectl config 命令

kubectl 提供了一套 config 子命令来帮助我们查看和管理 kubeconfig 文件。以下是几个最核心、最常用的命令:

1. 查看当前配置:kubectl config view

这个命令会显示我们当前的 kubeconfig 文件内容(或者合并后的内容,如果我们配置了多个文件)。它会隐藏敏感信息(如证书和 Token 的具体内容),非常适合快速检查配置概览。

1
2
kubectl config view
bash1

如果我们想看某个特定 Context 的详细信息,可以加上 --context 参数:

1
2
3
# 查看名为 'prod-cluster' 的 context 细节
kubectl config view --context=prod-cluster
bash12
2. 列出所有可用的上下文:kubectl config get-contexts

这是 最常用 的命令之一,它会列出我们在 kubeconfig 文件中定义的所有 Context。当前正在使用的 Context 会在名称前用星号 * 标记。

1
2
3
4
5
6
7
kubectl config get-contexts
# 输出示例:
# CURRENT NAME CLUSTER AUTHINFO NAMESPACE
# * test-cluster kubernetes-test user-test
# prod-cluster kubernetes-prod user-prod production
# docker-desktop docker-desktop docker-desktop
bash123456

从上面的输出可以清晰地看到:

  • 当前激活的 Context 是 test-cluster
  • 还有名为 prod-clusterdocker-desktop 的 Context 可供切换。
3. 查看当前使用的上下文:kubectl config current-context

如果我们只想快速确认当前 kubectl 命令会作用于哪个 Context(哪个集群),这个命令最直接:

1
2
3
4
kubectl config current-context
# 输出示例:
# test-cluster
bash123
4. 切换上下文:kubectl config use-context <context-name>

这绝对是 核心中的核心 !当我们需要将 kubectl 的操作目标从一个集群切换到另一个集群时,就使用这个命令。

假设我们想从当前的 test-cluster 切换到 prod-cluster

1
2
3
4
kubectl config use-context prod-cluster
# 输出示例:
# Switched to context "prod-cluster".
bash123

切换成功后,我们可以再次使用 kubectl config current-contextkubectl config get-contexts 来验证当前上下文是否已更改。

1
2
3
4
5
6
7
8
9
10
11
kubectl config current-context
# 输出示例:
# prod-cluster

kubectl config get-contexts
# 输出示例:
# CURRENT NAME CLUSTER AUTHINFO NAMESPACE
# test-cluster kubernetes-test user-test
# * prod-cluster kubernetes-prod user-prod production
# docker-desktop docker-desktop docker-desktop
bash12345678910

现在,所有后续的 kubectl 命令(如 kubectl get pods, kubectl apply -f ... 等)都会默认发送到 prod-cluster 所定义的集群,并使用 user-prod 的身份进行认证。

实践场景:在生产和测试集群间切换

假设我们的 kubeconfig 文件中已经配置好了代表生产环境和 测试环境 的 Context,可能分别命名为 productiontesting

我们的日常操作流程可能是这样的:

  1. 检查当前在哪:
    1
    2
    kubectl config current-context
    bash1
    或者看列表:
    1
    2
    kubectl config get-contexts
    bash1
  2. 需要操作测试环境:
    1
    2
    3
    4
    5
    6
    kubectl config use-context testing
    # 验证一下(可选但推荐)
    kubectl config current-context
    # 现在可以对测试环境执行操作了
    kubectl get pods -n test-namespace
    bash12345
  3. 需要紧急处理生产环境问题:
    1
    2
    3
    4
    5
    6
    kubectl config use-context production
    # 验证一下
    kubectl config current-context
    # 操作生产环境(请务必小心!)
    kubectl get deployment -n critical-app
    bash12345
  4. 完成生产环境操作,切回测试环境继续工作:
    1
    2
    kubectl config use-context testing
    bash1

提升效率的小贴士

  1. 清晰命名 Context :给我们的 Context 起一个能清晰表明环境和用途的名字,比如 gke-prod-eu, eks-dev-us, local-minikube 等。避免使用模糊不清的名字。
  2. 使用 Shell 别名 :很多人喜欢为 kubectl 设置别名,比如 alias k=kubectl 。这样我们的命令可以更短: k config get-contexts, k config use-context my-context
  3. 考虑使用辅助工具 :社区有一些流行的小工具可以让我们更方便地切换 Context 和 Namespace,例如:
    • kubectx (用于切换 Context)
    • kubens (用于切换 Namespace)
      这些工具通常提供交互式选择或更简洁的命令,可以显著提高效率。可以通过包管理器(如 Homebrew, apt, yum)或直接下载二进制文件来安装它们。
  4. 注意 kubeconfig 文件的安全性kubeconfig 文件包含了访问集群的凭证,务必妥善保管,不要泄露给未授权的人员。

总结

管理多个 Kubernetes 集群配置并不复杂,核心就在于理解和运用 kubeconfig 文件中的 Context 概念。通过掌握 kubectl config 的几个关键子命令:

  • view: 查看配置概览
  • get-contexts: 列出所有可用上下文
  • current-context: 显示当前激活的上下文
  • use-context <context-name>: 切换到指定的上下文

我们就能轻松地在不同的 Kubernetes 环境(如生产和测试)之间安全、高效地切换了。希望这篇回顾能帮我们重新找回操作 kubectl 多集群配置的熟悉感!

概述

本文详细介绍如何在qBittorrent中通过安装插件和集成Jackett实现更强大的BT资源搜索功能。Jackett是一个支持BT/磁力资源聚合搜索的神器,聚合了400多个Public Trackers、Semi-Private Trackers、Private Trackers,可以称得上市面上最为全面的磁力资源聚合器。

一、qBittorrent原生搜索插件配置

1.1 环境准备

qBittorrent的插件是通过Python实现的,因此需要先安装Python3环境。如果使用linuxserver/qbittorrent镜像,系统已经集成了Python3,无需额外安装。

1.2 安装搜索插件

  1. 进入qBittorrent主界面 → 搜索 → 搜索插件 → 安装新插件
  2. 访问qBittorrent插件官网,选择喜爱的磁力搜索引擎
  3. 拷贝对应插件后面的插件下载链接地址,填入插件链接,点击OK即可添加

1.3 插件资源

如果因网络问题无法访问官网,可以使用以下插件包:

插件包类型 插件数量 下载地址
官方版 10个插件 下载链接
非官方版 51个插件 下载链接

替代安装方法:直接将插件脚本放入qBittorrent安装目录下的nova3/engines文件夹中,重启qb服务即可。

1.4 代理配置

由于很多搜索引擎被墙,建议在qBittorrent中配置代理:

  • 菜单 → 工具 → 选项 → 连接 → 代理服务
  • 或使用系统全局代理

二、Jackett一站式资源搜索服务

2.1 Jackett简介

Jackett是一个跨平台的资源聚合搜索工具,支持Windows、macOS、Linux系统。它聚合了400多个Tracker,是目前最全面的磁力资源聚合器。

2.2 Docker部署Jackett

docker-compose配置脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: "2.1"
networks:
dllcnx:
external: true
services:
jackett:
image: lscr.io/linuxserver/jackett:latest
container_name: jackett
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- AUTO_UPDATE=true #optional
volumes:
- /docker/jackett/config:/config #配置路径
- /docker/jackett/downloads:/downloads #下载路径
ports:
- 9117:9117
restart: unless-stopped

启动与访问

  1. 启动容器:docker-compose up -d
  2. 访问地址:http://IP:9117

2.3 Jackett基础配置

主要设置参数:

  • Admin password:如果安装Jackett的机器有公网地址,请设置管理员密码
  • Proxy type、Proxy URL、Proxy port:在此处设置代理服务器信息,则qBittorrent中无需再设置

2.4 添加磁力搜索引擎

引擎类型说明:

  • Public:公开Tracker,无需账号
  • Semi-Private:半私有Tracker
  • Private:私有Tracker,需要邀请码或注册

添加步骤:

  1. 点击”Add indexer”添加磁力搜索引擎
  2. 配置参数:
    • categories:资源类型
    • type:引擎是否公开
    • Language:搜索资源引擎语言
  3. 点击”+”即可添加

推荐引擎示例:

  • 1337x:热门资源站
  • 0Magnet:磁力链接搜索

2.5 测试与验证

  1. 添加完成后,点击”Test All”测试所有搜索引擎
  2. 点击”Manual Search”进行搜索测试

三、qBittorrent集成Jackett

3.1 获取Jackett API Key

  1. 访问Jackett Web界面
  2. 在右上角找到并复制API Key

3.2 修改qBittorrent配置

  1. 找到qBittorrent配置文件:nova3/engines/jackett.json
  2. 修改配置文件内容:
    1
    2
    3
    4
    5
    {
    "api_key": "你的API Key",
    "tracker_first": false,
    "url": "http://IP:9117"
    }

3.3 启用与测试

  1. 在qBittorrent中确认Jackett插件已启用
  2. 进行搜索测试验证集成效果

四、搜索效果对比

4.1 原生插件搜索效果

原生插件搜索效果

4.2 Jackett集成后搜索效果

Jackett集成搜索效果

五、优势与特点

5.1 Jackett优势

  1. 资源全面:聚合400+个Tracker,覆盖广泛
  2. 跨平台支持:Windows、macOS、Linux全平台
  3. 中文资源支持:相比原生插件,支持更多中文资源站
  4. 配置灵活:支持代理、API集成等多种配置方式

5.2 组合优势

  • qBittorrent + Jackett:构建完整的一站式资源搜索下载服务
  • 跨平台兼容:两者都支持多平台,组合使用无平台限制
  • 功能互补:Jackett提供强大搜索,qBittorrent提供稳定下载

六、注意事项

6.1 安全考虑

  1. 公网访问:如果Jackett部署在公网,务必设置管理员密码
  2. Private Tracker:谨慎添加Private Tracker,确保遵守相关规则
  3. 代理配置:合理使用代理,避免IP被封

6.2 性能优化

  1. 引擎选择:根据需求选择合适的Tracker,避免添加过多无用引擎
  2. 定期测试:定期测试各搜索引擎的可用性
  3. 缓存清理:定期清理不必要的缓存数据

6.3 维护建议

  1. 定期更新:保持Jackett和qBittorrent为最新版本
  2. 备份配置:定期备份配置文件
  3. 监控日志:关注系统日志,及时发现并解决问题

七、常见问题解决

7.1 插件安装失败

  • 问题:无法从官网下载插件
  • 解决:使用提供的插件包进行本地安装

7.2 搜索无结果

  • 问题:搜索时显示无结果
  • 解决
    1. 检查网络连接和代理配置
    2. 测试单个搜索引擎是否正常工作
    3. 检查API Key配置是否正确

7.3 连接超时

  • 问题:连接Jackett时超时
  • 解决
    1. 检查Jackett服务是否正常运行
    2. 确认防火墙设置
    3. 检查网络连通性

八、总结

通过本文的配置指南,您可以成功搭建qBittorrent + Jackett的一站式资源搜索下载服务。这种组合方案具有以下特点:

  1. 功能强大:结合了qBittorrent的优秀下载能力和Jackett的全面搜索能力
  2. 配置灵活:支持多种部署方式和配置选项
  3. 资源丰富:覆盖国内外大量资源站点
  4. 跨平台:支持主流操作系统

建议根据实际需求选择合适的配置方案,并定期维护更新,以获得最佳的使用体验。对于家庭NAS用户或需要大量下载资源的用户,这套方案将大大提高工作效率和资源获取能力。

一、 问题背景

连接使用自签名证书的 HTTPS 远程仓库时,Git 默认校验失败并拒绝连接。可通过以下两种方案解决:

  • 方案一(推荐):将自签名证书加入 Git 信任库,保持 SSL 校验。
  • 方案二(临时):针对特定仓库 URL 关闭 SSL 校验。

二、 方案一:信任特定自签名证书(安全)

  1. 导出证书

    • 浏览器访问仓库 HTTPS 地址。
    • 点击地址栏锁图标 -> 证书详情 -> 导出为 .pem.crt 格式。
    • 保存至本地固定路径,如 /path/to/certificate.pem
  2. 配置 Git CA Bundle

    1
    2
    3
    4
    5
    6
    7
    8
    # 全局生效(推荐)
    git config --global http.sslCAInfo /path/to/certificate.pem

    # 仅当前仓库生效
    git config http.sslCAInfo /path/to/certificate.pem

    # 验证配置路径
    git config --global http.sslCAInfo

三、 方案二:针对特定仓库禁用 SSL 验证(便捷)

适用于内网测试或临时调试,不推荐用于生产环境。

1
2
3
4
5
# 针对特定远程 URL 全局禁用验证
git config --global http.https://example.com.sslVerify false

# 仅当前仓库禁用验证
git config http.sslVerify false

四、 验证配置

1
2
3
4
5
# 克隆仓库
git clone https://example.com/repository.git

# 拉取更新
git pull origin main

执行无 SSL certificate problem 报错即表示配置生效。

五、 注意事项

  • 自签名证书无法验证服务器真实身份,存在中间人攻击风险。
  • 仓库级配置 (git config) 优先级高于全局配置 (--global)。
  • 生产环境建议申请受信任的 CA 证书,或使用企业内网 CA 统一签发。

概述

VNC(Virtual Network Computing)通过 RFB 协议实现远程控制。客户端/服务器模型:

  • VNC 客户端:本地计算机
  • VNC 服务器:远程系统,传输显示画面副本

安装 VNC 服务器

1
2
sudo apt update
sudo apt -y install tightvncserver

安装桌面环境

使用 Xfce 桌面环境:

1
sudo apt install xfce4 xfce4-goodies

配置 VNC 服务器

设置密码

1
2
3
vncpasswd
Password:
Verify:

启动 VNC 服务器

1
vncserver :1

输出示例:

1
2
3
4
New 'ubuntu-01:1 (user)' desktop is ubuntu-01:1
Creating default startup script /home/user/.vnc/xstartup
Starting applications specified in /home/user/.vnc/xstartup
Log file is /home/user/.vnc/ubuntu-01:1.log

终止 VNC 服务器

1
vncserver -kill :1

配置桌面环境

编辑 VNC 启动脚本:

1
vim ~/.vnc/xstartup

添加内容:

1
exec /usr/bin/startxfce4 &

启动参数说明

参数 含义 示例值
:1 显示编号 :1
-geometry 分辨率 800x600
-depth 颜色深度 24

启动示例:

1
vncserver :1 -geometry 800x600 -depth 24

连接 VNC 桌面

SSH 隧道

创建安全隧道:

1
ssh <username>@<vncserver-ip> -C -L 5901:127.0.0.1:5901

安装客户端

Ubuntu:

1
sudo apt install tigervnc-viewer

Arch Linux:

1
sudo pacman -S tigervnc

连接

SSH 隧道运行后,连接 localhost:5901,输入 VNC 密码。


配置 Systemd 服务

停止现有实例

1
vncserver -kill :1

创建服务文件

1
sudo vim /etc/systemd/system/vncserver@1.service

写入配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=Start TightVNC server at startup
After=syslog.target network.target

[Service]
Type=forking
User=your_username
Group=your_username
WorkingDirectory=/home/your_username
PIDFile=/home/your_username/.vnc/%H:%i.pid
ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 :%i
ExecStop=/usr/bin/vncserver -kill :%i

[Install]
WantedBy=multi-user.target

注意:将 your_username 替换为实际用户名。

启用服务

1
2
sudo systemctl daemon-reload
sudo systemctl enable --now vncserver@1

检查状态

1
systemctl status vncserver@1

安全建议

VNC 密码传输无加密,推荐使用:

  • VPN:加密连接,隐藏服务器位置
  • SSH 隧道:如上述配置
  • 防火墙:限制 5900 端口访问

总结

完成以下步骤即可在 Ubuntu 上运行 VNC 服务器:

  1. 安装 tightvncserver 和 Xfce 桌面
  2. 配置密码和 xstartup 脚本
  3. 设置 SSH 隧道保证连接安全
  4. 配置 Systemd 服务实现开机自启

概述

TensorRT 是 NVIDIA 官方推出的深度学习推理优化工具,专为 NVIDIA GPU 设计,可显著提升模型推理速度并减少内存占用。支持 TensorFlow、PyTorch 等主流框架,通过 ONNX 实现跨框架模型转换。


一、安装TensorRT

1.1 官方包安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 下载匹配CUDA版本的deb包(需NVIDIA账号)
sudo dpkg -i nv-tensorrt-repo-${os}-${tag}_1-1_amd64.deb
sudo apt-key add /var/nv-tensorrt-repo-${os}-${tag}/7fa2af80.pub
sudo apt-get update
sudo apt-get install tensorrt

# Python依赖
python3 -m pip install numpy
sudo apt-get install python3-libnvinfer-dev

# ONNX支持(可选)
python3 -m pip install numpy onnx
sudo apt-get install onnx-graphsurgeon

# PyCUDA(必需)
python3 -m pip install 'pycuda<2021.1'

1.2 验证安装

1
2
3
4
5
6
7
8
9
# 检查系统包
dpkg -l | grep TensorRT

# 验证Python环境
python3 -c "
import tensorrt
print(tensorrt.__version__)
assert tensorrt.Builder(tensorrt.Logger())
"

注意:Anaconda虚拟环境中需额外执行:

1
python3 -m pip install --upgrade nvidia-tensorrt

二、PyTorch → TensorRT 转换流程

2.1 PyTorch → ONNX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import torch
import torchvision.models as models

# 加载预训练模型
model = models.resnext50_32x4d(pretrained=True)
dummy_input = torch.randn(32, 3, 224, 224) # BATCH_SIZE=32

# 导出ONNX
torch.onnx.export(
model,
dummy_input,
"resnet50_onnx_model.onnx",
verbose=False
)

替代方案:直接从 ONNX Model Zoo 下载预训练模型

2.2 ONNX → TensorRT

使用 trtexec 命令行工具(位于 /usr/src/tensorrt/bin/):

1
2
3
4
5
6
7
8
9
10
11
# 基础转换
./trtexec --onnx=resnet50_onnx_model.onnx \
--saveEngine=resnet_engine.trt

# 推荐参数(固定batch + FP16)
./trtexec --onnx=resnet50_onnx_model.onnx \
--saveEngine=resnet_engine.trt \
--explicitBatch \
--inputIOFormats=fp16:chw \
--outputIOFormats=fp16:chw \
--fp16

关键参数说明

参数 作用
--explicitBatch 固定输入batch size(与ONNX导出时一致)
--fp16 启用FP16精度(加速+省显存)
--inputIOFormats 指定输入数据格式

精度选项:TF32/FP32(默认)/FP16/INT8(需校准)


三、TensorRT 推理实现

3.1 Runtime选择

Runtime 适用场景 性能
C++ API 通用高性能需求 ★★★★
TF-TRT TensorFlow专用 ★★
Triton 多框架服务化 ★★★

推荐:PyTorch模型选用 C++ API(通过Python绑定)

3.2 Python推理代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import numpy as np
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import time

# 配置参数
BATCH_SIZE = 32
USE_FP16 = True
target_dtype = np.float16 if USE_FP16 else np.float32

# 加载引擎
with open("resnet_engine.trt", "rb") as f:
runtime = trt.Runtime(trt.Logger(trt.Logger.WARNING))
engine = runtime.deserialize_cuda_engine(f.read())
context = engine.create_execution_context()

# 内存分配
input_batch = np.random.randn(BATCH_SIZE, 224, 224, 3).astype(target_dtype)
output = np.empty([BATCH_SIZE, 1000], dtype=target_dtype)
d_input = cuda.mem_alloc(input_batch.nbytes)
d_output = cuda.mem_alloc(output.nbytes)
bindings = [int(d_input), int(d_output)]
stream = cuda.Stream()

# 预处理函数
def preprocess_input(input_data):
# (224,224,3) → (3,224,224)
result = torch.from_numpy(input_data).transpose(0,2).transpose(1,2)
return np.array(result, dtype=target_dtype)

# 推理函数
def predict(batch):
cuda.memcpy_htod_async(d_input, batch, stream)
context.execute_async_v2(bindings, stream.handle, None) # 异步推理
cuda.memcpy_dtoh_async(output, d_output, stream)
stream.synchronize()
return output

# 执行推理
preprocessed_inputs = np.array([
preprocess_input(inp) for inp in input_batch
])
print("Warming up...")
pred = predict(preprocessed_inputs)
print("Done warming up!")

t0 = time.time()
pred = predict(preprocessed_inputs)
print(f"Prediction cost {time.time()-t0:.4f}s")

关键点

  • 输入/输出内存需在GPU上分配
  • 数据格式需与导出时一致(CHW vs HWC)
  • 异步推理(execute_async_v2)性能优于同步

四、性能验证

测试模型:SlowFast 行为识别
输入尺寸(1,1,3,32,256,256)
结果:TensorRT 相比原生 PyTorch 推理速度显著提升(具体数据见原文图表)


参考资源

官方文档

社区资源

一、 概述与核心概念

1.1 什么是 CoreDNS?

CoreDNS 是一个用 Go 语言编写的、高度可扩展和插件化的 DNS 服务器。它来自云原生计算基金会(CNCF),是 Kubernetes 的默认 DNS 服务器,其设计目标是易于使用且功能强大。

核心特点

  • 插件化架构:几乎所有功能都通过插件实现,可以灵活组合,适用于传统 DNS、服务发现、负载均衡等多种场景。
  • 高性能与可靠性:基于 Go 语言,性能优异。支持自动重试、健康检查和负载均衡。
  • 易于配置:使用简单易懂的 Caddyfile 格式配置文件。
  • Kubernetes 原生:深度集成 K8s,用于集群内服务发现。
1.2 CoreDNS 与传统 DNS(如 BIND)的区别

传统 DNS 服务器功能固定且庞大。CoreDNS 则像一个“DNS 功能总线”,通过加载不同的插件来实现特定功能,这使得它更轻量、更灵活。正如其官方所说:CoreDNS is powered by plugins.

1.3 核心配置文件:Corefile

CoreDNS 的行为由 Corefile 定义。其基本结构如下:

1
2
3
4
5
# ZONE: 定义服务器负责的区,PORT 默认为 53
ZONE:[PORT] {
# PLUGIN: 定义要加载的插件及其参数
[PLUGIN] [PLUGIN_ARGUMENTS]...
}

示例

1
2
3
4
5
6
7
.:53 {
whoami
}

weiyigeek.top {
file db.weiyigeek.top
}

二、 安装与基础配置

2.1 安装 CoreDNS

方式一:二进制安装(推荐)

1
2
3
4
COREDNS_VERSION="1.11.1"
wget https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_amd64.tgz
tar xf coredns_${COREDNS_VERSION}_linux_amd64.tgz -C /usr/local/bin/
ln -s /usr/local/bin/coredns /usr/bin/coredns

方式二:从源码编译

1
2
3
4
5
git clone -b v1.11.1 https://github.com/coredns/coredns
cd coredns
make
# 或使用 Docker 环境编译
docker run --rm -i -t -v $PWD:/v -w /v golang:1.21 make
2.2 系统服务化部署
  1. 创建专用用户和目录
    1
    2
    3
    useradd coredns -s /sbin/nologin
    mkdir -p /etc/coredns/
    chown -R coredns /etc/coredns/
  2. 创建 Systemd 服务文件 (/usr/lib/systemd/system/coredns.service):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [Unit]
    Description=CoreDNS DNS server
    Documentation=https://coredns.io
    After=network.target

    [Service]
    LimitNOFILE=1048576
    User=coredns
    WorkingDirectory=/etc/coredns
    ExecStart=/usr/bin/coredns -conf=/etc/coredns/Corefile
    ExecReload=/bin/kill -SIGUSR1 $MAINPID
    Restart=on-failure

    [Install]
    WantedBy=multi-user.target
1
2
systemctl daemon-reload
systemctl enable coredns
  1. 配置防火墙
    1
    2
    firewall-cmd --permanent --add-service=dns
    firewall-cmd --reload
2.3 基础配置文件示例

创建 /etc/coredns/Corefile,配置一个简单的 DNS 服务器,使用 hosts 插件进行本地解析,并转发未知查询到上游 DNS。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.:53 {
bind 0.0.0.0
hosts {
# 自定义本地解析
192.168.1.2 www.weiyigeek.top
192.168.1.3 blog.weiyigeek.top
ttl 60
reload 1m
fallthrough # 未匹配时继续执行下一个插件
}
# 转发未知查询到公共 DNS
forward . 223.6.6.6 114.114.114.114
cache 120 # 缓存
log # 记录日志
errors # 记录错误
}
  1. 启动并测试
    1
    2
    3
    systemctl start coredns
    dig www.weiyigeek.top @localhost
    dig google.com @localhost # 应被转发解析

三、 插件系统详解

3.1 插件概述与工作模式

CoreDNS 的功能完全由插件驱动。插件分为两类:

  • Normal 插件:参与请求处理逻辑,并出现在插件链中(如 hosts, file, forward)。
  • Other 插件:不参与请求逻辑,仅修改服务器配置(如 health, ready, prometheus)。

插件链执行逻辑

  1. 请求进入匹配的 Server Zone。
  2. plugin.cfg 定义的顺序依次执行插件链上的插件。
  3. 每个插件决定如何处理请求:直接响应、传递 (fallthrough)、或添加信息后继续传递。

查看可用插件coredns -plugins

3.2 常用插件详解
hosts 插件

用于从 /etc/hosts 风格的文件或内联配置提供 A/AAAA/PTR 记录。适合少量静态记录。

  • 语法
    1
    2
    3
    4
    5
    6
    hosts [FILE] {
    [INLINE_ENTRIES]
    ttl SECONDS
    reload DURATION
    fallthrough [ZONES...]
    }
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    .:53 {
    hosts {
    192.168.1.10 api.internal
    192.168.1.11 db.internal
    fallthrough
    }
    forward . 8.8.8.8
    }
file 插件

用于从符合 RFC 1035 标准的主区域文件提供 DNS 服务。适合大量记录或需要标准区域文件管理的场景。

  • 语法
    1
    2
    3
    file DBFILE [ZONES...] {
    reload DURATION
    }
  • 示例
    1
    2
    3
    weiyigeek.top {
    file /etc/coredns/db.weiyigeek.top
    }
    *区域文件示例 (/etc/coredns/db.weiyigeek.top)*:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $TTL 86400
    @ IN SOA ns1.weiyigeek.top. admin.weiyigeek.top. (
    2023082501 ; Serial
    7200 ; Refresh
    3600 ; Retry
    1209600 ; Expire
    3600 ) ; Negative Cache TTL
    ;
    @ IN NS ns1
    ns1 IN A 192.168.1.100
    www IN A 192.168.1.101
forward 插件

将查询转发到上游 DNS 服务器。是构建递归解析器或指定上游的关键插件。

  • 语法
    1
    forward . UPSTREAM_DNS...
  • 示例
    1
    2
    3
    4
    .:53 {
    forward . 8.8.8.8:53 1.1.1.1:53 /etc/resolv.conf
    cache 60
    }
cache 插件

缓存 DNS 响应,减少上游查询,提升性能。

  • 语法
    1
    2
    3
    4
    cache [TTL] {
    success CAPACITY [TTL]
    denial CAPACITY [TTL]
    }
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    .:53 {
    forward . 8.8.8.8
    cache 120 # 缓存所有响应120秒
    # 或更精细控制
    cache {
    success 5000 300
    denial 1000 60
    }
    }
3.3 Kubernetes 集成插件 (kubernetes)

CoreDNS 在 K8s 中的核心插件,用于服务发现(将 Service 名称解析为 ClusterIP)。

  • 典型 K8s 配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    .:53 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
    pods verified
    fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
    }

四、 高级配置与实战

4.1 多区域与复杂配置

一个 Corefile 可以定义多个服务器块,处理不同域或端口的请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 处理内部域
internal.company {
file /etc/coredns/db.internal
log
}

# 处理外部域,监听在5300端口
example.com:5300 {
forward . 8.8.8.8
cache 300
}

# 默认处理所有其他查询
.:53 {
forward . 1.1.1.1 9.9.9.9
cache 60
errors
log
}
4.2 DNSSEC 配置

CoreDNS 支持动态 DNSSEC 签名。

  1. 生成 DNSSEC 密钥
    1
    2
    3
    cd /etc/coredns
    dnssec-keygen -a ECDSAP256SHA256 -f KSK weiyigeek.top
    # 生成 Kweiyigeek.top.+013+12345.key 和 .private 文件
  2. 使用 dnssec 插件(动态签名响应):
    1
    2
    3
    4
    5
    6
    weiyigeek.top {
    file /etc/coredns/db.weiyigeek.top
    dnssec {
    key file /etc/coredns/Kweiyigeek.top.+013+12345.key
    }
    }
  3. 使用 sign 插件(预签名区域文件):
    1
    2
    3
    4
    5
    6
    weiyigeek.top {
    sign /etc/coredns/db.weiyigeek.top {
    key file /etc/coredns/Kweiyigeek.top.+013+12345.key
    directory /var/lib/coredns
    }
    }
    签名后的区域文件将保存在 /var/lib/coredns/db.weiyigeek.top.signed
4.3 TSIG 配置(事务签名)

用于验证和签名 DNS 请求/响应,常用于区域传输(AXFR/IXFR)安全。

  1. 生成 TSIG 密钥
    1
    tsig-keygen -a hmac-sha256 dns-tsig-key. > /etc/coredns/dns-tsig.secrets
  2. 配置 tsig 插件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    weiyigeek.top {
    file /etc/coredns/db.weiyigeek.top
    tsig {
    secrets /etc/coredns/dns-tsig.secrets
    require AXFR IXFR # 要求区域传输必须签名
    }
    transfer {
    to * # 允许向任何请求者传输(生产环境应限制IP)
    }
    }
4.4 使用 etcd 插件实现动态服务发现

可以将服务记录存储在 etcd 中,CoreDNS 从中读取。

1
2
3
4
5
6
7
8
9
etcd-weiyigeek.local:53 {
etcd {
path /skydns
endpoint http://172.22.50.98:2379
fallthrough
}
cache 160
log
}

在 etcd 中存储记录

1
etcdctl put /skydns/local/etcd-weiyigeek/www '{"host":"172.22.50.100","ttl":60}'

查询dig www.etcd-weiyigeek.local

五、 故障排查与性能优化

  • 查看日志:确保配置中启用了 logerrors 插件。
  • 检查插件顺序:插件链顺序很重要,例如 cache 应在 forward 之后。
  • 监控:启用 prometheus 插件(默认在 :9153 端口)以获取指标。
  • 性能调优
    • 合理设置 cache 插件的 TTL 和容量。
    • 根据负载调整 forward 插件中的上游 DNS 服务器列表。
    • 使用 loadbalance 插件实现上游 DNS 的轮询负载均衡。

六、 总结

CoreDNS 凭借其插件化、高性能和易配置的特性,已成为从传统 DNS 到云原生服务发现的理想选择。通过灵活组合 hostsfileforwardcache 等插件,可以轻松构建出满足各种需求的 DNS 架构。对于 Kubernetes 环境,它更是不可或缺的核心组件。

官方资源


提示:生产环境部署时,请务必关注安全最佳实践,如使用非 root 用户运行、配置适当的防火墙规则、为区域传输启用 TSIG、以及定期更新 CoreDNS 版本。

1 背景与演进

1.1 为什么需要分布式文件系统

阶段 特点 优缺点
单机时代 项目目录下建立静态文件夹 简单但文件与代码耦合,流量大时影响业务
独立文件服务器 图片服务器 + Nginx 独立部署 性能分离但存在单机瓶颈
分布式文件系统 存储 + 仲裁 + 容灾三系统配合 高可用、可扩展,但复杂度较高

1.2 适用场景

FastDFS 特别适合以中小文件(建议范围:4KB < file_size < 500MB)为载体的在线服务:

  • 相册网站
  • 视频网站
  • 网盘、社区、广告等业务存储

2 FastDFS 概述

2.1 核心特性

  • 轻量级:纯 C 实现,支持 Linux、FreeBSD 等 UNIX 系统
  • 文件一对一:文件不分块存储,与 OS 文件系统一一对应
  • 去重:相同内容文件只保存一份,节约磁盘空间
  • HTTP 支持:内置 Web Server 或配合 Nginx/Apache
  • 在线扩容:支持动态扩展存储容量
  • 主从文件:支持主从文件机制
  • 高性能:V2.0 采用 libevent 网络通信,支持大并发

2.2 架构定位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────────────────────────────────────────────────┐
│ Client │
│ (业务请求发起方) │
└─────────────────────┬───────────────────────────────┘

┌───────▼───────┐
│ Tracker │
│ (调度中心) │
└───────┬───────┘

┌─────────────┼─────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Storage 1│ │Storage 2│ │Storage N│
│ (Group1)│ │ (Group1)│ │ (Group2)│
└─────────┘ └─────────┘ └─────────┘

3 核心概念

3.1 服务角色

角色 职责 特点
Tracker Server 调度、负载均衡 内存记录所有 storage 状态,无持久化,易扩展
Storage Server 文件存储 以组为单位组织,文件属性(meta-data)一并保存
Client 业务请求发起 通过专有 API 与 tracker/storage 交互

3.2 核心术语

术语 说明
Group / Volume 卷/组,同组内服务器文件完全相同,互为备份
Meta-data 文件属性,Key-Value 键值对(如:width=1024)
FID File ID,文件唯一标识

3.3 Storage 组织结构

1
2
3
4
5
6
7
8
9
Storage Server
├── /data/disk1/ # 数据存储目录1
│ ├── 00/
│ │ ├── 00/
│ │ ├── 01/
│ │ └── ...
│ └── FF/
├── /data/disk2/ # 数据存储目录2
└── ...
  • 每个存储目录创建 2 级子目录(每级 256 个)
  • 总共 65536 个文件目录
  • 文件按 hash 路由到对应子目录

4 上传机制

4.1 上传流程

1
2
3
4
5
6
┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│ Client │────▶│ Tracker │────▶│ Storage │────▶│ 写入磁盘 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │
▼ ▼
返回 ip:port 生成 file_id

4.2 选择策略

1. 选择 Group

规则 说明
Round robin 所有 group 间轮询
Specified group 指定确定 group
Load balance 剩余空间多的 group 优先

2. 选择 Storage Server

规则 说明
Round robin group 内所有 storage 间轮询
First server ordered by IP 按 IP 排序
First server ordered by priority 按优先级排序

3. 选择 Storage Path

规则 说明
Round robin 多个存储目录间轮询
剩余空间优先 剩余存储空间最多的目录优先

4.3 FileId 生成

1
FileId = base64(storage_ip + 文件创建时间 + 文件大小 + crc32 + 随机数)

4.4 文件名组成

1
文件名 = group + 虚拟磁盘路径 + 两级子目录 + file_id + 文件后缀

示例

1
group1/M00/00/00/wKgBaE9u4O6Ab7SDAAvgG5Q3vw428.jpg

5 下载机制

5.1 下载流程

1
2
3
┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│ Client │────▶│ Tracker │────▶│ Storage │────▶│ 返回文件 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘

5.2 Storage 选择策略

Tracker 按以下优先级选择可读的 storage:

优先级 条件 说明
1 源头 storage 文件上传时的源服务器,肯定包含文件
2 同步完成 文件创建时间 + 最大同步时间 < 当前时间
3 同步时间戳 文件创建时间 < storage 同步时间戳
4 延迟阈值 当前时间 - 文件创建时间 > 同步延迟阈值

6 同步机制

6.1 同步原理

1
2
3
4
5
6
┌──────────┐      binlog       ┌──────────┐
│Storage A │ ───────────────▶ │Storage B │
└──────────┐ └──────────┘
│ │
└─────────── 上报 ──────────────┘
Tracker
  • Storage 写文件后,后台异步同步到同组其他 server
  • 同步信息以 binlog 形式记录(不包含文件数据)
  • 同步进度以时间戳方式记录

6.2 时钟同步要求

集群内所有服务器时钟必须保持同步,否则同步进度计算会出错。


7 文件定位(FID)

7.1 FID 组成

1
FID = group + 虚拟磁盘路径 + 两级子目录 + file_id + 文件后缀

7.2 快速定位原理

步骤 操作 说明
1 解析 group tracker 定位到目标 storage group
2 解析路径 根据虚拟磁盘路径定位存储目录
3 解析目录 根据两级子目录定位具体目录
4 查找文件 根据文件名定位文件

8 集群部署

8.1 典型架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                ┌─────────────────────────────────────┐
│ Nginx │
│ (负载均衡/静态资源) │
└─────────────────┬───────────────────┘

┌──────────────────────────┼──────────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Tracker1 │ │ Tracker2 │ │ Tracker3 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ Group1 │ │ Group2 │ │ Group3 │
│ S1 S2 S3 │ │ S4 S5 S6 │ │ S7 S8 S9 │
└─────────────┘ └─────────────┘ └─────────────┘

8.2 部署建议

配置项 建议
Tracker 数量 至少 2 台,实现高可用
Group 内 Storage 3 台以上,互为备份
存储目录 多磁盘挂载,充分利用空间
时钟同步 所有节点配置 NTP 服务

9 Java 客户端使用

9.1 Maven 依赖

1
2
3
4
5
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.29-RELEASE</version>
</dependency>

9.2 配置文件

1
2
3
fastdfs.tracker_list=192.168.1.100:22122,192.168.1.101:22122
fastdfs.connect_timeout_in_seconds=5
fastdfs.network_timeout_in_seconds=30

9.3 上传示例

1
2
3
4
5
6
7
8
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = null;

StorageClient storageClient = new StorageClient(trackerServer, storageServer);
String[] result = storageClient.upload_file("/path/to/file.jpg", "jpg", null);
System.out.println("Group: " + result[0]);
System.out.println("Path: " + result[1]);

10 总结

10.1 核心优势

  • 高性能:轻量级设计,支持高并发
  • 高可用:多 tracker、多 storage 集群支持
  • 可扩展:在线扩容,灵活增加存储节点
  • 低成本:开源免费,硬件要求低

10.2 适用场景

  • 中小文件为主的在线服务
  • 需要高可用存储的业务系统
  • 对成本敏感但需要分布式存储的场景

10.3 参考资源

资源 链接
官方 GitHub https://github.com/happyfish100/
配置文档 https://github.com/happyfish100/fastdfs/wiki/
Java 客户端 https://github.com/happyfish100/fastdfs-client-java
0%