k3s 安装部署
随着Kubernetes技术的发展,越来越多的开发者和运维人员开始接触和使用Kubernetes。但对于资源受限的环境,传统的Kubernetes部署显得过于复杂和资源密集。K3s,作为一个轻量级的Kubernetes发行版,为这些场景提供了完美的解决方案。本教程将带领K3s新手一步步搭建自己的Kubernetes集群。
K3s是Rancher Labs开发的轻量级Kubernetes发行版,专为边缘计算、IoT和小型部署环境设计。它通过减少资源消耗和简化安装流程,使得在单机或少数几台机器上快速部署Kubernetes成为可能。
一、k3s 与 Docker 的核心区别 Docker 与 k3s 的定位不同,前者聚焦“单节点容器运行”,后者聚焦“多节点容器集群管理”,核心差异可概括为:
Docker :像「单个快递员」,仅负责在单台机器 上打包、运行容器(如 Nginx、MySQL 容器),无法跨机器管理。
k3s :像「快递公司调度系统」,可管理多台机器(节点) 上的容器,负责任务分配、故障重启、高可用保障,让多容器协同工作并保持稳定。
二、k3s 关键概念(对比 Docker) k3s 基于 Kubernetes 精简而来,核心概念围绕“集群管理”设计,与 Docker 的单节点逻辑差异显著:
1. 容器(Container)
Docker 中 :容器是独立运行的应用打包单元,通过 docker run nginx 直接启动,是 Docker 的核心操作对象。
k3s 中 :容器仍是应用运行载体,但不允许直接管理 ,必须封装到“Pod”中才能部署(类比:Docker 直接指挥“快递员”,k3s 先把“快递员”编为“小组”再指挥)。
2. Pod
k3s 核心概念 :k3s 最小部署单元,可包含 1 个或多个“关系紧密”的容器(如“应用容器 + 日志收集容器”)。 同一 Pod 内的容器共享网络和存储(类比:小组共用一张办公桌和电话)。
对比 Docker :Docker 直接运行单个容器(docker run),k3s 必须通过 Pod 部署容器,示例:
Docker 启动 Nginx:docker run nginx
k3s 启动 Nginx:先定义 Pod 配置文件(如 pod.yaml),再执行 k3s kubectl apply -f pod.yaml。
3. Node(节点)
k3s 核心概念 :运行容器的“物理机/虚拟机”,k3s 集群由两类节点组成:
Server 节点 :集群“大脑”,负责管理集群(调度 Pod、监控状态、存储配置)。
Agent 节点 :集群“工人”,负责实际运行 Pod 中的容器。
对比 Docker :Docker 仅能在“单台机器”运行容器(该机器相当于“孤立节点”),k3s 可将多台机器组成集群统一管理。
4. Deployment(部署)
k3s 核心概念 :Pod 的“自动化管理工具”,确保 Pod 按预期运行,核心能力包括:
维持指定数量的 Pod 副本(如“始终运行 3 个 Nginx Pod”)。
一键更新容器版本(如将 Nginx 从 1.21 升级到 1.25)。
故障自动回滚(升级失败时恢复到上一稳定版本)。
对比 Docker :Docker 需手动执行 docker run 多次创建多副本,容器挂了需手动重启;k3s 可通过 Deployment 全自动管理。
5. Service(服务)
k3s 核心概念 :Pod 的“稳定访问入口”。 因 Pod 可能重启(IP 变化)或被调度到其他节点(IP 变化),直接访问 Pod IP 不稳定。Service 类似“固定前台电话”,无论 Pod 如何变动,都能通过 Service 找到目标 Pod。
对比 Docker :Docker 通过 docker run -p 8080:80 nginx 映射端口,容器重启后需重新配置;k3s Service 自动跟踪 Pod 变化,访问入口始终可用。
6. Namespace(命名空间)
k3s 核心概念 :集群内的“资源隔离工具”,可将集群划分为多个“虚拟子集群”,示例:
dev 命名空间:存放开发环境的 Pod/Service。
prod 命名空间:存放生产环境的 Pod/Service。 不同命名空间的资源互不干扰,便于权限管理和环境隔离。
对比 Docker :Docker 无类似功能,所有容器共享单节点资源,需手动通过网络/存储隔离(操作复杂)。
7. k3s 服务管理(systemctl 命令)
k3s 中 :k3s 以系统服务形式运行,Server/Agent 节点的服务名不同:
Server 节点:服务名 k3s(如 systemctl start k3s)。
Agent 节点:服务名 k3s-agent(如 systemctl start k3s-agent)。
对比 Docker :与 Docker 服务管理逻辑一致,Docker 服务名通常为 docker(如 systemctl start docker)。
k3s是轻量级 Kubernetes 发行版 ,核心差异在于为边缘计算、小集群场景做了极致简化,而k8s是完整版,面向企业级大规模生产环境。
8. 目标场景与定位 两者的设计初衷完全不同,这是所有差异的根源。
k3s :聚焦轻量化场景,如边缘计算设备(路由器、物联网设备)、单机/小集群(3-5节点)、开发测试环境、CI/CD流水线。
k8s (标准Kubernetes):面向企业级生产环境,用于大规模集群(数十到数千节点)、复杂业务部署(微服务、高并发应用),追求功能全面性和稳定性。
9. 架构与组件简化 k3s通过合并、替换组件大幅降低复杂度,k8s则组件独立且完整。
对比维度
k3s
k8s(标准版)
核心组件合并
控制平面组件(API Server、Controller Manager等)打包成单个二进制文件,减少进程数量
控制平面组件独立部署(多进程),需单独维护
默认存储
用轻量级的SQLite 作为默认存储,无需额外部署etcd
依赖etcd (需单独部署,需3/5节点保证高可用)
附加工具整合
内置容器网络(Flannel)、Ingress(Traefik)、CSI存储,开箱即用
需手动部署或集成第三方网络、Ingress、存储插件
节点通信
支持通过“server-agent”模式简化节点注册,无需手动配置证书
需手动配置节点与控制平面的证书、网络通信
10. 资源占用与部署难度 k3s对硬件要求极低,部署速度远快于k8s。
k3s :
最低资源需求:1核CPU + 512MB内存(单机部署),适合低配置设备。
部署方式:单条命令(curl -sfL https://get.k3s.io | sh -)即可完成服务器部署,5分钟内可启动集群。
k8s :
最低资源需求:控制平面建议2核CPU + 4GB内存,节点建议1核CPU + 2GB内存,资源占用高。
部署方式:需手动配置etcd、证书、网络等,或依赖工具(如kubeadm、kops),部署流程复杂,耗时较长。
11. 功能完整性 k3s默认移除部分不常用功能以简化,k8s功能全面无删减。
k3s :默认禁用或移除部分企业级功能,如PodSecurityPolicy(已废弃)、NodeRestriction、部分alpha/beta特性,需手动开启。
k8s :包含全部官方功能,支持alpha/beta特性(需配置)、完整的RBAC权限控制、节点亲和性/反亲和性等复杂调度策略,满足生产环境的复杂需求。
12. 选择建议
选k3s :如果你需要在边缘设备部署、搭建小型测试集群,或追求快速部署、低资源占用。
选k8s :如果你需要搭建企业级生产集群、运行大规模复杂业务,或依赖k8s的完整功能(如高级调度、全量权限控制)。
三、k3s 常用命令(分类整理) k3s 兼容 Kubernetes 核心命令,同时新增自身服务管理命令,按“服务管理、安装卸载、集群操作”分类如下:
1. k3s 服务管理(Server/Agent 节点) 通过 systemctl 管理 k3s 服务生命周期,适用于启动、停止、查看状态等操作:
命令
用途
备注
sudo systemctl start k3s
启动 k3s Server 服务
仅 Server 节点使用
sudo systemctl stop k3s
停止 k3s Server 服务
仅 Server 节点使用
sudo systemctl restart k3s
重启 k3s Server 服务
仅 Server 节点使用
sudo systemctl status k3s
查看 k3s Server 运行状态
可查看是否正常启动、报错信息
sudo systemctl enable k3s
设置 k3s Server 开机自启
避免重启机器后手动启动
sudo systemctl disable k3s
关闭 k3s Server 开机自启
仅需临时使用时配置
sudo systemctl start k3s-agent
启动 k3s Agent 服务
仅 Agent 节点使用,替换 k3s 为 k3s-agent 即可
2. k3s 安装与卸载 推荐安装K3S Server和节点之前执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 mkdir -p /etc/rancher/k3s/cat >> /etc/rancher/k3s/registries.yaml << EOF mirrors: docker.io: endpoint: - "https://docker.m.daocloud.io" gcr.io: endpoint: - "https://gcr.m.daocloud.io" quay.io: endpoint: - "https://quay.m.daocloud.io" registry.k8s.io: endpoint: - "https://k8s.m.daocloud.io" EOF
(1)安装命令
Server 节点(初始化集群) : 基础安装(默认配置):
1 curl -sfL https://get.k3s.io | sh -
自定义配置(如禁用 Traefik、指定数据目录):
1 2 3 4 curl -sfL https://get.k3s.io | sh -s - \ --disable =traefik \ --data-dir /var/lib/my-k3s \ --docker
Agent 节点(加入集群) : 需先获取 Server 节点的 K3S_URL(API 地址)和 K3S_TOKEN(集群令牌):
1 2 3 4 5 6 7 curl -sfL https://get.k3s.io | \ K3S_URL=https://<server-ip>:6443 \ K3S_TOKEN=<token> \ sh -s - \ --docker
返回示例
1 2 root@ubuntu:~# cat /var/lib/rancher/k3s/server/node-token K102a28c38a37cc242058eaa774d061968b4c59416e3c5e418402bef590e78e568a::server:144b7cb8304c99d03d246b56c3a6ea52
(2)卸载命令
Server 节点 :
1 /usr/local/bin/k3s-uninstall.sh
Agent 节点 :
1 /usr/local/bin/k3s-agent-uninstall.sh
3. 集群与资源操作(兼容 kubectl) k3s 内置 kubectl 工具,可通过 k3s kubectl 操作集群(配置环境变量后可简化为 kubectl),核心命令如下:
(1)集群基础信息
命令
用途
k3s kubectl cluster-info
查看集群基本信息(API 地址、核心组件状态)
k3s kubectl get nodes
查看集群节点列表(状态、角色、版本)
k3s kubectl get nodes -o wide
查看节点详细信息(IP、容器运行时、内核版本)
k3s kubectl describe node <节点名>
查看单个节点详情(资源使用、标签、污点)
(2)Pod 操作
命令
用途
k3s kubectl get pods
查看当前命名空间的 Pod 列表(默认 default 命名空间)
k3s kubectl get pods -n <命名空间>
查看指定命名空间的 Pod(如 -n kube-system 查看系统组件)
k3s kubectl get pods --all-namespaces
查看所有命名空间的 Pod
k3s kubectl describe pod <Pod名>
查看单个 Pod 详情(事件、容器配置、挂载存储)
k3s kubectl logs <Pod名>
查看 Pod 日志(默认查看第一个容器)
k3s kubectl logs <Pod名> -f
实时跟踪 Pod 日志(类似 tail -f)
k3s kubectl delete pod <Pod名>
删除指定 Pod(Deployment 管理的 Pod 会自动重建)
(3)Service 操作
命令
用途
k3s kubectl get svc
查看当前命名空间的 Service 列表
k3s kubectl get svc -n <命名空间>
查看指定命名空间的 Service
k3s kubectl describe svc <Service名>
查看 Service 详情(端口映射、后端 Pod 列表)
k3s kubectl expose deployment <部署名> --type=NodePort --port=80 --target-port=80 --name=<Service名>
从 Deployment 创建 NodePort 类型的 Service(暴露端口供外部访问)
(4)Deployment 操作
命令
用途
k3s kubectl get deploy
查看当前命名空间的 Deployment 列表
k3s kubectl get deploy -n <命名空间>
查看指定命名空间的 Deployment
k3s kubectl apply -f <YAML文件>
通过 YAML 文件创建/更新 Deployment(如 nginx-deployment.yaml)
k3s kubectl delete -f <YAML文件>
通过 YAML 文件删除 Deployment
k3s kubectl scale deploy <部署名> --replicas=<数量>
调整 Deployment 的 Pod 副本数(如 --replicas=3 扩容到 3 个副本)
(5)其他常用操作
命令
用途
k3s kubectl get ns
查看所有命名空间
k3s kubectl create ns <命名空间名>
创建新命名空间(如 kubectl create ns dev)
k3s kubectl get configmaps
查看当前命名空间的 ConfigMap(存储配置信息)
k3s kubectl get secrets
查看当前命名空间的 Secret(存储敏感信息,如密码)
k3s kubectl top nodes
查看节点资源使用情况(CPU/内存使用率)
k3s kubectl top pods
查看 Pod 资源使用情况(CPU/内存使用率)
4. 配置文件相关 k3s 集群配置文件默认路径:/etc/rancher/k3s/k3s.yaml
若需通过本地 kubectl 连接远程 k3s 集群,操作步骤:
将远程 Server 节点的 k3s.yaml 复制到本地 ~/.kube/config。
修改配置文件中的 server: https://127.0.0.1:6443 为远程 Server 节点的 IP(如 https://192.168.1.100:6443)。
执行 kubectl cluster-info 验证连接。
四、k3s 实操:安装与 Nginx 测试 1. 系统要求 确保 Linux 服务器满足以下基础条件:
硬件:至少 1GB 内存、1 个 CPU 核心(生产环境建议 2GB+ 内存、2 核+ CPU)。
架构:支持 x86_64、ARMv7 或 ARM64(如树莓派 4B 可安装 ARM64 版本)。
环境:未占用容器运行时(k3s 内置轻量级运行时,无需提前安装 Docker,若需用 Docker 需额外配置)。
2. 安装 k3s(国内加速) 使用国内镜像源安装,避免网络问题,同时指定 Docker 为容器运行时(可选):
1 2 3 4 5 6 curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRROR=cn \ K3S_NODE_NAME=server \ sh -s - \ --docker --disable =traefik --service-node-port-range=1-65535
1 2 3 4 5 6 7 8 curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRROR=cn \ K3S_NODE_NAME=k3node \ K3S_URL=https://192.168.31.222:6443 \ K3S_TOKEN=K109b98888ba53e53a72b5dc0df4ab87d396e3765bea9cbbd5ebdb22d8a8a8871a2::server:d4bc60b93cf4c86c0b6fe77cdea85d5e \ sh -s - \ --docker
3. 验证安装 查看 k3s 核心组件状态(所有组件状态为 Running 即安装成功):
1 2 3 4 5 6 root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE coredns-64fd4b4794-rjgzb 1/1 Running 0 7h17m local-path-provisioner-774c6665dc-f7s9x 1/1 Running 0 7h17m metrics-server-7bfffcd44-5qjr2 1/1 Running 0 7h17m
4. 配置 kubectl(可选,简化命令) 默认需通过 k3s kubectl 执行命令,配置后可直接用 kubectl:
1 2 3 4 5 6 mkdir -p $HOME /.kubesudo cp /etc/rancher/k3s/k3s.yaml $HOME /.kube/configsudo chown $(id -u):$(id -g) $HOME /.kube/config
5. 部署 Nginx 测试 通过 Deployment 部署 Nginx,并暴露端口供外部访问。
5.1 创建 Deployment 配置文件 5.1.1 常见的资源类型
资源名称(Resource)
核心用途
关键特点
典型场景
StatefulSet
部署有状态应用
1. Pod有固定名称和网络标识(DNS),重建后不变; 2. 支持稳定持久化存储(每个Pod对应独立存储卷); 3. 按顺序部署/删除Pod,保证状态一致
MySQL主从集群、ZooKeeper、Elasticsearch
DaemonSet
确保指定节点运行相同Pod
1. 所有目标节点(或指定节点)必运行一个Pod; 2. 新增节点自动创建Pod,删除节点自动清理Pod
日志收集(Fluentd、Logstash)、监控代理(Prometheus Node Exporter)、网络插件(Calico、Flannel节点代理)
Job
运行一次性任务
1. 任务完成后Pod自动终止,状态变为Completed; 2. 支持配置失败重试次数
数据备份、批量计算
CronJob
定时执行周期性任务
1. 基于Job扩展,支持类似Linux cron的时间规则; 2. 按预设时间重复执行任务
定时数据备份、日志清理、周期性报表生成
ReplicaSet
维护指定数量的Pod副本
1. 确保集群中始终有N个Pod运行; 2. 是Deployment的底层依赖,通常不直接使用
配合Deployment管理无状态应用副本(不单独使用)
Pod
容器的基础封装单位
1. K8s最小资源单位,可包含多个容器; 2. 直接创建的Pod重启后可能换节点,IP会变化
临时测试场景(不推荐用于正式业务,需通过工作负载间接管理)
ReplicationController
早期管理Pod副本的资源
1. 功能类似ReplicaSet,用于维护Pod副本数量; 2. 现已被ReplicaSet替代,功能更弱
legacy旧集群兼容场景(建议优先用ReplicaSet或Deployment)
新建 nginx-deployment.yaml 文件,内容如下(含详细注释):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
5.2 部署 Nginx 执行配置文件创建 Deployment:
1 kubectl apply -f nginx-deployment.yaml
1 2 3 root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get deployment nginx NAME READY UP-TO-DATE AVAILABLE AGE nginx 2/2 2 2 76m
5.3 暴露 Nginx 服务(NodePort 类型) 通过 Service 暴露 Nginx 端口,让外部可访问:
1 2 3 4 5 kubectl expose deployment nginx \ --type =NodePort \ --port=80 \ --target-port=80 \ --name=nginx-service
或者
1 2 3 4 5 6 7 8 9 10 11 12 13 cat > nginx-service.yml <<EOF apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 EOF
1 kubectl apply -f nginx-service.yml
5.4 查看 Pod 与 Service 状态
5.5 访问 Nginx 测试 在浏览器中输入 http://<节点IP>:<节点端口>(如 http://192.168.31.222:30112),看到 Nginx 欢迎页即成功。
6. 部署 MySQL 8.0 测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0.28-debian ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "202019" - name: MYSQL_DATABASE value: "k3s" volumeMounts: - name: mysql-data mountPath: /var/lib/mysql args: - --default-authentication-plugin=mysql_native_password - --bind-address=0.0.0.0 volumeClaimTemplates: - metadata: name: mysql-data spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Gi --- apiVersion: v1 kind: Service metadata: name: mysql spec: selector: app: mysql ports: - port: 3306 targetPort: 3306 nodePort: 30306 type: NodePort
1 kubectl apply -f mysql.yaml
6.1 查看 Pod 状态 1 2 3 4 5 root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get pods -l app=mysql NAME READY STATUS RESTARTS AGE mysql-0 1/1 Running 0 6m51s
6.2 查看服务状态 1 2 3 4 5 root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get svc mysql NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mysql NodePort 10.43.212.180 <none> 3306:30306/TCP 9m52s
连接数据库
1 192.168.31.141:30306 root 202019
7.0 部署集群
服务器
IP
角色
Ubuntu 22.0.4
192.168.31.141
Controller
Ubuntu 22.0.4
192.168.31.142
Worker
在此之前确保我们的主机名不同,或是重命名服务器
1 2 3 4 vim /etc/hosts ===添加以下内容=== 127.0.0.1 ubuntu-agent
查看主节点token,我们需要凭借token加入集群
1 2 3 4 root@wyy-VMware-Virtual-Platform:~/k3s# cat /var/lib/rancher/k3s/server/node-token K109b98888ba53e53a72b5dc0df4ab87d396e3765bea9cbbd5ebdb22d8a8a8871a2::server:d4bc60b93cf4c86c0b6fe77cdea85d5e
计算节点执行
1 2 3 4 5 6 7 8 curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRROR=cn \ INSTALL_K3S_VERSION=v1.33.5+k3s1 \ K3S_URL=https://192.168.87.163:6443 \ K3S_TOKEN=K102a28c38a37cc242058eaa774d061968b4c59416e3c5e418402bef590e78e568a::server:144b7cb8304c99d03d246b56c3a6ea52 \ K3S_SKIP_TLS_SAN_VERIFY=true \ K3S_NODE_NAME=ubuntu-agent \ sh -s - \ --docker
1 2 3 4 5 6 7 8 9 10 11 12 13 root@wyy-VMware-Virtual-Platform-2:~# systemctl status k3s-agent.service ● k3s-agent.service - Lightweight Kubernetes Loaded: loaded (/etc/systemd/system/k3s-agent.service; enabled; preset: enabled) Active: active (running) since Fri 2025-11-14 10:18:07 CST; 1h 27min ago Invocation: fa7f34cf814c4684b139c4d3788601fa Docs: https://k3s.io Main PID: 1878 (k3s-agent) Tasks: 12 Memory: 224.1M (peak: 229.1M) CPU: 1min 10.734s CGroup: /system.slice/k3s-agent.service └─1878 "/usr/local/bin/k3s agent"
主节点视角
1 2 3 4 root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get nodes NAME STATUS ROLES AGE VERSION k3node Ready <none> 86m v1.33.5+k3s1 server Ready control-plane,master 7h26m v1.33.5+k3s1
五、ingress安装及测试 1.安装ingress-nginx https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.14.0/deploy/static/provider/baremetal/deploy.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx namespace: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: - "" resources: - namespaces verbs: - get - apiGroups: - "" resources: - configmaps - pods - secrets - endpoints verbs: - get - list - watch - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - coordination.k8s.io resourceNames: - ingress-nginx-leader resources: - leases verbs: - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission namespace: ingress-nginx rules: - apiGroups: - "" resources: - secrets verbs: - get - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets - namespaces verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission rules: - apiGroups: - admissionregistration.k8s.io resources: - validatingwebhookconfigurations verbs: - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: v1 data: null kind: ConfigMap metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-controller namespace: ingress-nginx spec: minReadySeconds: 0 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 spec: automountServiceAccountToken: true containers: - args: - /nginx-ingress-controller - --election-id=ingress-nginx-leader - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so image: registry.k8s.io/ingress-nginx/controller:v1.14.0@sha256:e4127065d0317bd11dc64c4dd38dcf7fb1c3d72e468110b4086e636dbaac943d imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - /wait-shutdown livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: controller ports: - containerPort: 80 name: http protocol: TCP - containerPort: 443 name: https protocol: TCP - containerPort: 8443 name: webhook protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: requests: cpu: 100m memory: 90Mi securityContext: allowPrivilegeEscalation: false capabilities: add: - NET_BIND_SERVICE drop: - ALL readOnlyRootFilesystem: false runAsGroup: 82 runAsNonRoot: true runAsUser: 101 seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /usr/local/certificates/ name: webhook-cert readOnly: true dnsPolicy: ClusterFirst nodeSelector: kubernetes.io/os: linux serviceAccountName: ingress-nginx terminationGracePeriodSeconds: 300 volumes: - name: webhook-cert secret: secretName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission-create namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission-create spec: automountServiceAccountToken: true containers: - args: - create - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc - --namespace=$(POD_NAMESPACE) - --secret-name=ingress-nginx-admission env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.4@sha256:bcfc926ed57831edf102d62c5c0e259572591df4796ef1420b87f9cf6092497f imagePullPolicy: IfNotPresent name: create securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure serviceAccountName: ingress-nginx-admission ttlSecondsAfterFinished: 0 --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission-patch spec: automountServiceAccountToken: true containers: - args: - patch - --webhook-name=ingress-nginx-admission - --namespace=$(POD_NAMESPACE) - --patch-mutating=false - --secret-name=ingress-nginx-admission - --patch-failure-policy=Fail env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.4@sha256:bcfc926ed57831edf102d62c5c0e259572591df4796ef1420b87f9cf6092497f imagePullPolicy: IfNotPresent name: patch securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure serviceAccountName: ingress-nginx-admission ttlSecondsAfterFinished: 0 --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.14 .0 name: ingress-nginx-admission webhooks: - admissionReviewVersions: - v1 clientConfig: service: name: ingress-nginx-controller-admission namespace: ingress-nginx path: /networking/v1/ingresses port: 443 failurePolicy: Fail matchPolicy: Equivalent name: validate.nginx.ingress.kubernetes.io rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses sideEffects: None
安装ingress-nginx
1 2 3 4 5 kubectl apply -f deploy.yaml root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7c658dcdb7-2tvrn 1/1 Running 0 51m
2.创建ingress 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cat > ingress.yml <<EOF apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress spec: ingressClassName: nginx rules: - host: traefik.com http: paths: - pathType: Prefix path: "/" backend: service: name: nginx-service # 前面nginx部署的service名称 port: number: 80 EOF
1 2 3 4 5 kubectl apply -f ingress.yml root@wyy-VMware-Virtual-Platform:~/k3s# kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE ingress nginx traefik.com 192.168.31.141 80 92m
service: ingress-nginx-controller 修改端口为
1 2 http: 80 → 80/http → http/TCP https: 443 → 443/https → https/TCP
把上述ADDRESS部分的IP和域名绑定解析
1 echo 192.168.31.141 traefik.com >> /etc/hosts
六、问题解决 安装agent是出现以下问题
1 2 3 4 journalctl -u k3s-agent -f 11月 14 02:48:13 wyy-VMware-Virtual-Platform-2 k3s[8319]: time ="2025-11-14T02:48:13+08:00" level=info msg="Waiting to retrieve agent configuration; server is not ready: /var/lib/rancher/k3s/agent/serving-kubelet.crt: Node password rejected, duplicate hostname or contents of '/etc/rancher/node/password' may not match server node-passwd entry, try enabling a unique node name with the --with-node-id flag"
Agent node对应的passwd和server中存储的hostname对应的passwd不一致
1 2 3 4 5 6 7 8 9 10 # agent $ cat /etc/rancher/node/password 47211f28f469622cccf893071dbda698 $ hostname xxxxxxx # server cat /var/lib/rancher/k3s/server/cred/passwd 31567be88e5408a31cbd036fc9b37975,ip-172-31-13-54,ip-172-31-13-54, cf3f4f37042c05c631e07b0c0abc528f,xxxxx,xxxxxx,