生产级终极完整版可直接交付一、环境拓扑你的真实机器角色IP说明Master192.168.222.141kubectl 操作机Node1192.168.222.142WorkerNode2192.168.222.143NFS Server二、整体部署顺序死记纯文本纯文本NFS → StorageClass → MySQL → Redis → RuoYi后端 → RuoYi前端三、NFS StorageClass第一关1️⃣ NFS 服务器143bashbashyum install -y nfs-utils rpcbind mkdir -p /opt/k8s chmod 777 /opt/k8s cat /etc/exports EOF /opt/k8s *(rw,sync,no_root_squash) EOF systemctl enable --now rpcbind systemctl enable --now nfs-server exportfs -r✅ 验证bashbashshowmount -e localhost2️⃣ 所有节点bashbashyum install -y nfs-utils3️⃣ NFS Provisioner血泪教训RBAC 必须全rbac.yamlyamlyamlapiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-client-provisioner-runner rules: - apiGroups: [] resources: [persistentvolumes] verbs: [get,list,watch,create,delete] - apiGroups: [] resources: [persistentvolumeclaims] verbs: [get,list,watch,update] - apiGroups: [storage.k8s.io] resources: [storageclasses] verbs: [get,list,watch] - apiGroups: [] resources: [events,endpoints] verbs: [get,list,watch,create,update,patch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: kube-system roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.ioprovisioner.yamlyamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner namespace: kube-system spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/iuxt/nfs-subdir-external-provisioner:v4.0.2 env: - name: PROVISIONER_NAME value: nfs-subdir-external-provisioner - name: NFS_SERVER value: 192.168.222.143 - name: NFS_PATH value: /opt/k8s volumeMounts: - name: nfs-root mountPath: /persistentvolumes volumes: - name: nfs-root nfs: server: 192.168.222.143 path: /opt/k8sstorageclass.yamlyamlyamlapiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-storage annotations: storageclass.kubernetes.io/is-default-class: true provisioner: nfs-subdir-external-provisioner allowVolumeExpansion: true reclaimPolicy: Delete volumeBindingMode: Immediate parameters: archiveOnDelete: false四、MySQLStatefulSet第二关坑 1PVC Pending原因StorageClass 名字写错解法kubectl get sc坑 2MySQL 起不来原因NFS 权限解法runAsUser: 999mysql-sts.yaml#注意下mysql的中文问题RuoYi 乱码 ≠ 前端问题 MySQL 5.7 默认字符集 K8s 没显式声明 utf8mb4yamlyamlapiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: securityContext: runAsUser: 999 fsGroup: 999 containers: - name: mysql image: mysql:5.7 args: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_general_ci env: - name: MYSQL_ROOT_PASSWORD value: 123456 - name: MYSQL_DATABASE value: ry_vue ports: - containerPort: 3306 volumeMounts: - name: mysql-data mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-data spec: accessModes: [ReadWriteOnce] storageClassName: nfs-storage resources: requests: storage: 5Gimysql-svc.yamlyamlyamlapiVersion: v1 kind: Service metadata: name: mysql spec: clusterIP: None selector: app: mysql ports: - port: 3306五、RedisStatefulSet第三关坑 3Redis 起不来原因UID 不匹配解法runAsUser: 0redis-sts.yamlyamlyamlapiVersion: apps/v1 kind: StatefulSet metadata: name: redis spec: serviceName: redis replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: securityContext: runAsUser: 0 fsGroup: 0 containers: - name: redis image: redis:6.2 command: [redis-server, --appendonly, yes] ports: - containerPort: 6379 volumeMounts: - name: redis-data mountPath: /data volumeClaimTemplates: - metadata: name: redis-data spec: accessModes: [ReadWriteOnce] storageClassName: nfs-storage resources: requests: storage: 2Giredis-svc.yamlyamlyamlapiVersion: v1 kind: Service metadata: name: redis spec: clusterIP: None selector: app: redis ports: - port: 6379六、RuoYi 后端Deployment第四关坑 4Java 连不上库原因用了mysql.server解法必须用 STS 域名ruoyi-admin.yamlyamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: ruoyi-admin spec: replicas: 1 selector: matchLabels: app: ruoyi-admin template: metadata: labels: app: ruoyi-admin spec: containers: - name: ruoyi-admin image: ruoyi-admin:latest ports: - containerPort: 8080 env: - name: SPRING_DATASOURCE_URL value: jdbc:mysql://mysql-0.mysql.default.svc.cluster.local:3306/ry_vue? useUnicodetrue characterEncodingutf8 serverTimezoneAsia/Shanghai - name: SPRING_DATASOURCE_USERNAME value: root - name: SPRING_DATASOURCE_PASSWORD value: 123456 - name: SPRING_REDIS_HOST value: redis-0.redis.default.svc.cluster.local - name: SPRING_REDIS_PORT value: 6379ruoyi-admin-svc.yamlyamlyamlapiVersion: v1 kind: Service metadata: name: ruoyi-admin spec: selector: app: ruoyi-admin ports: - port: 8080 targetPort: 8080七、RuoYi 前端Nginx第五关坑 5404原因没代理/prod-api坑 6502原因端口不一致nginx.confnginxnginxserver { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } location /prod-api/ { proxy_pass http://ruoyi-admin:8080/; proxy_setHeader Host $host; proxy_setHeader X-Real-IP $remote_addr; } }DockerfiledockerfiledockerfileFROM nginx:alpine COPY ./dist/ /usr/share/nginx/html/ #dist是在当前目录下上传的文件夹 COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD [nginx, -g, daemon off;]ruoyi-frontend.yamlyamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: ruoyi-frontend spec: replicas: 1 selector: matchLabels: app: ruoyi-frontend template: metadata: labels: app: ruoyi-frontend spec: containers: - name: nginx image: my-frontend:v2 #这个是加过若以ui的nginx前端修改版 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: ruoyi-frontend spec: type: NodePort selector: app: ruoyi-frontend ports: - port: 80 targetPort: 80 nodePort: 30080八、最终部署命令严格执行bashbashkubectl apply -f rbac.yaml kubectl apply -f provisioner.yaml kubectl apply -f storageclass.yaml kubectl apply -f mysql-svc.yaml kubectl apply -f mysql-sts.yaml kubectl apply -f redis-svc.yaml kubectl apply -f redis-sts.yaml kubectl apply -f ruoyi-admin-svc.yaml kubectl apply -f ruoyi-admin.yaml kubectl apply -f ruoyi-frontend.yaml#乱码问题ruoyi jar的application.yml示例spring:datasource:url: jdbc:mysql://localhost:3306/ry?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai
K8s(12)RuoYi on K8s 全流程 · 全思路 · 全排错 · 全配置
发布时间:2026/6/12 0:55:16
生产级终极完整版可直接交付一、环境拓扑你的真实机器角色IP说明Master192.168.222.141kubectl 操作机Node1192.168.222.142WorkerNode2192.168.222.143NFS Server二、整体部署顺序死记纯文本纯文本NFS → StorageClass → MySQL → Redis → RuoYi后端 → RuoYi前端三、NFS StorageClass第一关1️⃣ NFS 服务器143bashbashyum install -y nfs-utils rpcbind mkdir -p /opt/k8s chmod 777 /opt/k8s cat /etc/exports EOF /opt/k8s *(rw,sync,no_root_squash) EOF systemctl enable --now rpcbind systemctl enable --now nfs-server exportfs -r✅ 验证bashbashshowmount -e localhost2️⃣ 所有节点bashbashyum install -y nfs-utils3️⃣ NFS Provisioner血泪教训RBAC 必须全rbac.yamlyamlyamlapiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-client-provisioner-runner rules: - apiGroups: [] resources: [persistentvolumes] verbs: [get,list,watch,create,delete] - apiGroups: [] resources: [persistentvolumeclaims] verbs: [get,list,watch,update] - apiGroups: [storage.k8s.io] resources: [storageclasses] verbs: [get,list,watch] - apiGroups: [] resources: [events,endpoints] verbs: [get,list,watch,create,update,patch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: kube-system roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.ioprovisioner.yamlyamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner namespace: kube-system spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/iuxt/nfs-subdir-external-provisioner:v4.0.2 env: - name: PROVISIONER_NAME value: nfs-subdir-external-provisioner - name: NFS_SERVER value: 192.168.222.143 - name: NFS_PATH value: /opt/k8s volumeMounts: - name: nfs-root mountPath: /persistentvolumes volumes: - name: nfs-root nfs: server: 192.168.222.143 path: /opt/k8sstorageclass.yamlyamlyamlapiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-storage annotations: storageclass.kubernetes.io/is-default-class: true provisioner: nfs-subdir-external-provisioner allowVolumeExpansion: true reclaimPolicy: Delete volumeBindingMode: Immediate parameters: archiveOnDelete: false四、MySQLStatefulSet第二关坑 1PVC Pending原因StorageClass 名字写错解法kubectl get sc坑 2MySQL 起不来原因NFS 权限解法runAsUser: 999mysql-sts.yaml#注意下mysql的中文问题RuoYi 乱码 ≠ 前端问题 MySQL 5.7 默认字符集 K8s 没显式声明 utf8mb4yamlyamlapiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: securityContext: runAsUser: 999 fsGroup: 999 containers: - name: mysql image: mysql:5.7 args: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_general_ci env: - name: MYSQL_ROOT_PASSWORD value: 123456 - name: MYSQL_DATABASE value: ry_vue ports: - containerPort: 3306 volumeMounts: - name: mysql-data mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-data spec: accessModes: [ReadWriteOnce] storageClassName: nfs-storage resources: requests: storage: 5Gimysql-svc.yamlyamlyamlapiVersion: v1 kind: Service metadata: name: mysql spec: clusterIP: None selector: app: mysql ports: - port: 3306五、RedisStatefulSet第三关坑 3Redis 起不来原因UID 不匹配解法runAsUser: 0redis-sts.yamlyamlyamlapiVersion: apps/v1 kind: StatefulSet metadata: name: redis spec: serviceName: redis replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: securityContext: runAsUser: 0 fsGroup: 0 containers: - name: redis image: redis:6.2 command: [redis-server, --appendonly, yes] ports: - containerPort: 6379 volumeMounts: - name: redis-data mountPath: /data volumeClaimTemplates: - metadata: name: redis-data spec: accessModes: [ReadWriteOnce] storageClassName: nfs-storage resources: requests: storage: 2Giredis-svc.yamlyamlyamlapiVersion: v1 kind: Service metadata: name: redis spec: clusterIP: None selector: app: redis ports: - port: 6379六、RuoYi 后端Deployment第四关坑 4Java 连不上库原因用了mysql.server解法必须用 STS 域名ruoyi-admin.yamlyamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: ruoyi-admin spec: replicas: 1 selector: matchLabels: app: ruoyi-admin template: metadata: labels: app: ruoyi-admin spec: containers: - name: ruoyi-admin image: ruoyi-admin:latest ports: - containerPort: 8080 env: - name: SPRING_DATASOURCE_URL value: jdbc:mysql://mysql-0.mysql.default.svc.cluster.local:3306/ry_vue? useUnicodetrue characterEncodingutf8 serverTimezoneAsia/Shanghai - name: SPRING_DATASOURCE_USERNAME value: root - name: SPRING_DATASOURCE_PASSWORD value: 123456 - name: SPRING_REDIS_HOST value: redis-0.redis.default.svc.cluster.local - name: SPRING_REDIS_PORT value: 6379ruoyi-admin-svc.yamlyamlyamlapiVersion: v1 kind: Service metadata: name: ruoyi-admin spec: selector: app: ruoyi-admin ports: - port: 8080 targetPort: 8080七、RuoYi 前端Nginx第五关坑 5404原因没代理/prod-api坑 6502原因端口不一致nginx.confnginxnginxserver { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } location /prod-api/ { proxy_pass http://ruoyi-admin:8080/; proxy_setHeader Host $host; proxy_setHeader X-Real-IP $remote_addr; } }DockerfiledockerfiledockerfileFROM nginx:alpine COPY ./dist/ /usr/share/nginx/html/ #dist是在当前目录下上传的文件夹 COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD [nginx, -g, daemon off;]ruoyi-frontend.yamlyamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: ruoyi-frontend spec: replicas: 1 selector: matchLabels: app: ruoyi-frontend template: metadata: labels: app: ruoyi-frontend spec: containers: - name: nginx image: my-frontend:v2 #这个是加过若以ui的nginx前端修改版 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: ruoyi-frontend spec: type: NodePort selector: app: ruoyi-frontend ports: - port: 80 targetPort: 80 nodePort: 30080八、最终部署命令严格执行bashbashkubectl apply -f rbac.yaml kubectl apply -f provisioner.yaml kubectl apply -f storageclass.yaml kubectl apply -f mysql-svc.yaml kubectl apply -f mysql-sts.yaml kubectl apply -f redis-svc.yaml kubectl apply -f redis-sts.yaml kubectl apply -f ruoyi-admin-svc.yaml kubectl apply -f ruoyi-admin.yaml kubectl apply -f ruoyi-frontend.yaml#乱码问题ruoyi jar的application.yml示例spring:datasource:url: jdbc:mysql://localhost:3306/ry?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai