# K3s + Helm + NPM(含 cert-manager / Traefik Middleware)命令式部署文档

> 说明:
> - 本文把你现有的部署步骤整理成“可直接执行的命令式 Markdown 教程”
> - 适用于 ARM64 Linux 机器
> - 文中的 `NPM` 如果你指的是 `Nginx Proxy Manager`,那它通常不是直接部署在 K3s 里的核心依赖;你当前给出的实际内容主要是:
>   - K3s
>   - cert-manager
>   - Helm
>   - Traefik HTTPS 重定向中间件
>   - ClusterIssuer
> - 所以下面文档会按你实际提供的内容整理

---

# 1. 部署目标

部署以下组件:

- K3s
- kubectl(随 K3s 一起可用)
- Helm
- cert-manager CRDs
- Let's Encrypt `ClusterIssuer`
- Traefik 的 `redirect-https` Middleware

---

# 2. 前置要求

请确保:

- 当前系统为 Linux ARM64
- 使用 root 用户执行,或者命令前自行加 `sudo`
- 机器可访问公网
- 域名已经正确解析到当前服务器
- 80/443 端口已放行
- 邮箱地址可用于 Let's Encrypt 注册

---

# 3. 设置主机名

```bash
hostnamectl set-hostname k3s-master
```

检查:

```bash
hostnamectl
```

---

# 4. 配置内核参数

将以下参数写入 `/etc/sysctl.conf`:

- 开启 IP 转发
- 开启 proxy_arp

执行:

```bash
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
```

检查是否生效:

```bash
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.proxy_arp
```

期望输出类似:

```text
net.ipv4.ip_forward = 1
net.ipv4.conf.all.proxy_arp = 1
```

---

# 5. 安装 K3s

执行:

```bash
curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig ~/.kube/config --write-kubeconfig-mode 600
```

说明:

- `--write-kubeconfig ~/.kube/config`
  - 把 kubeconfig 写到当前用户的 `~/.kube/config`
- `--write-kubeconfig-mode 600`
  - 设置配置文件权限为 600

---

# 6. 验证 K3s 是否安装成功

检查服务状态:

```bash
systemctl status k3s --no-pager
```

检查节点:

```bash
kubectl get nodes -o wide
```

检查所有 Pod:

```bash
kubectl get pods -A
```

如果看到节点状态为 `Ready`,说明 K3s 基本安装成功。

---

# 7. 安装 cert-manager CRDs

执行:

```bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.crds.yaml
```

验证:

```bash
kubectl get crds | grep cert-manager
```

---

# 8. 安装 Helm

下载 ARM64 版本:

```bash
wget https://get.helm.sh/helm-v4.1.4-linux-arm64.tar.gz
```

解压:

```bash
tar -zxvf helm-v4.1.4-linux-arm64.tar.gz
```

移动二进制到系统路径:

```bash
mv linux-arm64/helm /usr/local/bin/helm
```

验证版本:

```bash
helm version
```

---

# 9. 添加 Jetstack Helm 仓库并更新

执行:

```bash
helm repo add jetstack https://charts.jetstack.io
helm repo update
```

验证:

```bash
helm repo list
```

---

# 10. 创建 ClusterIssuer 配置文件

新建文件 `production-issuer.yaml`:

```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory

    # Email address used for ACME registration
    email: zszxingchenid@gmail.com

    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod

    # Enable the HTTP-01 challenge provider
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik
```

保存后执行:

```bash
kubectl apply -f production-issuer.yaml
```

验证:

```bash
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-prod
```

---

# 11. 创建 HTTPS 重定向 Middleware 配置文件

新建文件 `https-redirect.yaml`:

```yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: redirect-https
  namespace: default
spec:
  redirectScheme:
    scheme: https
    permanent: true
```

保存后执行:

```bash
kubectl apply -f https-redirect.yaml
```

验证:

```bash
kubectl get middleware -A
kubectl describe middleware redirect-https -n default
```

---

# 12. 推荐的一次性执行顺序

如果你已经准备好了 `production-issuer.yaml` 和 `https-redirect.yaml`,可以按下面顺序执行:

```bash
hostnamectl set-hostname k3s-master

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf

curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig ~/.kube/config --write-kubeconfig-mode 600

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.crds.yaml

wget https://get.helm.sh/helm-v4.1.4-linux-arm64.tar.gz
tar -zxvf helm-v4.1.4-linux-arm64.tar.gz
mv linux-arm64/helm /usr/local/bin/helm

helm repo add jetstack https://charts.jetstack.io
helm repo update

kubectl apply -f production-issuer.yaml
kubectl apply -f https-redirect.yaml
```

---

# 13. 建议补充的 cert-manager 安装步骤

> 注意:
> 你当前命令里只安装了 cert-manager 的 CRDs,
> 但通常还需要安装 cert-manager 控制器本体。
> 否则 `ClusterIssuer` 虽然能创建,但实际签发证书可能不会工作。

建议执行以下命令安装 cert-manager:

```bash
kubectl create namespace cert-manager --dry-run=client -o yaml | kubectl apply -f -
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --version v1.20.2
```

验证:

```bash
kubectl get pods -n cert-manager
```

期望看到类似组件:

- `cert-manager`
- `cert-manager-cainjector`
- `cert-manager-webhook`

---

# 14. 常用检查命令

## 检查节点

```bash
kubectl get nodes -o wide
```

## 检查所有命名空间 Pod

```bash
kubectl get pods -A
```

## 检查 Traefik

```bash
kubectl get pods -n kube-system | grep traefik
```

## 检查 cert-manager

```bash
kubectl get pods -n cert-manager
```

## 检查 ClusterIssuer

```bash
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-prod
```

## 检查 Middleware

```bash
kubectl get middleware -A
kubectl describe middleware redirect-https -n default
```

---

# 15. 故障排查

## 1)`kubectl` 无法连接集群

检查 K3s 服务:

```bash
systemctl status k3s --no-pager
```

检查 kubeconfig:

```bash
ls -l ~/.kube/config
```

---

## 2)`kubectl apply production-issuer.yaml` 报 cert-manager 资源不存在

说明 cert-manager CRDs 可能未安装成功,重新执行:

```bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.crds.yaml
```

然后确认:

```bash
kubectl get crds | grep cert-manager
```

---

## 3)`ClusterIssuer` 创建成功但证书不签发

大概率是因为只装了 CRDs,没有装 cert-manager 控制器。

请执行:

```bash
kubectl create namespace cert-manager --dry-run=client -o yaml | kubectl apply -f -
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --version v1.20.2
```

---

## 4)Let's Encrypt HTTP-01 验证失败

请检查:

- 域名是否正确解析到服务器
- 80 端口是否开放
- Ingress 是否使用 `traefik`
- Traefik 是否正常运行

检查命令:

```bash
kubectl get ingress -A
kubectl get svc -A
kubectl get pods -n kube-system | grep traefik
```

---

# 16. 推荐目录结构

建议把 YAML 文件放到一个单独目录里,例如:

```bash
mkdir -p ~/k3s-init
cd ~/k3s-init
```

目录结构示例:

```text
~/k3s-init/
├── production-issuer.yaml
└── https-redirect.yaml
```

这样后续部署更清晰:

```bash
cd ~/k3s-init
kubectl apply -f production-issuer.yaml
kubectl apply -f https-redirect.yaml
```

---

# 17. 最终建议版部署流程

下面是更完整、更推荐的版本:

```bash
hostnamectl set-hostname k3s-master

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf

curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig ~/.kube/config --write-kubeconfig-mode 600

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.crds.yaml

wget https://get.helm.sh/helm-v4.1.4-linux-arm64.tar.gz
tar -zxvf helm-v4.1.4-linux-arm64.tar.gz
mv linux-arm64/helm /usr/local/bin/helm

helm repo add jetstack https://charts.jetstack.io
helm repo update

kubectl create namespace cert-manager --dry-run=client -o yaml | kubectl apply -f -

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --version v1.20.2

kubectl apply -f production-issuer.yaml
kubectl apply -f https-redirect.yaml
```

---

# 18. 配置文件汇总

## `https-redirect.yaml`

```yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: redirect-https
  namespace: default
spec:
  redirectScheme:
    scheme: https
    permanent: true
```

## `production-issuer.yaml`

```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: zszxingchenid@gmail.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik
```

---