612 lines
15 KiB
Bash
612 lines
15 KiB
Bash
#!/bin/bash
|
||
|
||
# ===================================================
|
||
# 脚本功能:
|
||
# 1. 配置 systemd-networkd 网络桥接与 VLAN
|
||
# 2. 配置 k3s agent 节点并启动服务
|
||
# 3. 可通过配置文件 bushu.conf 管理所有参数
|
||
# ===================================================
|
||
set -euo pipefail
|
||
|
||
# -----------------------
|
||
# 检查 root 权限
|
||
# -----------------------
|
||
if [[ $EUID -ne 0 ]]; then
|
||
echo "请使用 root 用户运行此脚本"
|
||
exit 1
|
||
fi
|
||
|
||
# -----------------------
|
||
# 引入配置文件
|
||
# -----------------------
|
||
CONFIG_FILE="./bushu.conf"
|
||
if [[ -f "$CONFIG_FILE" ]]; then
|
||
source "$CONFIG_FILE"
|
||
else
|
||
echo "配置文件 $CONFIG_FILE 不存在,请先创建!"
|
||
exit 1
|
||
fi
|
||
|
||
# -----------------------
|
||
# 网络配置部分
|
||
# -----------------------
|
||
echo "=== 开始 cloud 网桥配置 ==="
|
||
|
||
# 备份现有网络配置
|
||
mkdir -p /etc/systemd/network/backup
|
||
cp /etc/systemd/network/*.network /etc/systemd/network/backup/ 2>/dev/null || true
|
||
cp /etc/systemd/network/*.netdev /etc/systemd/network/backup/ 2>/dev/null || true
|
||
echo "网络配置备份已完成"
|
||
|
||
|
||
# 创建 cloud bridge
|
||
cat > /etc/systemd/network/00-cloud.netdev << EOF
|
||
[NetDev]
|
||
Name=cloud
|
||
Kind=bridge
|
||
MACAddress=$CLOUD_MAC
|
||
|
||
[Bridge]
|
||
VLANFiltering=yes
|
||
EOF
|
||
|
||
# 配置 cloud 网络
|
||
cat > /etc/systemd/network/00-cloud.network << EOF
|
||
[Match]
|
||
Name=cloud
|
||
|
||
[Network]
|
||
Address=$CLOUD_IP
|
||
Address=$CLOUD_SECOND_IP
|
||
Gateway=$CLOUD_GATEWAY
|
||
DNS=$CLOUD_DNS
|
||
ConfigureWithoutCarrier=yes
|
||
|
||
[Link]
|
||
RequiredForOnline=no-carrier
|
||
EOF
|
||
|
||
|
||
cat > /etc/systemd/network/00-$CLOUD_IFACE.network << EOF
|
||
[Match]
|
||
Name=$CLOUD_IFACE
|
||
|
||
[Network]
|
||
Bridge=cloud
|
||
DHCP=no
|
||
# VLAN=cloud-monitor
|
||
|
||
[BridgeVLAN]
|
||
VLAN=1-4094
|
||
|
||
[BridgeVLAN]
|
||
VLAN=1
|
||
PVID=1
|
||
EgressUntagged=1
|
||
EOF
|
||
|
||
|
||
echo "cloud 网桥配置已完成"
|
||
|
||
# -----------------------
|
||
echo "=== 开始 yewu 网桥配置 ==="
|
||
|
||
# 创建 yewu bridge
|
||
cat > /etc/systemd/network/00-yewu.netdev << EOF
|
||
[NetDev]
|
||
Name=yewu
|
||
Kind=bridge
|
||
MACAddress=$YEWU_MAC
|
||
|
||
[Bridge]
|
||
VLANFiltering=yes
|
||
EOF
|
||
|
||
# 配置 yewu 网络
|
||
cat > /etc/systemd/network/00-yewu.network << EOF
|
||
[Match]
|
||
Name=yewu
|
||
|
||
[Network]
|
||
Address=$YEWU_IP
|
||
Gateway=$YEWU_GATEWAY
|
||
DNS=$YEWU_DNS
|
||
ConfigureWithoutCarrier=yes
|
||
|
||
[Link]
|
||
RequiredForOnline=no-carrier
|
||
EOF
|
||
|
||
# 用户网卡接入 yewu bridge
|
||
cat > /etc/systemd/network/00-$YEWU_IFACE.network << EOF
|
||
[Match]
|
||
Name=$YEWU_IFACE
|
||
|
||
[Network]
|
||
Bridge=yewu
|
||
DHCP=no
|
||
|
||
[BridgeVLAN]
|
||
VLAN=1-4094
|
||
|
||
[BridgeVLAN]
|
||
VLAN=1
|
||
PVID=1
|
||
EgressUntagged=1
|
||
EOF
|
||
|
||
echo "yewu 网桥配置已完成"
|
||
|
||
# 使用 networkctl reload 应用配置
|
||
echo "正在重新加载网络配置..."
|
||
networkctl reload
|
||
echo "网络配置已生效"
|
||
|
||
|
||
# ===================================================
|
||
# 新增部分:monitor VLAN 子接口配置
|
||
# ===================================================
|
||
echo "=== 开始配置 monitor VLAN 子接口 ==="
|
||
|
||
: "${MONITOR_VLAN_ID:?请在 bushu.conf 中配置 MONITOR_VLAN_ID}"
|
||
: "${MONITOR_PHY_IFACE:?请在 bushu.conf 中配置 MONITOR_PHY_IFACE}"
|
||
: "${MONITOR_ALIAS:=lsa}"
|
||
|
||
MONITOR_VLAN_IFACE="${MONITOR_PHY_IFACE}.${MONITOR_VLAN_ID}"
|
||
|
||
echo "monitor 物理网卡: ${MONITOR_PHY_IFACE}"
|
||
echo "monitor VLAN ID: ${MONITOR_VLAN_ID}"
|
||
echo "monitor VLAN 子接口: ${MONITOR_VLAN_IFACE}"
|
||
echo "monitor VLAN alias: ${MONITOR_ALIAS}"
|
||
|
||
modprobe 8021q || true
|
||
|
||
if ip link show "${MONITOR_VLAN_IFACE}" >/dev/null 2>&1; then
|
||
echo "VLAN 子接口 ${MONITOR_VLAN_IFACE} 已存在,跳过创建"
|
||
else
|
||
echo "正在创建 VLAN 子接口 ${MONITOR_VLAN_IFACE} ..."
|
||
ip link add link "${MONITOR_PHY_IFACE}" name "${MONITOR_VLAN_IFACE}" type vlan id "${MONITOR_VLAN_ID}"
|
||
fi
|
||
|
||
ip link set dev "${MONITOR_VLAN_IFACE}" alias "${MONITOR_ALIAS}"
|
||
ip link set dev "${MONITOR_VLAN_IFACE}" up
|
||
|
||
echo "monitor VLAN 子接口 ${MONITOR_VLAN_IFACE} 当前已生效"
|
||
|
||
# -----------------------
|
||
# 新增部分:写入 rc.local,保证重启后自动创建
|
||
# -----------------------
|
||
echo "=== 写入 rc.local,配置 monitor VLAN 开机自动创建 ==="
|
||
|
||
if [[ ! -f /etc/rc.local ]]; then
|
||
cat > /etc/rc.local << 'EOF'
|
||
#!/bin/bash
|
||
|
||
exit 0
|
||
EOF
|
||
chmod +x /etc/rc.local
|
||
fi
|
||
|
||
sed -i '/# BEGIN MONITOR VLAN/,/# END MONITOR VLAN/d' /etc/rc.local
|
||
|
||
sed -i "/^exit 0/i\\
|
||
# BEGIN MONITOR VLAN\\
|
||
modprobe 8021q || true\\
|
||
while ! ip link show ${MONITOR_PHY_IFACE} >/dev/null 2>&1; do\\
|
||
sleep 1\\
|
||
done\\
|
||
ip link show ${MONITOR_VLAN_IFACE} >/dev/null 2>&1 || ip link add link ${MONITOR_PHY_IFACE} name ${MONITOR_VLAN_IFACE} type vlan id ${MONITOR_VLAN_ID}\\
|
||
ip link set dev ${MONITOR_VLAN_IFACE} alias ${MONITOR_ALIAS}\\
|
||
ip link set dev ${MONITOR_VLAN_IFACE} up\\
|
||
# END MONITOR VLAN\\
|
||
" /etc/rc.local
|
||
|
||
chmod +x /etc/rc.local
|
||
|
||
systemctl enable rc-local 2>/dev/null || true
|
||
systemctl enable rc-local.service 2>/dev/null || true
|
||
|
||
echo "rc.local 已写入 monitor VLAN 配置"
|
||
|
||
|
||
|
||
# -----------------------
|
||
# k3s 配置部分
|
||
# -----------------------
|
||
echo "=== k3s 安装配置 ==="
|
||
echo "=== 下载 K3s 二进制到 /usr/bin/ ==="
|
||
curl -L -o /usr/bin/k3s "https://file.piicloud.com/f/acfd6bc97c7e42de8647/?dl=1"
|
||
chmod +x /usr/bin/k3s
|
||
ls -lh /usr/bin/k3s
|
||
|
||
|
||
|
||
echo "=== 检查/创建 K3s agent 镜像目录 ==="
|
||
if [ ! -d "/var/lib/rancher/agent/images" ]; then
|
||
mkdir -p /var/lib/rancher/agent/images
|
||
echo "目录已创建"
|
||
else
|
||
echo "目录已存在,跳过创建"
|
||
fi
|
||
|
||
# 下载镜像
|
||
[ -f "/var/lib/rancher/agent/images/base.tar" ] || \
|
||
curl -L -o /var/lib/rancher/agent/images/base.tar "https://file.piicloud.com/f/40e4c1cc37564dd8900d/?dl=1"
|
||
[ -f "/var/lib/rancher/agent/images/expend.tar" ] || \
|
||
curl -L -o /var/lib/rancher/agent/images/expend.tar "https://file.piicloud.com/f/c6cf4a7811d344ca9bf6/?dl=1"
|
||
|
||
chown root:root /var/lib/rancher/agent/images/*.tar
|
||
chmod 644 /var/lib/rancher/agent/images/*.tar
|
||
ls -lh /var/lib/rancher/agent/images/
|
||
|
||
# 创建 systemd 服务文件
|
||
cat > /etc/systemd/system/k3s.service << EOF
|
||
[Unit]
|
||
Description=Lightweight Kubernetes
|
||
Documentation=https://k3s.io
|
||
Wants=network-online.target
|
||
After=network-online.target
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
|
||
[Service]
|
||
Type=notify
|
||
EnvironmentFile=-/etc/default/%N
|
||
EnvironmentFile=-/etc/sysconfig/%N
|
||
EnvironmentFile=-/etc/systemd/system/k3s.service.env
|
||
KillMode=process
|
||
Delegate=yes
|
||
User=root
|
||
LimitNOFILE=1048576
|
||
LimitNPROC=infinity
|
||
LimitCORE=infinity
|
||
TasksMax=infinity
|
||
TimeoutStartSec=0
|
||
Restart=always
|
||
RestartSec=5s
|
||
ExecStartPre=-/sbin/modprobe br_netfilter
|
||
ExecStartPre=-/sbin/modprobe overlay
|
||
ExecStart=/usr/bin/k3s server
|
||
EOF
|
||
|
||
|
||
# 创建 override 配置
|
||
mkdir -p /etc/systemd/system/k3s.service.d
|
||
cat > /etc/systemd/system/k3s.service.d/override.conf << EOF
|
||
[Service]
|
||
ExecStart=
|
||
ExecStart=/usr/bin/k3s agent \
|
||
--server https://$MASTER_IP:6443 \
|
||
--token $K3S_TOKEN \
|
||
--node-name $NODE_NAME \
|
||
--node-ip $NODE_IP \
|
||
--node-external-ip $NODE_EXT_IP \
|
||
--kubelet-arg max-pods=120
|
||
EOF
|
||
|
||
# 创建 registries.yaml
|
||
mkdir -p /etc/rancher/k3s/
|
||
cat > /etc/rancher/k3s/registries.yaml << EOF
|
||
configs:
|
||
harbor.tdology.com:
|
||
auth:
|
||
password: Y_TSq6qDJBZC}538
|
||
username: admin
|
||
mirrors:
|
||
docker.io:
|
||
endpoint:
|
||
- http://localhost:30500
|
||
- https://harbor.tdology.com
|
||
EOF
|
||
|
||
# -----------------------
|
||
# NVMe 分区与格式化
|
||
# -----------------------
|
||
|
||
# 检查磁盘是否存在
|
||
if [[ ! -b /dev/nvme0n1 ]]; then
|
||
echo "错误:/dev/nvme0n1 不存在"
|
||
exit 1
|
||
fi
|
||
|
||
# 如果分区不存在,则创建
|
||
if [[ ! -b /dev/nvme0n1p1 ]]; then
|
||
echo "/dev/nvme0n1p1 不存在,开始创建分区..."
|
||
|
||
if lsblk -nr /dev/nvme0n1 | awk '{print $6}' | grep -q '^part$'; then
|
||
echo "检测到已有分区,但没有 nvme0n1p1,请手动检查"
|
||
exit 1
|
||
fi
|
||
|
||
parted -s /dev/nvme0n1 mklabel gpt
|
||
parted -s /dev/nvme0n1 mkpart primary 0% 100%
|
||
|
||
partprobe /dev/nvme0n1
|
||
sleep 2
|
||
|
||
if [[ ! -b /dev/nvme0n1p1 ]]; then
|
||
echo "错误:分区创建失败"
|
||
exit 1
|
||
fi
|
||
|
||
echo "分区创建成功:/dev/nvme0n1p1"
|
||
else
|
||
echo "/dev/nvme0n1p1 已存在,跳过创建分区"
|
||
fi
|
||
|
||
# 如果没有文件系统,则格式化
|
||
if ! blkid /dev/nvme0n1p1 >/dev/null 2>&1; then
|
||
echo "/dev/nvme0n1p1 没有文件系统,开始格式化为 ext4..."
|
||
mkfs.ext4 -F /dev/nvme0n1p1
|
||
else
|
||
echo "/dev/nvme0n1p1 已有文件系统,跳过格式化"
|
||
fi
|
||
|
||
# -----------------------
|
||
# NVMe 挂载与绑定挂载
|
||
# -----------------------
|
||
|
||
# 确保主挂载点存在
|
||
mkdir -p /mnt/nvme
|
||
|
||
# 挂载 /mnt/nvme
|
||
if ! mountpoint -q /mnt/nvme; then
|
||
echo "挂载 /dev/nvme0n1p1 到 /mnt/nvme ..."
|
||
mount /dev/nvme0n1p1 /mnt/nvme
|
||
else
|
||
echo "/mnt/nvme 已经挂载,跳过挂载"
|
||
fi
|
||
|
||
# ✅ 确保源目录存在(关键修复点)
|
||
mkdir -p /mnt/nvme/rancher
|
||
mkdir -p /mnt/nvme/longhorn
|
||
|
||
# 确保绑定挂载目标目录存在
|
||
mkdir -p /var/lib/rancher
|
||
mkdir -p /var/lib/longhorn
|
||
|
||
# 挂载 /var/lib/rancher
|
||
if ! mountpoint -q /var/lib/rancher; then
|
||
echo "绑定挂载 /mnt/nvme/rancher 到 /var/lib/rancher ..."
|
||
mount --bind /mnt/nvme/rancher /var/lib/rancher
|
||
else
|
||
echo "/var/lib/rancher 已经挂载,跳过绑定挂载"
|
||
fi
|
||
|
||
# 挂载 /var/lib/longhorn
|
||
if ! mountpoint -q /var/lib/longhorn; then
|
||
echo "绑定挂载 /mnt/nvme/longhorn 到 /var/lib/longhorn ..."
|
||
mount --bind /mnt/nvme/longhorn /var/lib/longhorn
|
||
else
|
||
echo "/var/lib/longhorn 已经挂载,跳过绑定挂载"
|
||
fi
|
||
|
||
# -----------------------
|
||
# 更新 /etc/fstab
|
||
# -----------------------
|
||
|
||
NVME_UUID=$(blkid -s UUID -o value /dev/nvme0n1p1)
|
||
NVME_FSTYPE=$(blkid -s TYPE -o value /dev/nvme0n1p1)
|
||
|
||
if [[ -z "$NVME_UUID" || -z "$NVME_FSTYPE" ]]; then
|
||
echo "错误:无法获取 UUID 或文件系统类型,停止写入 fstab"
|
||
exit 1
|
||
fi
|
||
|
||
# 主挂载(安全)
|
||
grep -qE "[[:space:]]/mnt/nvme[[:space:]]" /etc/fstab || \
|
||
echo "UUID=${NVME_UUID} /mnt/nvme ${NVME_FSTYPE} defaults,nofail,x-systemd.device-timeout=5 0 2" >> /etc/fstab
|
||
|
||
# bind mount(安全)
|
||
grep -qE "[[:space:]]/var/lib/rancher[[:space:]]" /etc/fstab || \
|
||
echo "/mnt/nvme/rancher /var/lib/rancher none bind,nofail,x-systemd.requires-mounts-for=/mnt/nvme 0 0" >> /etc/fstab
|
||
|
||
grep -qE "[[:space:]]/var/lib/longhorn[[:space:]]" /etc/fstab || \
|
||
echo "/mnt/nvme/longhorn /var/lib/longhorn none bind,nofail,x-systemd.requires-mounts-for=/mnt/nvme 0 0" >> /etc/fstab
|
||
|
||
# -----------------------
|
||
# 验证
|
||
# -----------------------
|
||
|
||
echo "测试 fstab..."
|
||
mount -a
|
||
|
||
echo "显示挂载状态"
|
||
findmnt /mnt/nvme
|
||
findmnt /var/lib/rancher
|
||
findmnt /var/lib/longhorn
|
||
|
||
# -----------------------
|
||
# 时间同步
|
||
# -----------------------
|
||
echo "=== 时间同步配置 ==="
|
||
|
||
: "${ENABLE_CHRONY:=true}"
|
||
: "${ENABLE_GPTP:=false}"
|
||
|
||
if [[ "${ENABLE_CHRONY}" == "true" && "${ENABLE_GPTP}" == "true" ]]; then
|
||
echo "错误:ENABLE_CHRONY 和 ENABLE_GPTP 不能同时为 true"
|
||
exit 1
|
||
fi
|
||
|
||
echo "=== 从 RTC 恢复系统时间 ==="
|
||
hwclock -s 2>/dev/null || hwclock --hctosys 2>/dev/null || true
|
||
date
|
||
|
||
if [[ "${ENABLE_CHRONY}" == "true" || "${ENABLE_GPTP}" == "true" ]]; then
|
||
echo "安装时间同步相关组件..."
|
||
apt update
|
||
apt install -y chrony linuxptp
|
||
fi
|
||
|
||
if [[ "${ENABLE_CHRONY}" == "true" ]]; then
|
||
echo "=== 启用 chrony 时间同步 ==="
|
||
|
||
systemctl disable --now gptp.service 2>/dev/null || true
|
||
systemctl disable --now phc2sys.service 2>/dev/null || true
|
||
pkill ptp4l 2>/dev/null || true
|
||
pkill phc2sys 2>/dev/null || true
|
||
|
||
cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak 2>/dev/null || true
|
||
|
||
cat > /etc/chrony/chrony.conf << EOF
|
||
# 由 bushu.sh 自动生成
|
||
EOF
|
||
|
||
for server in "${CHRONY_SERVERS[@]}"; do
|
||
echo "server ${server} iburst" >> /etc/chrony/chrony.conf
|
||
done
|
||
|
||
cat >> /etc/chrony/chrony.conf << EOF
|
||
|
||
driftfile /var/lib/chrony/chrony.drift
|
||
makestep 1.0 -1
|
||
rtcsync
|
||
logdir /var/log/chrony
|
||
EOF
|
||
|
||
systemctl enable --now chrony
|
||
chronyc -a makestep || true
|
||
sleep 3
|
||
|
||
chronyc sources -v || true
|
||
chronyc tracking || true
|
||
|
||
elif [[ "${ENABLE_GPTP}" == "true" ]]; then
|
||
echo "=== 启用 gPTP 时间同步 ==="
|
||
|
||
systemctl disable --now chrony 2>/dev/null || true
|
||
|
||
: "${GPTP_IFACE:?请在 bushu.conf 中配置 GPTP_IFACE}"
|
||
|
||
mkdir -p /usr/local/bin
|
||
mkdir -p /etc/linuxptp
|
||
|
||
cat > /etc/linuxptp/gptp.cfg << EOF
|
||
# 由 bushu.sh 自动生成
|
||
# gPTP / IEEE 802.1AS 配置
|
||
|
||
[global]
|
||
gmCapable 0
|
||
priority1 248
|
||
priority2 248
|
||
logAnnounceInterval 0
|
||
logSyncInterval -3
|
||
syncReceiptTimeout 3
|
||
neighborPropDelayThresh 800
|
||
min_neighbor_prop_delay -20000000
|
||
assume_two_step 1
|
||
path_trace_enabled 1
|
||
follow_up_info 1
|
||
transportSpecific 0x1
|
||
ptp_dst_mac 01:80:C2:00:00:0E
|
||
network_transport L2
|
||
delay_mechanism P2P
|
||
time_stamping hardware
|
||
EOF
|
||
|
||
cat > /usr/local/bin/start-gptp.sh << 'EOF'
|
||
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
GPTP_IFACE="${1:?Usage: start-gptp.sh <interface>}"
|
||
|
||
while ! ip link show "${GPTP_IFACE}" >/dev/null 2>&1; do
|
||
echo "等待网卡 ${GPTP_IFACE} 出现..."
|
||
sleep 1
|
||
done
|
||
|
||
ip link set dev "${GPTP_IFACE}" up
|
||
|
||
if ethtool -T "${GPTP_IFACE}" 2>/dev/null | grep -q "hardware-transmit"; then
|
||
TS_MODE="hardware"
|
||
else
|
||
echo "警告:${GPTP_IFACE} 不支持硬件时间戳,切换为 software timestamp"
|
||
TS_MODE="software"
|
||
sed -i 's/^time_stamping.*/time_stamping software/' /etc/linuxptp/gptp.cfg
|
||
fi
|
||
|
||
echo "gPTP timestamp mode: ${TS_MODE}"
|
||
|
||
exec /usr/sbin/ptp4l \
|
||
-i "${GPTP_IFACE}" \
|
||
-f /etc/linuxptp/gptp.cfg \
|
||
-m
|
||
EOF
|
||
|
||
chmod +x /usr/local/bin/start-gptp.sh
|
||
|
||
cat > /etc/systemd/system/gptp.service << EOF
|
||
[Unit]
|
||
Description=gPTP IEEE 802.1AS Service
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=/usr/local/bin/start-gptp.sh ${GPTP_IFACE}
|
||
Restart=always
|
||
RestartSec=5
|
||
User=root
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
cat > /etc/systemd/system/phc2sys.service << EOF
|
||
[Unit]
|
||
Description=Synchronize system clock from gPTP PHC
|
||
After=gptp.service
|
||
Requires=gptp.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStartPre=/bin/sleep 10
|
||
ExecStart=/usr/sbin/phc2sys -s ${GPTP_IFACE} -c CLOCK_REALTIME -O 0 -m
|
||
Restart=always
|
||
RestartSec=5
|
||
User=root
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable --now gptp.service
|
||
systemctl enable --now phc2sys.service
|
||
|
||
else
|
||
echo "=== 未启用时间同步 ==="
|
||
systemctl disable --now chrony 2>/dev/null || true
|
||
systemctl disable --now gptp.service 2>/dev/null || true
|
||
systemctl disable --now phc2sys.service 2>/dev/null || true
|
||
fi
|
||
|
||
echo "=== 检查系统时间 ==="
|
||
date
|
||
timedatectl || true
|
||
|
||
YEAR=$(date +%Y)
|
||
if (( YEAR < 2024 )); then
|
||
echo "错误:系统时间异常,当前时间:$(date)"
|
||
echo "拒绝继续执行,避免 apt/curl/k3s TLS 失败"
|
||
exit 1
|
||
fi
|
||
|
||
|
||
# -----------------------
|
||
# 域名解析
|
||
# -----------------------
|
||
echo "=== 配置 /etc/hosts ==="
|
||
for entry in "${HOSTS_ENTRIES[@]}"; do
|
||
grep -qF "$entry" /etc/hosts || echo "$entry" >> /etc/hosts
|
||
done
|
||
|
||
# -----------------------
|
||
# 启动 k3s 服务
|
||
# -----------------------
|
||
systemctl daemon-reload
|
||
systemctl enable k3s
|
||
systemctl start k3s
|
||
echo "k3s 配置完成" |