在单个VPS节点上安装k3s Kubernetes

完整版 Kubernetes 对单个 VPS 来说可能显得过于复杂和资源密集。k3s 是 CNCF 认证的轻量级 Kubernetes 发行版,30 秒内安装完毕,仅占用约 512 MB 内存,完全兼容 kubectl 和 Helm。k3s 特别适合在预算有限的 VPS 上运行生产级工作负载。与 Docker Compose 不同,k3s 提供了企业级特性如自动故障恢复、零停机滚动更新、精细的资源限制和声明式基础设施管理。此外,k3s 内置了 Traefik 作为 Ingress 控制器,并集成了本地路径存储驱动,使得在单节点环境中管理持久化数据变得简单直观。

为何选择 k3s 而非 Docker Compose?

Docker Compose 对于运行少量容器足有效率,但当应用规模增长时,Kubernetes 提供了 Docker Compose 无法实现的高级功能:

从 Docker Compose 迁移到 k3s 是自然的进化路径。当您的应用需要更精细的资源控制、健康检查和跨多个容器的服务编排时,k3s 是理想选择。更关键的是,您在 k3s 上编写的 YAML 配置文件和积累的知识,未来可以无缝迁移到更大规模的生产集群。

系统要求与规划

对于生产环境,建议使用 4GB 内存的 VPS。如果计划运行数据库(如 PostgreSQL)或更复杂的应用,8GB 以上内存更为理想。检查 VPS 提供商是否允许修改内核参数和加载内核模块,这些对 Kubernetes 正常运行是必要的。

第一步 — 安装 k3s

k3s 的安装极其简单。官方安装脚本会自动检测系统环境并配置所有必要的组件:

curl -sfL https://get.k3s.io | sh -
# 等待 1-2 分钟自动完成
sudo k3s kubectl get nodes

如果看到节点状态为 Ready,说明 k3s 已成功启动。若节点长时间处于 NotReady 状态,请检查以下项目:

第二步 — 本地配置 kubectl

为了从本地机器(而非 VPS 上)管理集群,需要配置本地 kubectl 连接到 VPS 上的 k3s API:

# 在 VPS 上打印 kubeconfig
sudo cat /etc/rancher/k3s/k3s.yaml

将输出内容复制下来,在本地机器上创建配置文件:

# 在本地机器上
mkdir -p ~/.kube
# 粘贴上面的内容,将 127.0.0.1 替换为 VPS 的公网 IP(例如 1.2.3.4)
nano ~/.kube/config-k3s

# 例如将这一行
# server: https://127.0.0.1:6443
# 改为
# server: https://1.2.3.4:6443

# 设置环境变量指向该配置
export KUBECONFIG=~/.kube/config-k3s

# 验证连接
kubectl get nodes
kubectl get pods --all-namespaces

如果连接失败,确保 VPS 防火墙已开放 6443 端口,并且 IP 地址替换正确。可使用 telnet VPS_IP 6443 测试端口连通性。

第三步 — 部署第一个应用

创建 Deployment

Deployment 定义应用应该如何在集群中运行(镜像、副本数、资源限制等):

# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
spec:
  replicas: 2      # 运行 2 个副本实现负载均衡
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine   # 使用轻量级 Alpine 镜像
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "500m"       # 限制不超过 0.5 CPU 核心
kubectl apply -f nginx-deployment.yaml
kubectl get pods -w    # -w 参数持续监视 Pod 状态变化

运行命令后,kubectl 会逐个启动 2 个 nginx Pod。观察状态从 Pending → ContainerCreating → Running 的变化。

创建 Service

Service 为 Pod 群组提供稳定的网络访问端点。即使 Pod 重启 IP 变化,Service IP 保持不变:

# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: ClusterIP      # ClusterIP 仅在集群内可访问
  ports:
  - protocol: TCP
    port: 80           # Service 监听的端口
    targetPort: 80     # 转发到 Pod 的端口
kubectl apply -f nginx-service.yaml
kubectl get svc        # 查看 Service 的 ClusterIP

通过 Ingress 暴露到互联网(使用内置 Traefik)

Ingress 使应用可以通过 HTTP(S) 从互联网访问。k3s 默认部署 Traefik Ingress 控制器,支持自动 HTTPS 和路由规则:

# nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
spec:
  rules:
  - host: nginx.example.com       # 用你的域名替换
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
kubectl apply -f nginx-ingress.yaml

# 查看 Ingress 的 IP/域名
kubectl get ingress -w

创建 Ingress 后,将你的域名 A 记录指向 VPS 的 IP。Traefik 会自动申请 Let's Encrypt SSL 证书(需要域名指向正确)。等待几秒钟,访问 https://nginx.example.com 应该返回 nginx 欢迎页面。

第四步 — 安装和使用 Helm

Helm 是 Kubernetes 的包管理器,可一条命令部署整个应用栈(例如数据库、缓存、应用服务):

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version

示例:用 Helm 安装 cert-manager

cert-manager 自动化 Kubernetes 中的 TLS 证书管理和续期,与 Traefik 协同工作:

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

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

# 验证安装
kubectl get pods -n cert-manager

Helm Chart 封装了所有必要的 YAML 配置、依赖关系和最佳实践。安装后,cert-manager 会自动为标记了特定注解的 Ingress 颁发和续期 Let's Encrypt 证书。

第五步 — 配置 ConfigMap 和 Secret

ConfigMap 存储应用配置(非敏感数据),Secret 存储敏感信息(密码、API 密钥)。都是 Kubernetes 原生资源,支持热更新:

# 创建 ConfigMap
kubectl create configmap app-config \
  --from-literal=DB_HOST=postgres \
  --from-literal=DB_PORT=5432 \
  --from-literal=LOG_LEVEL=info

# 创建 Secret(自动 Base64 编码)
kubectl create secret generic app-secret \
  --from-literal=DB_PASSWORD=my_secure_password \
  --from-literal=API_KEY=secret_api_key

在 Deployment 中引用这些配置:

env:
- name: DB_HOST
  valueFrom:
    configMapKeyRef:
      name: app-config
      key: DB_HOST
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: app-secret
      key: DB_PASSWORD

修改 ConfigMap/Secret 后,Pod 需要重启才能加载新值。可通过 kubectl rollout restart deployment/app-name 重启 Deployment 中的所有 Pod。

存储和持久卷

对于需要数据持久化的应用(如数据库),需要配置 PersistentVolumeClaim(PVC):

# postgres-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
spec:
  accessModes:
  - ReadWriteOnce              # 一次仅一个 Pod 可读写
  resources:
    requests:
      storage: 50Gi            # 请求 50GB 存储
  storageClassName: local-path # k3s 内置的本地存储驱动

k3s 内置的 local-path 驱动将数据存储在 VPS 的 /var/lib/rancher/k3s/storage 目录。对于生产数据库,建议将这个目录挂载到高性能 SSD 上,或配置定期备份策略。

常用 kubectl 命令速查

kubectl get all -A                            # 查看所有资源
kubectl get nodes                             # 查看集群节点
kubectl get pods -n [namespace]               # 查看指定 namespace 的 Pod
kubectl describe pod [pod-name]               # 查看 Pod 详细信息
kubectl logs [pod-name] -f                    # 流式查看 Pod 日志
kubectl exec -it [pod-name] -- /bin/sh        # 进入 Pod 容器 Shell
kubectl scale deployment [name] --replicas=3  # 扩展副本数
kubectl set image deployment/[name] [container]=[image:tag] # 更新镜像版本
kubectl rollout undo deployment/[name]        # 回滚部署到上一个版本
kubectl port-forward svc/[service] 8080:80    # 本地端口转发测试服务
kubectl delete pod [pod-name]                 # 删除 Pod(Deployment 会自动重建)

启用资源指标监控:默认 k3s 不部署 metrics-server。执行 kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 启用后,即可使用 kubectl top nodes 和 kubectl top pods 查看实时 CPU 和内存使用。

网络和 DNS 配置

k3s 使用 CoreDNS 作为集群内 DNS 服务,所有 Pod 默认可通过服务名称 (dns.default) 相互通信。Service DNS 名称格式为 [service-name].[namespace].svc.cluster.local。例如:

# Pod 访问另一个 namespace 的服务
curl http://my-service.other-namespace.svc.cluster.local:8080

对于跨 VPS 或跨区域的 Kubernetes 集群,可使用 CNI 插件(如 Flannel、Weave)实现高级网络拓扑。k3s 默认使用 Flannel,已配置完毕无需额外设置。

安全加固和最佳实践

RBAC(基于角色的访问控制):k3s 默认启用 RBAC。生产环境中,为不同团队和服务创建独立的 ServiceAccount,并分配最小必要权限:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: read-pods
rules:
- apiGroups: [""]
  resources: ["pods", "pods/logs"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-pods-users
subjects:
- kind: User
  name: "app-user"
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: read-pods
  apiGroup: rbac.authorization.k8s.io

网络策略:使用 NetworkPolicy 限制 Pod 间通信,实现零信任网络:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels:
      tier: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: frontend

资源配额:为每个 namespace 设置资源上限,防止单个应用消耗整个集群的资源:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: production
spec:
  hard:
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    pods: "50"

故障排查和监控

集群运行过程中遇到问题时,按以下步骤诊断:

# 1. 检查 k3s 服务状态
sudo systemctl status k3s

# 2. 查看系统日志
sudo journalctl -u k3s -n 100 -f

# 3. 诊断 Pod 问题
kubectl describe pod [problem-pod]   # 查看事件和状态

# 4. 查看容器日志
kubectl logs [pod-name] --previous   # 上一次的容器日志(如果 Pod 重启过)

# 5. 检查集群健康
kubectl get componentstatuses
kubectl cluster-info

常见问题排查:Pod 卡在 Pending(通常是资源不足或 image 镜像无法拉取)、CrashLoopBackOff(应用启动错误)、ImagePullBackOff(镜像仓库无法访问)。逐一查看事件信息可快速定位问题。

备份和恢复

k3s 默认将集群状态保存在 SQLite 数据库(/var/lib/rancher/k3s/server/db)。定期备份该目录以防数据丢失:

# 在 VPS 上执行定期备份
sudo tar -czf /backup/k3s-backup-$(date +%Y%m%d).tar.gz \
  /var/lib/rancher/k3s/server/db \
  /etc/rancher/k3s/k3s.yaml

# 恢复时停止 k3s,替换数据库,重启
sudo systemctl stop k3s
sudo rm -rf /var/lib/rancher/k3s/server/db
sudo tar -xzf /backup/k3s-backup-20260101.tar.gz -C /
sudo systemctl start k3s

k3s 与 Docker Compose 功能对比

功能 k3s Docker Compose
自动重启✅ 存活探针重启策略
零停机部署✅ 滚动更新❌ 需停机
资源限制✅ CPU/内存有限
学习难度中等(学习曲线)✅ 低
内存开销~512MB~50MB
Helm 支持✅ 完全支持❌ 无
自动扩展✅ 水平扩展❌ 手动扩展
适用场景生产工作负载、多微服务、需要高可靠性开发测试、简单应用、单机部署

需要运行 k3s 的 VPS?

AsiaGB VPS 配备 4–8 GB 内存和完全 root 权限,完美适配 k3s 生产工作负载。SSD 存储、99% 正常运行时间保证。起价仅需 500 泰铢/月。

查看 VPS 方案