构建wezzer平台!

redis

部署

复制代码
[root@k8s-master redis]# ls
namespace.yaml  redis-config.yaml  redis-master.yaml  redis-slave.yaml
[root@k8s-master redis]# cat namespace.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: redis
[root@k8s-master redis]# cat redis-config.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-config
  namespace: redis
data:
  redis-master.conf: |
    port 6379
    bind 0.0.0.0
    protected-mode no
    daemonize no
    timeout 0
    save ""
    appendonly no
    maxmemory 1gb
    maxmemory-policy allkeys-lru
  redis-slave.conf: |
    port 6379
    bind 0.0.0.0
    protected-mode no
    daemonize no
    timeout 0
    save ""
    appendonly no
    maxmemory 1gb
    maxmemory-policy allkeys-lru
    slaveof redis-master-0.redis-master.redis.svc.cluster.local 6379
    slave-read-only yes

redis-master

复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-master
  namespace: redis
spec:
  serviceName: redis-master
  replicas: 1
  selector:
    matchLabels:
      app: redis-master
  template:
    metadata:
      labels:
        app: redis-master
    spec:
      containers:
      - name: redis-master
        image: redis:6
        command:
        - /bin/sh
        - -c
        - |
          redis-cli FLUSHALL  # 清空所有缓存
          redis-server /etc/redis/redis-master.conf
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: redis-config
          mountPath: /etc/redis
        - name: redis-data
          mountPath: /data
      volumes:
      - name: redis-data
        persistentVolumeClaim:
          claimName: redis-master-pvc
      - name: redis-config
        configMap:
          name: redis-config
---
apiVersion: v1
kind: Service
metadata:
  name: redis-master
  namespace: redis
spec:
  clusterIP: None
  selector:
    app: redis-master
  ports:
  - port: 6379
    targetPort: 6379

redis-slave

复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-slave
  namespace: redis
spec:
  serviceName: redis-slave
  replicas: 2
  selector:
    matchLabels:
      app: redis-slave
  template:
    metadata:
      labels:
        app: redis-slave
    spec:
      containers:
      - name: redis-slave
        image: redis:6
        command:
        - /bin/sh
        - -c
        - |
          redis-cli FLUSHALL  # 清空所有缓存
          redis-server /etc/redis/redis-master.conf
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: redis-config
          mountPath: /etc/redis
      volumes:
      - name: redis-config
        configMap:
          name: redis-config
---
apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  namespace: redis
spec:
  clusterIP: None
  selector:
    app: redis-slave
  ports:
  - port: 6379
    targetPort: 6379

mysql

部署

复制代码
[root@k8s-master mysql]# ls
aaa_mysql.sh  configmap.yaml  init-scripts.yaml  master.yaml  mysql.yaml  secret.yaml  slave.yaml
[root@k8s-master mysql]# cat mysql.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: mysql
[root@k8s-master mysql]# cat secret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secrets
  namespace: mysql
type: Opaque
data:
  root-password: MTIzLmNvbQ==  # 解码后:123.com
[root@k8s-master mysql]# cat init-scripts.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-init-scripts
  namespace: mysql
data:
  master-init.sql: |
    # 从环境变量获取密码(避免明文)
    CREATE USER IF NOT EXISTS 'rsyncuser'@'%' IDENTIFIED BY '123.com';
    GRANT REPLICATION SLAVE ON *.* TO 'rsyncuser'@'%';
    
    CREATE DATABASE IF NOT EXISTS discuz;
    CREATE USER IF NOT EXISTS 'discuz'@'%' IDENTIFIED BY '123.com';
    GRANT ALL PRIVILEGES ON discuz.* TO 'discuz'@'%';
    
    CREATE DATABASE IF NOT EXISTS biyesheji;
    CREATE USER IF NOT EXISTS 'tomcat'@'%' IDENTIFIED BY '123.com';
    GRANT ALL PRIVILEGES ON biyesheji.* TO 'tomcat'@'%';
    
    FLUSH PRIVILEGES;
  slave-init.sql: |
    CHANGE MASTER TO
      MASTER_HOST = 'mysql-master-0.mysql-master.mysql.svc.cluster.local',
      MASTER_PORT = 3306,
      MASTER_USER = 'rsyncuser',
      MASTER_PASSWORD = '123.com',  # 从环境变量获取
      MASTER_AUTO_POSITION = 1;
    START SLAVE;
[root@k8s-master mysql]# cat configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
  namespace: mysql
data:
  master.cnf: |
    [mysqld]
    server-id=10
    log_bin=/var/lib/mysql/mysql-bin.log
    read_only=0
    bind-address=0.0.0.0
    gtid_mode=ON
    enforce_gtid_consistency=ON
    default_authentication_plugin=mysql_native_password

  slave1.cnf: |
    [mysqld]
    server-id=20
    relay_log=/var/lib/mysql/mysql-relay-bin.log
    log_bin=/var/lib/mysql/mysql-bin.log
    read_only=1
    bind-address=0.0.0.0
    gtid_mode=ON
    enforce_gtid_consistency=ON
    default_authentication_plugin=mysql_native_password

mysql-master

复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-master
  namespace: mysql
spec:
  serviceName: mysql-master
  replicas: 1
  selector:
    matchLabels:
      app: mysql-master
  template:
    metadata:
      labels:
        app: mysql-master
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: root-password
        volumeMounts:
        - name: mysql-config
          mountPath: /etc/mysql/conf.d/master.cnf
          subPath: master.cnf
        - name: master-init-script  # 仅挂载主库脚本
          mountPath: /docker-entrypoint-initdb.d/master-init.sql
          subPath: master-init.sql  # 明确指定脚本名
      volumes:
      - name: mysql-config
        configMap:
          name: mysql-config
          items:
          - key: master.cnf
            path: master.cnf
      - name: master-init-script  # 关联 ConfigMap 中的主库脚本
        configMap:
          name: mysql-init-scripts
          items:
          - key: master-init.sql
            path: master-init.sql
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-master
  namespace: mysql
spec:
  ports:
  - port: 3306
    name: mysql
  clusterIP: None
  selector:
    app: mysql-master

mysql-slave

复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-slave
  namespace: mysql
spec:
  serviceName: mysql-slave
  replicas: 1  
  selector:
    matchLabels:
      app: mysql-slave
  template:
    metadata:
      labels:
        app: mysql-slave
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: root-password
        volumeMounts:
        - name: mysql-config
          mountPath: /etc/mysql/conf.d/slave.cnf
          subPath: slave1.cnf
        - name: init-script
          mountPath: /docker-entrypoint-initdb.d
      volumes:
      - name: mysql-config
        configMap:
          name: mysql-config
          items:
          - key: slave1.cnf
            path: slave1.cnf
      - name: init-script
        configMap:
          name: mysql-init-scripts


---
apiVersion: v1
kind: Service
metadata:
  name: mysql-slave
  namespace: mysql
spec:
  ports:
  - port: 3306
    name: mysql
  clusterIP: None
  selector:
    app: mysql-slave

web-nginx

构建自定义镜像

配置文件

nginx
复制代码
server {
    listen 80;
    server_name localhost;
    root /var/www/html;
    index index.php index.html index.htm;

    access_log /var/log/nginx/discuz_access.log;
    error_log /var/log/nginx/discuz_error.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php83-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}
php-fpm
复制代码
[www]
user = nginx
group = nginx
listen = /run/php/php83-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

php_admin_value[error_log] = /var/log/php83/www-error.log
php_admin_flag[log_errors] = on
Dockerfile
复制代码
FROM alpine:latest
RUN  apk update && apk add --no-cache \
     php83 php83-fpm php83-mysqlnd php83-gd php83-mbstring \
     php83-curl php83-json php83-openssl php83-xml \
     php83-mysqli php83-tokenizer php83-pdo php83-pdo_mysql \
     nginx php83-redis vim 
RUN mkdir -p \
    /run/nginx \
    /var/www/html \
    /run/php &&\
    chown -R nginx:nginx /var/www/html /run/nginx && \
    chmod 755 /var/www/html
#nginx配置
COPY discuz.conf /etc/nginx/http.d/default.conf
#php配置
COPY www.conf /etc/php83/php-fpm.d/www.conf
#暴露端口
EXPOSE 80
#运行
CMD ["sh","-c","php-fpm83 --nodaemonize & nginx -g 'daemon off;'"]

启动容器

编写测试文件

复制代码
index.html 
web-nginx

info.php 
<?php
    phpinfo(); 
?>
复制代码
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$host = 'mysql-master-0.mysql-master.mysql.svc.cluster.local';     // 数据库主机地址
$user = 'discuz';        // MySQL 用户名
$pass = '123.com';       // MySQL 用户密码
$dbname = 'discuz';      // 要连接的数据库名

// 尝试连接 MySQL
$conn = new mysqli($host, $user, $pass, $dbname);

// 检查连接错误
if ($conn->connect_error) {
    // 连接失败时终止脚本并输出错误
    die('连接失败:' . $conn->connect_error);
}

// 连接成功,输出数据库版本信息
echo "MySQL 连接成功!数据库版本:" . $conn->server_info;
?>
复制代码
<?php
$redis = new Redis();
try {
    // 连接Master(替换为你的实际地址和端口)
    $conn = $redis->connect('redis-master.redis.svc.cluster.local', 6379, 2); 
    if ($conn) {
        echo "连接成功!";
        echo "Redis响应:" . $redis->ping(); // 测试服务响应
    } else {
        echo "连接失败(无错误信息)";
    }
} catch (RedisException $e) {
    // 打印具体错误(如:连接超时、拒绝连接、认证失败等)
    echo "Redis连接错误:" . $e->getMessage();
}

导入dicuz文件

复制代码
docker cp ./  c37e6292ca17:/var/www/html/

修改属主

修改discuz默认配置(upload/config/)

config_global_default.php
数据库
从库
redis数据库
config_ucenter_default.php

镜像导出

复制代码
[root@k8s-master web-nginx]# docker commit 9fbf6304f924 web-nginx:latest
sha256:79c04b1494346f3e4111229e2d902c40ee73c8beb1ad9d65df2111c0906fa73b
[root@k8s-master web-nginx]# docker save -o web-nginx.tar web-nginx:latest
镜像导入每个节点

部署web-nginx

编写 启动文件

启动

访问

默认即可

问题

出现这个页面时,将redi缓存清理就ok

taomcat

自定义镜像

下载镜像

复制代码
docker pull tomcat:8

生成测试镜像

复制代码
docker run -itd --name tomcat -v /root/xm/tomcat/shangcheng/:/usr/local/tomcat/webapps/  --restart=always tomcat:8
sql文件拷贝给mysql库
注入sql语句

将复制的 sql文件内容拷贝到 configmap.yaml 文件中

主配置 匹配cofihmap

复制代码
     volumeMounts:
        - name: biyesheji-sql
          mountPath: /docker-entrypoint-initdb.d/biyesheji.sql
          subPath: biyesheji.sql
      volumes:
      - name: biyesheji-sql
        configMap:
          name: mysql-config
          items:
          - key: biyesheji.sql
            path: biyesheji.sql

验证

编写镜像

修改商城默认配置

复制代码
vim WEB-INF/classes/jdbc.properties 
复制代码
 vim /usr/local/tomcat/webapps/biyesheji/WEB-INF/classes/jdbc.properties 
复制代码
docker commit d44d4163 shangcheng:v1

docker save -o shangcheng.tar   a4e0365

将镜像拷给各节点

复制代码
docker tag a4e036 shangcheng:v1

如果
REPOSITORY                                           TAG          IMAGE ID       CREATED         SIZE
<none>                                               <none>       a4e0365f328b   6 minutes ago   208MB

部署商城

复制代码
apiVersion: v1
kind: Namespace
metadata:
  name: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dep-tomcat
  namespace: web 
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-tomcat
  template:
    metadata:
      labels:
        app: web-tomcat
    spec:
      containers:
      - name: tomcat
        image: shangcheng:v1  # 使用你的镜像
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080  # 容器内暴露的端

---
apiVersion: v1
kind: Service
metadata:
  name: svc-tomcat
  namespace: web  # 指定命名空间为 discuz
spec:
  type: NodePort
  ports:
  - port: 8080        # 集群内访问端口
    targetPort: 8080  # 容器内端口
    nodePort: 30808 # 对外暴露的节点端口
  selector:
    app: web-tomcat  # 匹配 Deployment 的标签

启动

结论

访问成功(/biyesheji/fore/foreIndex/)

discuz与nginx基于域名访问

拷贝镜像并导入

解压并提交

loadbalance模式

复制代码
kubectl -n ingress-nginx edit svc ingress-nginx-controller

创建ip池

复制代码
cat >IPAddressPool.yaml<<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: planip-pool #这里与下面的L2Advertisement的ip池名称需要一样
  namespace: metallb-system
spec:
  addresses:
  - 192.168.11.140-192.168.11.170 #自定义ip段
EOF

关联IP池

复制代码
cat >L2Advertisement.yaml<<EOF
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: planip-pool
  namespace: metallb-system
spec:
  ipAddressPools:
  - planip-pool #这里需要跟上面ip池的名称保持一致
EOF

提交

复制代码
kubectl apply -f IPAddressPool.yaml
kubectl apply -f L2Advertisement.yaml

添加规则

复制代码
kubectl apply -f ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress # 创建一个类型为Ingress的资源
metadata:
  name: nginx-ingress # 这个资源的名字为 nginx-ingress
  namespace: web
spec:
  ingressClassName: nginx # 使用nginx
  rules:
  - host: nginx.wezzer.com # 访问此内容的域名
    http:
      paths:
      - backend:
          service:
            name: svc-discuz # 对应nginx的服务名字,该规则的namespace必须与service的一致
            port:
              number: 80 # 访问的端口
        path: / # 匹配规则
        pathType: Prefix # 匹配类型,这里为前缀匹配
  - host: tomcat.wezzer.com # 访问此内容的域名
    http:
      paths:
      - backend:
          service:
            name: svc-tomcat # 对应nginx的服务名字,该规则的namespace必须与service的一致
            port:
              number: 8080 # 访问的端口
        path: / # 匹配规则
        pathType: Prefix # 匹配类型,这里为前缀匹配

修改hosts文件

结果

持久化部署(pvc)

确保每台主机下载 nfs-utils

1、共享目录文件

复制代码
vim /etc/exports

2、mysql 可持久化

2.1、生成pv对应 共享目录

复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
 name: mysql-master
spec:
 capacity:
  storage: 10Gi
 accessModes: ["ReadWriteMany"]
 nfs:
  path: /data/mysql/master
  server: 192.168.11.20
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: mysql-slave
spec:
 capacity:
  storage: 10Gi
 accessModes: ["ReadWriteMany"]
 nfs:
  path: /data/mysql/slave
  server: 192.168.11.20

2.2、生成对应pvc 对应 pv

复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: mysql-master-pvc
 namespace: mysql
spec:
 accessModes: ["ReadWriteMany"]
 resources:
   requests:
     storage: 8Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: mysql-slave-pvc
 namespace: mysql
spec:
 accessModes: ["ReadWriteMany"]
 resources:
   requests:
     storage: 8Gi

2.3、修改配置文文件 对应 pvc

mysql启动时会查看 /var/lib/mysql/ 文件 ,如果是空,则进行初始化操作,如果有这继承该文件内容

master
slave
更新
结果

3、redis 持久化

3.1、添加pv 对应 共享目录

复制代码
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: redis-master
spec:
 capacity:
  storage: 10Gi
 accessModes: ["ReadWriteMany"]
 nfs:
  path: /data/redis/master
  server: 192.168.11.20

---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: redis-slave
spec:
 capacity:
  storage: 10Gi
 accessModes: ["ReadWriteMany"]
 nfs:
  path: /data/redis/slave
  server: 192.168.11.20

3.2、添加pvc 对应pv

复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: redis-master-pvc
 namespace: redis
spec:
 accessModes: ["ReadWriteMany"]
 resources:
   requests:
     storage: 8Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: redis-slave-pvc
 namespace: redis
spec:
 accessModes: ["ReadWriteMany"]
 resources:
   requests:
     storage: 8Gi

3.3、修改配置文件 对应 pvc

master
slave
更新
结果

4、web-discuz 持久化

4.1、添加pv 对应 共享目录

复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
 name: nginx-discuz
spec:
 capacity:
  storage: 10Gi
 accessModes: ["ReadWriteMany"]
 nfs:
  path: /data/discuz
  server: 192.168.11.20

4.2、添加pvc 对应 pv

复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: discuz-pvc
 namespace: web
spec:
 accessModes: ["ReadWriteMany"]
 resources:
   requests:
     storage: 8Gi

4.3、再共享目录中添加对应文件

复制代码
chown -R 100:101 *

4.4、修改配置文件 对应 pvc

spec.template.spec 下的 containers 添加 volumeMounts

spec.template.spec(与 containers 同级)中添加 volumes 部分

4.5、访问

4.6、验证持久化

将discuz论坛部署后

添加新用户

删除 nginx的pod
删除 mysql的pod

删除redis 的pod

5、tomcat 持久化

5.1、添加 pv 对应 共享目录

复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
 name: tomcat-shangcheng
spec:
 capacity:
  storage: 10Gi
 accessModes: ["ReadWriteMany"]
 nfs:
  path: /data/tomcat
  server: 192.168.11.20

5.2、添加pvc 对应 pv

复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: tomcat-pvc
 namespace: web
spec:
 accessModes: ["ReadWriteMany"]
 resources:
   requests:
     storage: 8Gi

5.3、修改配置文件 对应 pvc

复制代码
        volumeMounts:
        - name: tomcat-data
          mountPath: /usr/local/tomcat/webapps
      volumes:
      - name: tomcat-data
        persistentVolumeClaim:
          claimName: tomcat-pvc

5.4、访问文件修改

结果

访问

(访问失败,可以删除tomcatpod尝试)