記錄用 Terraform 在 Proxmox 上自動化建置 LXC + K3s 過程中踩到的坑。
1. SSH 認證失敗(remote-exec)
錯誤
SSH authentication failed: ssh: unable to authenticate, attempted methods [none publickey]原因connection block 沒有提供 password 或 private_key,SSH 沒有任何可用的認證方式。
修法
在 connection block 加上 password:
connection {
type = "ssh"
user = "your-username"
host = "192.168.68.x"
password = "your-password"
}2. API Token 401 Authentication Failed
錯誤
error retrieving container: received an HTTP 401 response - Reason: Authentication failed!原因api_token 的 UUID 填錯了(複製到舊的 token 值)。
確認方式
在 PVE 上跑:
pveum user token list root@pam把輸出的 value 欄位貼回 main.tf:
api_token = "root@pam!privileged_token=<正確的UUID>"3. zsh 的 ! 符號問題
錯誤
zsh: event not found: privileged_token=...原因
zsh 把 ! 當成 history expansion,導致 curl 指令失敗。
修法
用單引號包住含有 ! 的字串:
curl -sk -H 'Authorization: PVEAPIToken=root@pam!privileged_token=UUID' https://...4. Proxmox API Token Privilege Separation
原因
Proxmox token 預設開啟 Privilege Separation(privsep=1),token 沒有任何 ACL 權限,打 API 會被拒。
修法(方案A)用 root@pam,關閉 privsep
pveum user token remove root@pam privileged_token
pveum user token add root@pam privileged_token --privsep 0修法(方案B)用獨立 user,設 ACL
pveum user add terraform@pve
pveum aclmod / -user terraform@pve -role Administrator
pveum user token add terraform@pve terraform-token --privsep 05. 403:修改 privileged container feature flags 需要 root@pam
錯誤
Permission check failed (changing feature flags for privileged container is only allowed for root@pam)原因unprivileged = false 的容器,feature flags(fuse、keyctl 等)只有 root@pam token 能設定,其他 user 就算有 Administrator 權限也不行。
修法
改用 root@pam token,或是改成 unprivileged container:
unprivileged = true
features {
nesting = true
}6. sudo echo 無法寫入受保護檔案
錯誤
cannot create /etc/pve/lxc/<vmid>.conf: Permission denied原因sudo echo 'xxx' >> /etc/pve/lxc/xxx.conf 無效,因為 >> 重定向是由原本的 shell 執行,不是 sudo 的 root shell。
修法
改用 tee -a:
echo 'lxc.apparmor.profile: unconfined' | sudo tee -a /etc/pve/lxc/<vmid>.conf7. pct 指令找不到
錯誤
pct: not found原因pct 在 /usr/sbin/pct,非 root 使用者的 PATH 不含 /usr/sbin。
修法
用完整路徑:
sudo /usr/sbin/pct stop <vmid>
sudo /usr/sbin/pct start <vmid>8. Terraform remote-exec 卡住(sudo 等待密碼)
現象
remote-exec 卡在 [sudo] password for user: 超過 2 分鐘。
原因
Terraform 執行遠端指令時無法互動輸入密碼,sudo 等待輸入導致 timeout。
修法
在 PVE 上設定 NOPASSWD:
echo 'your-username ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/your-username9. kubectl get nodes — connection refused(k3s 還在啟動)
錯誤
dial tcp 127.0.0.1:6443: connect: connection refused原因
k3s 啟動時會先在 6444 跑 temporary apiserver,待 TLS 憑證產生完畢才切換到 6443。
太早跑 kubectl 就會 connection refused。
修法
等 k3s 完全就緒再下指令(通常 30~60 秒),或用以下指令確認 6443 已在監聽:
ss -tlnp | grep 644310. LXC 裡無法載入 kernel module(br_netfilter / overlay)
錯誤(systemctl status k3s)
modprobe br_netfilter (code=exited, status=1/FAILURE)
modprobe overlay (code=exited, status=1/FAILURE)原因
LXC 容器沒有權限載入 kernel module,必須在 PVE 宿主機上載入。
修法
在 PVE host 上執行:
modprobe br_netfilter overlay
# 開機自動載入
echo -e "br_netfilter\noverlay" | tee /etc/modules-load.d/k3s.conf11. kubelet 起不來:/dev/kmsg 不存在
錯誤
open /dev/kmsg: no such file or directory
Error: failed to run Kubelet: failed to create kubelet: open /dev/kmsg: no such file or directory原因
unprivileged LXC 容器裡 /dev/kmsg 不存在,kubelet 啟動時需要它來建立 oomWatcher,找不到就直接 crash 並重啟。
修法(容器內)
echo 'L /dev/kmsg - - - - /dev/console' > /etc/tmpfiles.d/kmsg.conf
systemd-tmpfiles --create /etc/tmpfiles.d/kmsg.conf
systemctl restart k3sTerraform 自動化(remote-exec 加在 pct start 之後)
"sudo /usr/sbin/pct exec ${self.vm_id} -- bash -c \"echo 'L /dev/kmsg - - - - /dev/console' > /etc/tmpfiles.d/kmsg.conf && systemd-tmpfiles --create /etc/tmpfiles.d/kmsg.conf\""12. kubelet 無法寫入 /proc/sys(unprivileged LXC 權限不足)
錯誤
open /proc/sys/vm/overcommit_memory: permission denied
open /proc/sys/kernel/panic: permission denied
open /proc/sys/kernel/panic_on_oops: permission denied
Error: failed to run Kubelet: failed to start ContainerManager原因
unprivileged LXC 容器沒有權限寫入 kernel 參數,kubelet 啟動時嘗試調整這些值並 crash。
修法
建立 k3s 設定檔,啟用 KubeletInUserNamespace feature gate 讓 kubelet 跳過這些操作:
mkdir -p /etc/rancher/k3s
cat > /etc/rancher/k3s/config.yaml << 'EOF'
kubelet-arg:
- "feature-gates=KubeletInUserNamespace=true"
EOF
systemctl restart k3s確認成功
NAME STATUS ROLES AGE VERSION
k3s-master Ready control-plane,etcd 70s v1.35.4+k3s1