生产级终极完整版(可直接交付)
一、环境拓扑(你的真实机器)
| 角色 | IP | 说明 |
|---|---|---|
| Master | 192.168.222.141 | kubectl 操作机 |
| Node1 | 192.168.222.142 | Worker |
| Node2 | 192.168.222.143 | NFS Server |
二、整体部署顺序(死记)
纯文本
纯文本
NFS → StorageClass → MySQL → Redis → RuoYi后端 → RuoYi前端
三、NFS + StorageClass(第一关)
1️⃣ NFS 服务器(143)
bash
bash
yum 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
✅ 验证:
bash
bash
showmount -e localhost
2️⃣ 所有节点
bash
bash
yum install -y nfs-utils
3️⃣ NFS Provisioner(血泪教训:RBAC 必须全)
rbac.yaml
yaml
yaml
apiVersion: 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.io
provisioner.yaml
yaml
yaml
apiVersion: 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/k8s
storageclass.yaml
yaml
yaml
apiVersion: 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"
四、MySQL(StatefulSet,第二关)
坑 1:PVC Pending
原因:StorageClass 名字写错
解法 :kubectl get sc
坑 2:MySQL 起不来
原因:NFS 权限
解法 :runAsUser: 999
mysql-sts.yaml
#注意下mysql的中文问题,
RuoYi 乱码 ≠ 前端问题
= MySQL 5.7 默认字符集 + K8s 没显式声明 utf8mb4
yaml
yaml
apiVersion: 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-server=utf8mb4"
- "--collation-server=utf8mb4_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: 5Gi
mysql-svc.yaml
yaml
yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None
selector:
app: mysql
ports:
- port: 3306
五、Redis(StatefulSet,第三关)
坑 3:Redis 起不来
原因:UID 不匹配
解法 :runAsUser: 0
redis-sts.yaml
yaml
yaml
apiVersion: 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: 2Gi
redis-svc.yaml
yaml
yaml
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
clusterIP: None
selector:
app: redis
ports:
- port: 6379
六、RuoYi 后端(Deployment,第四关)
坑 4:Java 连不上库
原因 :用了 mysql.server
解法 :必须用 STS 域名
ruoyi-admin.yaml
yaml
yaml
apiVersion: 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?
useUnicode=true&
characterEncoding=utf8&
serverTimezone=Asia/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: "6379"
ruoyi-admin-svc.yaml
yaml
yaml
apiVersion: v1
kind: Service
metadata:
name: ruoyi-admin
spec:
selector:
app: ruoyi-admin
ports:
- port: 8080
targetPort: 8080
七、RuoYi 前端(Nginx,第五关)
坑 5:404
原因 :没代理 /prod-api
坑 6:502
原因:端口不一致
nginx.conf
nginx
nginx
server {
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;
}
}
Dockerfile
dockerfile
dockerfile
FROM 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.yaml
yaml
yaml
apiVersion: 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
八、最终部署命令(严格执行)
bash
bash
kubectl 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?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai