1. systemd 自定义启动项

/etc/systemd/system/usr/lib/systemd/system 的区别和用途,为什么优先使用 /etc/systemd/system

  • systemd 读取单元文件时,会按照优先级搜索:

    1. /etc/systemd/system

    2. /run/systemd/system

    3. /usr/lib/systemd/system

  • 这样可以让管理员通过在 /etc/systemd/system 放置自定义单元文件或者覆盖已有单元,实现定制化而不影响系统默认文件。

  • 举例:如果你想修改一个默认服务的启动参数,建议复制对应文件到 /etc/systemd/system,然后修改;系统升级时不会覆盖你的改动。

k8s-modules.service

cat > /etc/systemd/system/k8s-modules.service <<EOF
# 描述:开机自动加载 Kubernetes 所需内核模块,并自动启动 sysctl-k8s 服务
[Unit]
Description=Load Kubernetes required kernel modules
# 保证在网络初始化之前加载内核模块
Before=network-pre.target
# 希望 network-pre.target 启动,也希望自动启动 sysctl-k8s.service
Wants=network-pre.target sysctl-k8s.service
# 关闭默认依赖,手动控制依赖关系顺序
DefaultDependencies=no

[Service]
# 一次性任务,执行完即退出
Type=oneshot
# 加载k8s需要用到的内核模块
ExecStart=/etc/sysconfig/modules/ipvs.modules
ExecStart=/etc/sysconfig/modules/br_netfilter.modules
# 执行完成后服务状态保持激活
RemainAfterExit=yes

[Install]
# 系统进入多用户运行级别时自动启动
WantedBy=multi-user.target
EOF

sysctl-k8s.service

cat > /etc/systemd/system/sysctl-k8s.service <<EOF
[Unit]
Description=应用 Kubernetes 所需的 sysctl 内核参数(适配麒麟系统)
# 确保该服务在网络初始化前执行,以便内核参数(如 ip_forward)及时生效
Before=network-pre.target
Wants=network-pre.target

# 确保内核模块先加载,避免 sysctl 参数路径不存在
After=k8s-modules.service
Requires=k8s-modules.service

# 禁用默认依赖,防止 systemd 自动附加不必要的依赖链,确保尽早启动
DefaultDependencies=no

# 关于为什么不用 sysctl --system:
# sysctl --system 会加载多个路径的 *.conf 配置文件
# 但其依赖 systemd-sysctl.service 来实现自动执行,而麒麟系统中该服务可能未启用或执行顺序靠后
# 导致某些关键参数(如 ip_forward)在 kubelet 或网络插件启动前未生效
# 所以使用 systemd 单独编排此 service 是更稳定可靠的做法

[Service]
Type=oneshot
# 加载我们自定义的 Kubernetes 所需 sysctl 配置
ExecStart=/usr/sbin/sysctl -p /etc/sysctl.d/k8s.conf
RemainAfterExit=true

[Install]
# 设置为在多用户模式下自动启动,确保开机时加载
WantedBy=multi-user.target
EOF

2. LVM逻辑卷管理器

[root@hybxvdka01 appuser]# lsblk
NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda              253:0    0  100G  0 disk 
├─vda1           253:1    0  500M  0 part /boot/efi
├─vda2           253:2    0    1G  0 part /boot
└─vda3           253:3    0   96G  0 part 
  ├─rootvg-root  252:0    0   30G  0 lvm  /
  ├─rootvg-swap  252:4    0   16G  0 lvm  
  ├─rootvg-kdump 252:5    0   10G  0 lvm  /kdump
  ├─rootvg-tmp   252:6    0   10G  0 lvm  /tmp
  └─rootvg-var   252:7    0   10G  0 lvm  /var
vdb              253:16   0  200G  0 disk 
├─vg_app-lv_app  252:1    0   50G  0 lvm  /app
├─vg_app-lv_data 252:2    0   10G  0 lvm  /data
└─vg_app-lv_log  252:3    0    5G  0 lvm  /log

步骤 1:确认当前空间和 VG 剩余空间
# 查看当前逻辑卷(LV)信息
[root@hybxvdka01 appuser]# lvdisplay /dev/vg_app/lv_data
  --- Logical volume ---
  LV Path                /dev/vg_app/lv_data
  LV Name                lv_data
  VG Name                vg_app
  LV UUID                bMYIde-dZMr-9kww-vFVi-xYQC-0QRf-PsplA1
  LV Write Access        read/write
  LV Creation host, time hybxvdka01, 2025-07-18 19:10:37 +0800
  LV Status              available
  # open                 1
  LV Size                10.00 GiB
  Current LE             2560
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           252:2


# 查看卷组(VG)剩余空间
[root@hybxvdka01 appuser]# vgdisplay vg_app
  --- Volume group ---
  VG Name               vg_app
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               <200.00 GiB
  PE Size               4.00 MiB
  Total PE              51199
  Alloc PE / Size       16640 / 65.00 GiB
  Free  PE / Size       34559 / <135.00 GiB
  VG UUID               u3OXCb-NHy7-SHQm-ggpU-f59e-7ia5-l38bGK


# 方法1:直接扩展到 50G(推荐)
lvextend -L 50G /dev/vg_app/lv_data
# 或方法2:增加 40G(等效操作)
lvextend -L +40G /dev/vg_app/lv_data

# 调整文件系统
如果是 ext4: resize2fs /dev/vg_app/lv_data
如果是 xfs: xfs_growfs /data 

[root@hybxvdka01 appuser]# xfs_growfs /data
meta-data=/dev/mapper/vg_app-lv_data isize=512    agcount=4, agsize=655360 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=2621440, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2621440 to 13107200
[root@hybxvdka01 appuser]# df -h /data/
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_app-lv_data   50G  392M   50G   1% /data

空间转移

rootvg-var 空间告急了,rootvg-swap基本是用不上了,直接删了他将空间给rootvg-var使用。

[appuser@hybxvdka01 ~]$ lsblk
NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda              253:0    0  100G  0 disk 
├─vda1           253:1    0  500M  0 part /boot/efi
├─vda2           253:2    0    1G  0 part /boot
└─vda3           253:3    0   96G  0 part 
  ├─rootvg-root  252:0    0   30G  0 lvm  /
  ├─rootvg-swap  252:4    0   16G  0 lvm  
  ├─rootvg-kdump 252:5    0   10G  0 lvm  /kdump
  ├─rootvg-tmp   252:6    0   10G  0 lvm  /tmp
  └─rootvg-var   252:7    0   10G  0 lvm  /var
vdb              253:16   0  200G  0 disk 
├─vg_app-lv_app  252:1    0   50G  0 lvm  /app
├─vg_app-lv_data 252:2    0   50G  0 lvm  /data
└─vg_app-lv_log  252:3    0    5G  0 lvm  /log


# 1. 删除 swap 的逻辑卷
sudo lvremove -y /dev/rootvg/swap

# 2. 扩容 /var(加上 swap 释放的 16G)
sudo lvextend -L +16G /dev/rootvg/var

# 3. 在线扩容文件系统(假设 /var 是 XFS 文件系统)
sudo xfs_growfs /var

3. glibc和musl等标准库差异

今在基于 AlmaLinux 9.4 (ARM aarch64 架构) 的容器里,安装了 Alpine Linux 专用的 OpenJDK 21 (aarch64-alpine-linux-hotspot 版本) 后,尝试运行 java 命令时出现 /opt/java/bin/java: No such file or directory 错误。
这个错误虽然提示“文件不存在”,但实际上文件是存在的,问题的根源在于该 Java 二进制文件依赖的运行时环境不兼容。

原因分析

  • 该 JDK 包是专门为 Alpine Linux 打包的,Alpine Linux 使用的是 musl libc

  • 而 AlmaLinux 是基于 RHEL,默认使用的是 glibc

  • 尽管架构(aarch64)相同,但两个系统的 C 标准库(libc)完全不同且不兼容。

  • 在 glibc 系统上运行编译依赖 musl libc 的二进制文件,会出现类似“文件不存在”的错误,因为动态链接器找不到 musl libc 的相关库和符号。

  • 这导致操作系统在尝试加载可执行文件时失败,表现为“文件不存在”错误。


结论

不能在基于 glibc 的 AlmaLinux 系统上直接使用 Alpine(musl)版本的 OpenJDK。

正确做法是:

  • 使用为 glibc 系统编译的 OpenJDK 版本(例如官方 Linux aarch64 版本)。

  • 或者在 Alpine 系统环境中使用 Alpine 版本 JDK。

[root@localhost ~]# ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

4. CPU架构与指令集

为什么 ARM 会分这么多版本?

它们的区别在于 指令集版本(架构等级)兼容性,ARM 架构有不同的指令集版本,类似于 Intel 也分 x86、x86_64。主要几种区别:

文件名里的架构

常见 CPU 型号

特点

兼容性

arm64(aarch64)

树莓派 4B 8GB、AWS Graviton、Ampere、RK3588 等

64 位 ARM 指令集(ARMv8 及以上)

只能在 64 位 ARM 上运行

armv7

树莓派 2/3(32 位 OS)、老的 Android 盒子

32 位 ARM 指令集(ARMv7-A)

不能跑 64 位程序

armv6

树莓派 1/Zero、非常老的嵌入式设备

较老的 32 位 ARM 指令集(ARMv6)

兼容性最好,性能最低

amd64(x86_64)

Intel/AMD 服务器、台式机

64 位 x86 指令集

不能在 ARM 上运行

为什么不直接一个 arm64 就够?

  • arm64 性能最好,但只能运行在 64 位 ARM CPU 上

  • armv7 / armv6 是为了兼容老设备(比如树莓派 1、树莓派 2、老 NAS)

  • 如果是服务器,99% 可能是 arm64,因为现在云厂商的 ARM 实例几乎都是 ARMv8 架构

你可以直接在服务器运行uname -m,常见输出:

  • aarch64 → ARM 64 位(用 arm64 包)

  • armv7l → ARMv7 32 位(用 armv7 包)

  • armv6l → ARMv6 32 位(用 armv6 包)

  • x86_64 → AMD64(用 amd64 包)

1panel-v1.10.29-lts-offline-linux-amd64.tar.gz   130 MB   Apr 11
1panel-v1.10.29-lts-offline-linux-arm64.tar.gz   120 MB   Apr 11
1panel-v1.10.29-lts-offline-linux-armv6.tar.gz   120 MB   Apr 11
1panel-v1.10.29-lts-offline-linux-armv7.tar.gz   120 MB   Apr 11