标签归档:linux

解决 Linux Wayland 环境下 Joplin 使用 fcitx5 中文输入漏字问题

在 Linux + Wayland 环境下使用 Joplin 时,如果配合 fcitx5 输入中文,可能会遇到输入漏字的问题。

下面这份配置可作为参考:

➜  Downloads cat /usr/share/applications/joplin-desktop.desktop
[Desktop Entry]
Name=Joplin
Comment=Joplin for Desktop
-Exec=/usr/bin/joplin-desktop --gtk-version=3 --ozone-platform=x11
+Exec=/usr/bin/joplin-desktop --gtk-version=3 --ozone-platform-hint=auto --enable-wayland-ime
Terminal=false
Icon=joplin-desktop
StartupWMClass=@joplin/app-desktop
Type=Application
Categories=Office;
MimeType=x-scheme-handler/joplin;
SingleMainWindow=true

使用 --ozone-platform=x11 可以解决 Joplin 全局菜单不显示的问题,但中文输入时可能会出现漏字。

改用 --ozone-platform-hint=auto --enable-wayland-ime 后,可以解决 fcitx5 中文输入漏字的问题;不过相应地,Joplin 全局菜单可能又无法正常显示。

实测二者不可两全,暂无找到很好的方法。建议先采用第一行配置,显示出来菜单做好配置后,改用第二行配置,确保后期中文输入体现。

输入漏字真的很恼火,如有两全解决方案欢迎讨论。

Refs

修复 Joplin on KDE 菜单栏显示问题

在 KDE 桌面下默认使用全局菜单显示应用程序的菜单栏,但是唯独 Joplin 无法显示。

最后在这里找到了解决方案,下面简单记录:

sudo vim /usr/share/applications/joplin-desktop.desktop 
--Exec=/usr/bin/joplin-desktop
++Exec=/usr/bin/joplin-desktop --gtk-version=3 --ozone-platform=x11

启动程序增加这两个参数即可解决。

Refs

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=21yjpwt8mhhc0

Copy Fail:Linux 内核 2017 年至今的高危漏洞(附临时缓解方案) | CVE-2026-31431

最近爆出一个 Linux 内核存在近10年的漏洞,随便找了一台最近在用的机器试了一下,直接成功提权:

~$ whoami
songtianlun
~$ python3 test.py 
# whoami
root

临时解决方案如下:

由于 SSH/OpenSSL 等安全基建库几乎都在使用自行维护的用户态加密库, 所以 AF_ALG 可以直接禁用, 为临时缓解措施 (仅供参考):

rmmod algif_aead 2>/dev/null || true
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf

再尝试就不行了:

~$ python3 test.py Traceback (most recent call last):
  File "/home/songtianlun/test.py", line 9, in 
<module>
    while i<len(e):c(f,i,e[i:i+4]);i+=4
  File "/home/songtianlun/test.py", line 5, in c
    a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
FileNotFoundError: [Errno 2] No such file or directory

影响面甚广,赶快检查一下自己的服务器。

Refs

在 K3s 节点上安装并使用 nerdctl

适用场景:K3s 默认不附带 nerdctl,但其内置的 containerd 与 nerdctl 完全兼容。本教程讲解如何在 K3s 节点上以最小代价安装 nerdctl,并正确指向 K3s 的 containerd socket,无需重复安装 containerd 或 CNI。

一、背景与原理

工具 说明
ctr containerd 内置调试工具,与 Docker CLI 不兼容,功能有限
crictl CRI 调试工具,K3s 自带,面向 Kubernetes 运维
nerdctl Docker 兼容 CLI,支持 run/build/compose推荐日常使用

K3s 的 containerd socket 路径为 /run/k3s/containerd/containerd.sock,而非标准路径 /run/containerd/containerd.sock。只需在配置中指向该路径,nerdctl 即可接管 K3s 容器管理。

K3s 已自带 CNI 插件(flannel/calico 等),查看 K3s 节点已有的 Pod 和镜像无需额外 CNI。若需要 nerdctl run 启动独立容器并连接网络,则需要补充安装 CNI 插件(见第四节)。

二、安装 nerdctl(仅二进制)

K3s 节点已有 containerd,只需下载 nerdctl 的精简包(不含 containerd/CNI,体积小)。

2.1 下载二进制

# 查询最新版本(或手动前往 https://github.com/containerd/nerdctl/releases 查看)
NERDCTL_VERSION=$(curl -s https://api.github.com/repos/containerd/nerdctl/releases/latest \
  | grep tag_name | cut -d '"' -f4 | tr -d 'v')

echo "最新版本: ${NERDCTL_VERSION}"

# 下载精简包(仅 nerdctl 二进制)
curl -LO "https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz"

ARM64 节点(如树莓派、ARM 服务器)将 amd64 替换为 arm64

curl -LO "https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-arm64.tar.gz"

2.2 解压并安装

# 解压到 /usr/local/bin
sudo tar Cxzvf /usr/local/bin nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz nerdctl

# 验证安装
nerdctl --version

三、配置 nerdctl 指向 K3s containerd

nerdctl 默认连接 /run/containerd/containerd.sock,在 K3s 节点上需要修改为 K3s 专用路径。

3.1 创建配置文件

sudo mkdir -p /etc/nerdctl

sudo tee /etc/nerdctl/nerdctl.toml > /dev/null <<EOF
# nerdctl 全局配置,适配 K3s 节点
address        = "/run/k3s/containerd/containerd.sock"
namespace      = "k8s.io"
EOF

说明

  • address:K3s containerd 的 socket 路径
  • namespace:K3s 所有容器和镜像均存储在 k8s.io 命名空间下

3.2 验证连接

# 列出 K3s 命名空间下的所有容器(等同于 kubectl get pods 的容器视角)
sudo nerdctl ps -a

# 列出镜像
sudo nerdctl images

如果能看到 K3s 系统 Pod(如 coredns、traefik 等),说明配置成功。

四、安装 CNI 插件(按需,用于 nerdctl run)

如果只需要查看 K3s 已有容器和镜像,可跳过此节。

只有当你需要用 nerdctl run 启动独立容器(即非 Kubernetes 管理的容器)时,才需要 CNI 插件。K3s 自带的 CNI 仅供 Kubernetes 使用,nerdctl 的独立容器网络需要单独配置。

4.1 下载官方 CNI 插件

CNI_VERSION=$(curl -s https://api.github.com/repos/containernetworking/plugins/releases/latest \
  | grep tag_name | cut -d '"' -f4)

curl -LO "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-amd64-${CNI_VERSION}.tgz"

# 安装到标准路径
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-${CNI_VERSION}.tgz

4.2 创建默认网络配置

sudo mkdir -p /etc/cni/net.d

sudo tee /etc/cni/net.d/10-nerdctl-bridge.conflist > /dev/null <<EOF
{
  "cniVersion": "1.0.0",
  "name": "nerdctl-bridge",
  "plugins": [
    {
      "type": "bridge",
      "bridge": "nerdctl0",
      "isGateway": true,
      "ipMasq": true,
      "ipam": {
        "type": "host-local",
        "ranges": [
          [{"subnet": "10.88.0.0/16"}]
        ],
        "routes": [{"dst": "0.0.0.0/0"}]
      }
    },
    {
      "type": "portmap",
      "capabilities": {"portMappings": true}
    },
    {
      "type": "firewall"
    }
  ]
}
EOF

注意:此桥接网络(10.88.0.0/16)仅供 nerdctl 管理的独立容器使用,不会影响 K3s 自身网络。

4.3 验证独立容器运行

# 注意:启动独立容器时需使用默认命名空间(不加 --namespace k8s.io)
# 或在 nerdctl.toml 中临时切换,推荐直接在命令行覆盖:
sudo nerdctl --namespace default run -d --name test-nginx -p 8080:80 nginx:alpine

# 确认运行
sudo nerdctl --namespace default ps
curl http://localhost:8080

五、常用命令速查

所有命令均需 sudo(或将当前用户加入 containerd 相关权限组)。

查看 K3s 容器和镜像

# 列出所有容器(K3s 管理)
sudo nerdctl ps -a

# 列出镜像
sudo nerdctl images

# 查看容器日志
sudo nerdctl logs <容器ID或名称>

# 进入容器终端
sudo nerdctl exec -it <容器ID或名称> sh

镜像管理

# 拉取镜像(拉取后可直接被 K3s Pod 使用)
sudo nerdctl pull nginx:alpine

# 查看镜像详情
sudo nerdctl inspect <镜像ID>

# 删除镜像
sudo nerdctl rmi <镜像ID>

# 从 tar 包导入镜像(常用于离线环境)
sudo nerdctl load < image.tar

# 导出镜像为 tar 包
sudo nerdctl save nginx:alpine -o nginx.tar

构建镜像(需安装 BuildKit,见第六节)

sudo nerdctl build -t myapp:v1 /path/to/dockerfile-dir

配合 kubectl 使用本地镜像

# 构建并打 tag 到 k8s.io 命名空间
sudo nerdctl --namespace k8s.io build -t myapp:local .

# 然后在 Pod spec 中指定 imagePullPolicy: Never 即可使用本地镜像
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: myapp
    image: myapp:local
    imagePullPolicy: Never
EOF

六、可选:安装 BuildKit(支持 nerdctl build)

nerdctl 构建镜像需要 BuildKit daemon。

BUILDKIT_VERSION=$(curl -s https://api.github.com/repos/moby/buildkit/releases/latest \
  | grep tag_name | cut -d '"' -f4)

curl -LO "https://github.com/moby/buildkit/releases/download/${BUILDKIT_VERSION}/buildkit-${BUILDKIT_VERSION}.linux-amd64.tar.gz"

sudo tar Cxzvf /usr/local buildkit-${BUILDKIT_VERSION}.linux-amd64.tar.gz

# 创建 systemd 服务
sudo tee /etc/systemd/system/buildkit.service > /dev/null <<EOF
[Unit]
Description=BuildKit
After=network.target containerd.service

[Service]
ExecStart=/usr/local/bin/buildkitd \
  --addr unix:///run/buildkit/buildkitd.sock \
  --containerd-worker-addr /run/k3s/containerd/containerd.sock
Restart=always

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now buildkit

Refs

KDE Plasma6 禁用全局菜单,恢复正常应用菜单

前情提要

不知道从什么时候开始,KDE Plasma 默认启用类似 macOS 的全局应用菜单。

即应用窗口标题栏下方不显示菜单,而是移动到顶部菜单栏中“全局菜单”小组件中。

但问题是,Linux 桌面生态生态复杂,X11 Wayland Qt GTK 等等技术太过复杂,很难保证常用软件都能够正常显示全局菜单。

比如我最近在使用 Joplin ,就发现除了菜单栏根本找不到任何入口。

于是搜索了一番后,终于找到了关闭全局菜单,恢复正常的应用菜单的方法。

恢复方法

第一步:移除“全局菜单组件”

Edit Mode > Add or Manage Widgets > Global Menu > Remove all instances (button in the top right corner of the widget)

进入编辑模式,添加或管理组件,删除“全局菜单”小组间

image

第二步:移除应用菜单

实测完成第一步即可,第二步按照自己实际情况决定是否要做。

Settings > Colors & Themes > Window Decorations > Configure Titlebar Buttons…

There remove the Application Menu (“Hamburger”) button from your titlebars.

进入设置,颜色与主题,窗口装饰元素,配置菜单栏按钮,将“应用菜单”按钮移除,点击应用,即可。

image

第三步:重启应用

此时应该就能看到应用菜单了,如果看不到再重启一下即可。

image

Refs

彻底解决阿里云和 tailscale 冲突

如果你在一台阿里云服务器安装并启动了 tailscale,大概率会出现阿里云服务器无法上网的问题,根本原因为阿里云服务器默认DNS与tailscale网段产生冲突。

由于阿里云和 tailscale 都使用了 100.64.0.0/10 这个网段。100.64.0.0/10RFC 6598 中被保留为 运营商级 NAT (Carrier-Grade NAT) 地址段,用于 ISP 做 NAT 时避免与内网冲突。Tailscale 把它当成“只允许来自 Tailscale 接口的地址段”是符合规范的。但阿里云在 VPC 内把 100.100.2.136100.100.2.138 作为内网 DNS 服务地址,初衷是: 地址在公网不可路由,避免外泄; 与经典网络互通时不会冲突。

由于动机不同,目标不同,造成二者冲突。

目前比较流行的方法,是关闭 tailscale 的 iptables 规则生成,但这是不安全的。浏览各种解决方案后我认为脚本轮询的方案最可靠。

脚本轮训解决

/usr/local/bin/fix-ts-dns.sh

#!/bin/bash
while true; do
  if ! iptables -C ts-input -s 100.100.2.136/32 -j ACCEPT 2>/dev/null; then
    iptables -I ts-input 1 -s 100.100.2.136/32 -j ACCEPT
  fi
  sleep 30
done

/etc/systemd/system/fix-ts-dns.service

[Unit]
Description=Keep Aliyun DNS whitelist in Tailscale chain
After=tailscaled.service

[Service]
Type=simple
ExecStart=/usr/local/bin/fix-ts-dns.sh
Restart=always

[Install]
WantedBy=multi-user.target
chmod +x /usr/local/bin/fix-ts-dns.sh
systemctl enable --now fix-ts-dns.service

脚本轮询,检查到存在 tailscale 的规则表且不存在白名单时,自动插入一条放通阿里云网段的规则。

解决方案来源:https://www.xugj520.cn/archives/aliyun-cgnat-tailscale-conflict.html

Refs

SSH 通过跳板机连接

TL;DR

有两种方式可以实现通过跳板机直接连接目标服务器 SSH.

# ProxyJump(推荐方式)OpenSSH >= 7.3
ssh -J user@jump-server.dealiaxy.com:10023 user@target.dealiaxy.com
# 在这条命令中,-J 后面指定了跳板机的地址(user@jump-server.dealiaxy.com)和端口(10023)。SSH 会先与跳板机建立连接,然后通过跳板机转发流量到目标服务器 target.dealiaxy.com。整个过程只需要一次登录操作,极大简化了访问流程。
# ProxyCommand
ssh -o "ProxyCommand ssh -W %h:%p user@jump-server.dealiaxy.com -p 10023" user@target.dealiaxy.com
# 在这个命令中,-o "ProxyCommand" 选项指定了一个自定义的命令来通过跳板机进行连接。具体地,ssh -W %h:%p 会将目标主机(%h)和端口(%p)转发给跳板机,然后通过跳板机建立与目标主机的连接。

Refs

Debian 11 + PVE LACP Mac 冲突问题调查与解决方案

By TL.S

问题背景

在Debian 11 + Proxmox VE环境中,当配置LACP(Link Aggregation Control Protocol)绑定接口时,有一个环境遇到一个令人困惑的问题:相同硬件配置的多台服务器上,所有服务器的同名bond接口都被分配了相同的MAC地址。这种情况会导致严重的网络连接问题,特别是在集群环境中。

根本原因分析

经过深入调查,这个问题的根本原因可以归纳为以下几个方面:

1. systemd/udev MAC 地址生成策略变更

systemd 242 版本开始,引入了新的MACAddressPolicy=persistent策略。该策略的目标是为虚拟网络设备(如bond、bridge、vlan等)生成持久的MAC地址,避免重启后MAC地址变化。

核心变更:systemd通过哈希算法,基于机器的machine-id和接口名称来生成MAC地址,确保在同一台机器上重启后MAC地址保持不变。

Refs: https://github.com/systemd/systemd/pull/11382

2. machine-id 相同导致的问题

关键问题:当多台服务器具有相同的machine-id时,相同的接口名称会生成完全相同的MAC地址。

machine-id 相同的几种情况:

  • 克隆安装:从同一个镜像克隆安装的系统
  • 模板部署:使用相同模板部署的虚拟机或物理机
  • 其他原因:其他原因导致 /etc/machine-id文件内容重复

3. MAC地址分配类型

通过查看系统文件可以确认MAC地址的分配方式:

root@server:~# cat /sys/class/net/bond0/addr_assign_type
3

根据Linux内核文档,addr_assign_type=3表示”set using dev_set_mac_address”,即通过dev_set_mac_address函数设置的MAC地址。

4. 虚拟设备的特殊性

问题主要影响虚拟网络设备,因为这些设备缺少必要的ID_NET_NAME_*属性,udev 无法为它们分配稳定的MAC地址。systemd 的解决方案是使用 接口名称+machine-id 的组合来生成MAC地址。

技术原理深度解析

MAC地址生成算法

systemd使用以下算法生成MAC地址:

  1. 获取/etc/machine-id的内容
  2. 结合接口名称(如bond0、vmbr0等)
  3. 通过哈希算法计算出唯一的MAC地址
  4. 确保生成的MAC地址符合本地管理地址规范

解决方案

方案一:重置machine-id(推荐)

这是最根本的解决方案,适用于所有情况:

# 停止网络服务
systemctl stop networking

# 备份原machine-id(可选)
cp /etc/machine-id /etc/machine-id.backup

# 清空machine-id
echo -n > /etc/machine-id

# 重新生成machine-id
systemd-machine-id-setup

# 验证新的machine-id
cat /etc/machine-id

# 重启系统使配置生效
reboot

注意事项

  • 重置machine-id可能影响其他依赖machine-id的服务
  • 建议在维护窗口期间执行
  • 重启后所有虚拟网络接口的MAC地址都会更新

方案二:手动指定MAC地址

如果不想更改machine-id,可以在网络配置中手动指定MAC地址:

# 编辑网络配置文件
vim /etc/network/interfaces

# 为bond接口指定唯一的MAC地址
auto bond0
iface bond0 inet manual
    bond-slaves ens1f0 ens1f1
    bond-miimon 100
    bond-mode 802.3ad
    bond-xmit-hash-policy layer3+4
    hwaddress ether 02:01:02:03:04:05  # 手动指定MAC地址

# 为bridge接口指定唯一的MAC地址
auto vmbr0
iface vmbr0 inet static
    address 10.10.4.41/24
    gateway 10.10.4.1
    bridge-ports bond0
    bridge-stp off
    bridge-fd 0
    hwaddress ether 02:01:02:03:04:06  # 手动指定MAC地址

方案三:更改MAC地址策略

修改systemd的MAC地址策略来解决MAC冲突问题。首先了解当前策略和可选项:

当前默认策略查看

# 查看当前systemd网络配置
ls -la /etc/systemd/network/
ls -la /lib/systemd/network/

# 查看当前默认策略文件(如果存在)
cat /lib/systemd/network/99-default.link 2>/dev/null || echo "默认策略文件不存在"

# 查看当前接口的MAC策略
networkctl status bond0

MAC地址策略选项说明

systemd支持以下MACAddressPolicy选项:

策略 说明 适用场景
persistent 当前默认策略,基于machine-id和接口名生成稳定MAC 需要MAC地址在重启后保持不变
random 每次启动时生成随机MAC地址 不需要MAC地址稳定性
none 不设置MAC地址,使用驱动程序默认值 物理接口或需要保持原有MAC

当前问题的根源:默认的persistent策略在相同machine-id的服务器上会生成相同的MAC地址。

实施步骤

# 1. 检查是否已有配置文件
echo "检查现有配置..."
if [ -f /etc/systemd/network/99-default.link ]; then
    echo "发现现有配置文件:"
    cat /etc/systemd/network/99-default.link
    echo ""
    echo "是否要备份现有配置?(y/n)"
    read -r response
    if [ "$response" = "y" ]; then
        cp /etc/systemd/network/99-default.link /etc/systemd/network/99-default.link.backup.$(date +%Y%m%d_%H%M%S)
        echo "已备份到: /etc/systemd/network/99-default.link.backup.$(date +%Y%m%d_%H%M%S)"
    fi
else
    echo "未发现现有配置文件,将创建新配置"
fi

# 2. 创建网络配置目录(如果不存在)
mkdir -p /etc/systemd/network

# 3. 根据需求选择策略创建配置文件

# 选项A:使用random策略(推荐用于解决冲突)
cat > /etc/systemd/network/99-default.link << EOF
# MAC地址策略配置
# 创建时间: $(date)
# 目的: 解决LACP MAC地址冲突问题

[Match]
OriginalName=*

[Link]
MACAddressPolicy=random
NamePolicy=keep kernel database onboard slot path
EOF

# 选项B:仅对虚拟接口使用random策略
cat > /etc/systemd/network/99-virtual.link << EOF
# 虚拟接口MAC地址策略配置
# 创建时间: $(date)

[Match]
Kind=bond bridge vlan macvlan veth

[Link]
MACAddressPolicy=random
EOF

# 选项C:禁用MAC地址自动分配
cat > /etc/systemd/network/99-no-mac.link << EOF
# 禁用MAC地址自动分配
# 创建时间: $(date)

[Match]
OriginalName=*

[Link]
MACAddressPolicy=none
EOF

# 4. 验证配置文件语法
echo "验证配置文件..."
systemd-analyze verify /etc/systemd/network/99-default.link

# 5. 应用新策略
echo "应用新的MAC地址策略..."
# 重新加载systemd配置
systemctl daemon-reload

# 重启网络服务(根据系统使用的网络管理器)
if systemctl is-active --quiet systemd-networkd; then
    systemctl restart systemd-networkd
    echo "已重启systemd-networkd"
elif systemctl is-active --quiet networking; then
    systemctl restart networking
    echo "已重启networking服务"
else
    echo "警告:未检测到活跃的网络服务,可能需要手动重启网络或系统"
fi

# 6. 验证策略是否生效
echo "等待网络接口重新初始化..."
sleep 5

echo "验证新的MAC地址策略:"
networkctl status | grep -E "(bond|vmbr|bridge)"

策略选择建议

推荐策略组合

  1. 对于生产环境

    # 仅对虚拟接口使用random策略,物理接口保持默认
    [Match]
    Kind=bond bridge vlan
    
    [Link]
    MACAddressPolicy=random
  2. 对于测试环境

    # 所有接口使用random策略
    [Match]
    OriginalName=*
    
    [Link]
    MACAddressPolicy=random
  3. 对于特定接口

    # 只对特定名称的接口应用
    [Match]
    OriginalName=bond* vmbr*
    
    [Link]
    MACAddressPolicy=random

回滚方案

如果新策略导致问题,可以快速回滚:

# 删除自定义策略文件
rm -f /etc/systemd/network/99-default.link

# 或者恢复备份
if [ -f /etc/systemd/network/99-default.link.backup.* ]; then
    cp /etc/systemd/network/99-default.link.backup.* /etc/systemd/network/99-default.link
fi

# 重启网络服务
systemctl daemon-reload
systemctl restart systemd-networkd

注意事项

  • 影响范围:此方案会影响系统中所有匹配的网络接口
  • 重启要求:配置更改后,需要重启网络服务或重启系统
  • 兼容性:确保你的系统使用systemd-networkd而不是NetworkManager
  • 监控:更改后应监控网络连接是否正常

方案四:运行时动态修改

如果需要立即解决问题而不重启:

# 生成随机MAC地址(注意要符合本地管理地址规范)
NEW_MAC=$(printf '02:00:00:%02x:%02x:%02x\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))

# 停止接口
ip link set dev bond0 down

# 设置新的MAC地址
ip link set dev bond0 address $NEW_MAC

# 启动接口
ip link set dev bond0 up

# 验证更改
ip link show bond0

预防措施

1. 标准化部署流程

在部署新系统时,确保:

# 在系统部署脚本中加入
if [ -f /etc/machine-id ]; then
    echo "重置machine-id..."
    echo -n > /etc/machine-id
    systemd-machine-id-setup
fi

2. 监控和检查

定期检查集群中的MAC地址冲突:

#!/bin/bash
# mac_check.sh - 检查MAC地址冲突

echo "检查集群MAC地址冲突..."
for host in server1 server2 server3; do
    echo "=== $host ==="
    ssh $host "ip link show | grep -E 'bond|vmbr' | grep 'link/ether'"
done

3. 文档化和记录

建立标准的网络配置文档,记录:

  • 每台服务器的machine-id
  • 手动分配的MAC地址范围
  • 网络拓扑和接口映射

影响范围和版本信息

受影响版本

  • Debian 10/11 + systemd >= 242
  • Proxmox VE 6.x/7.x/8.x
  • 其他基于systemd的Linux发行版

特别注意

  • Intel网卡比Broadcom网卡更容易出现此问题
  • 虚拟化环境中的问题更加常见
  • 集群环境影响更严重

总结

Debian 11 + PVE LACP Mac冲突问题的根本原因是systemd的MAC地址生成策略与machine-id机制的相互作用。当多台服务器具有相同的machine-id时,会为相同名称的虚拟网络接口生成相同的MAC地址,导致网络冲突。

References

Linux 自签名 CA 证书安装方法

在 Linux 中运行 docker, containerd, helm 等应用时需要信任自签署证书保护的内部仓库服务,此时需要注入自签名 CA 证书,以 Ubunut 为例。在 Ubuntu 系统中,CA 证书信任主要存储在以下目录:

主要目录:

  • /etc/ssl/certs/ – 系统级 CA 证书目录
  • /usr/share/ca-certificates/ – 预安装的 CA 证书包

关键文件:

  • /etc/ssl/certs/ca-certificates.crt – 合并的 CA 证书文件
  • /etc/ca-certificates.conf – CA 证书配置文件

管理方式:

  • 添加新的 CA 证书:将 .crt 文件放入 /usr/local/share/ca-certificates/ 目录
  • 更新证书:运行 sudo update-ca-certificates 命令

具体操作示例:

# 添加自定义 CA 证书
sudo cp your-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

# 查看当前信任的 CA 证书
ls /etc/ssl/certs/

系统会自动将 /usr/local/share/ca-certificates//usr/share/ca-certificates/ 中的证书合并到 /etc/ssl/certs/ca-certificates.crt 文件中,这个文件被大多数应用程序用作默认的 CA 证书束。