当前位置: 首页 > news >正文

k8s-容器化部署论坛和商城服务(小白的“升级打怪”成长之路)

目录

一、配置文件编写

1、mysql主从复制

2、php解析环境

3、nginx服务

4、redis主从复制

5、tomcat服务

6、操作命令

7、在每个node节点操作上

8、更改服务文件加入redis缓存和实现访问动静分离

9、更改商城应用文件

二、实现域名访问

1、配置ingress规则

2、在wondows主机上更改hosts文件

3、网站访问


操作前准备:安装好k8s集群、安装好ingress服务

设计思路:

1、通过ingress规则实现自定义域名访问nginx,经php解析,访问到redis再到mysql

2、通过ingress规则实现自定义域名访问tomcat,访问到mysql

注意:

1、拉取镜像网络不好容器拉去失败,建议在网络好的地方操作

2、在windos主机上编写hosts文件时,要把hosts文件拉到桌面改,改完再拉回来,不然很可能电脑不会重新读取文件导致失败

一、配置文件编写

1、mysql主从复制

vim mysql-m-s/mysql-secrets.yaml

# 定义K8s Secret,存储MySQL敏感密码(base64编码)
apiVersion: v1
kind: Secret
metadata:name: mysql-secrets  # Secret名称,供其他资源引用
type: Opaque  # 通用类型,存储任意键值对
data:# 密码需先base64编码(示例原密码:123.com → 编码后:MTIzLmNvbQ==)root-password: MTIzLmNvbQ==          # MySQL root用户密码replication-password: cmVwbDEyMw==   # 主从复制用户(repl)密码rep123

vim mysql-m-s/mysql-configmap.yaml

# 定义K8s ConfigMap,存储非敏感配置(配置文件、脚本)
apiVersion: v1
kind: ConfigMap
metadata:name: mysql-config  # ConfigMap名称,供Pod引用
data:# --------------------------# 主库核心配置# --------------------------master.cnf: |[mysqld]server-id=1               # 主库唯一ID(必须≠从库)log_bin=mysql-bin         # 开启二进制日志(主从复制依赖)skip-host-cache           # 禁用主机缓存(减少DNS依赖)skip-name-resolve         # 禁用域名解析(加速连接)default_authentication_plugin=mysql_native_password  # 解决认证插件兼容问题
​# --------------------------# 从库核心配置# --------------------------slave.cnf: |[mysqld]server-id=2               # 从库唯一ID(必须≠主库)relay_log=mysql-relay-bin # 开启中继日志(存储主库同步的日志)log_bin=mysql-bin         # 开启二进制日志(支持级联复制)read_only=1               # 从库设为只读(root用户除外)skip-host-cacheskip-name-resolve
​# --------------------------# 主库初始化脚本(容器启动时执行)# --------------------------init-master.sh: |#!/bin/bashset -e  # 脚本出错立即退出
​# 等待MySQL服务启动(避免脚本先于数据库执行)until mysqladmin ping -h localhost --silent; doecho "等待主库MySQL启动..."sleep 2done
​# 1. 创建复制用户repl(从库用该用户连接主库)mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE USER IF NOT EXISTS 'repl'@'%' IDENTIFIED BY '$REPLICATION_PASSWORD';"# 2. 授予复制权限(仅允许同步操作)mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';"# 3. 创建额外数据库mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE DATABASE IF NOT EXISTS discuz;"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE DATABASE IF NOT EXISTS biyesheji;"# 4. 创建额外用户和权限mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE USER IF NOT EXISTS 'discuz_user'@'%' IDENTIFIED BY '123.com';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'%';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "DROP USER IF EXISTS 'root'@'%';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '123.com';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "FLUSH PRIVILEGES;"  # 刷新权限
​# 记录主库日志状态(供从库同步起点使用)mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SHOW MASTER STATUS\G" > /var/lib/mysql/master-status.txt
​# --------------------------# 从库初始化脚本(容器启动时执行)# --------------------------init-slave.sh: |  # 修正缩进:与init-master.sh保持同级(属于data的子项)#!/bin/bashset -e# 等待从库自身MySQL启动until mysqladmin ping -h localhost --silent; doecho "等待从库MySQL启动..."sleep 2done
​# 等待主库服务就绪(增加超时机制,避免无限等待)timeout=120elapsed=0until mysqladmin ping -h mysql-master --silent -u root -p"$MYSQL_ROOT_PASSWORD"; doecho "等待主库就绪...(已等待 $elapsed 秒)"sleep 2elapsed=$((elapsed + 2))if [ $elapsed -ge $timeout ]; thenecho "ERROR: 主库超时未就绪!"exit 1fidone
​# 1. 从主库获取同步起点(增加重试,确保日志位置有效)retry=3while [ $retry -gt 0 ]; doMASTER_STATUS=$(mysql -u root -p"$MYSQL_ROOT_PASSWORD" -h mysql-master -e "SHOW MASTER STATUS\G")MASTER_LOG_FILE=$(echo "$MASTER_STATUS" | grep 'File:' | awk '{print $2}')MASTER_LOG_POS=$(echo "$MASTER_STATUS" | grep 'Position:' | awk '{print $2}')if [ -n "$MASTER_LOG_FILE" ] && [ "$MASTER_LOG_POS" -gt 0 ]; thenbreak  # 日志位置有效,退出重试fiecho "重试获取主库日志位置...(剩余 $retry 次)"retry=$((retry - 1))sleep 5done
​# 2. 配置从库同步参数mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "STOP SLAVE;"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CHANGE MASTER TOMASTER_HOST='mysql-master',MASTER_USER='repl',MASTER_PASSWORD='$REPLICATION_PASSWORD',MASTER_LOG_FILE='$MASTER_LOG_FILE',MASTER_LOG_POS=$MASTER_LOG_POS;"# 3. 创建额外数据库mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE DATABASE IF NOT EXISTS discuz;"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE DATABASE IF NOT EXISTS biyesheji;"# 4. 创建额外用户和权限mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE USER IF NOT EXISTS 'discuz_user'@'%' IDENTIFIED BY '123.com';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'%';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "DROP USER IF EXISTS 'root'@'%';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '123.com';"mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;"
​
​# 5. 启动同步并验证状态(核心新增:确保启动成功)mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "START SLAVE;"if ! mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SHOW SLAVE STATUS\G" | grep -q "Slave_IO_Running: Yes"; thenecho "ERROR: 从库IO线程启动失败!"exit 1fi
[root@k8s

vim mysql-m-s/mysql-master.yaml

# --------------------------
# 主库Pod定义
# --------------------------
apiVersion: v1
kind: Pod
metadata:name: mysql-master  # 主库Pod名称labels:app: mysql        # 应用标签(用于Service关联)role: master      # 角色标签(区分主从)
spec:containers:- name: mysqlimage: mysql:8.0  # 基础镜像(MySQL 8.0)ports:- containerPort: 3306  # 容器内MySQL端口env:# 从Secret获取root密码(引用mysql-secrets中的key)- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretskey: root-password# 从Secret获取复制密码- name: REPLICATION_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretskey: replication-passwordvolumeMounts:# 挂载主库配置文件(从ConfigMap获取)- name: master-configmountPath: /etc/mysql/conf.d/master.cnf  # MySQL默认配置目录subPath: master.cnf  # 只挂载ConfigMap中的master.cnf(避免覆盖其他文件)# 挂载主库初始化脚本(从ConfigMap获取)- name: init-scriptsmountPath: /docker-entrypoint-initdb.d/init-master.sh  # MySQL初始化脚本目录subPath: init-master.sh# 挂载数据目录(持久化MySQL数据)- name: master-datamountPath: /var/lib/mysql  # MySQL数据存储路径# 健康检查(确保主库存活)livenessProbe:exec:# 执行mysqladmin ping检查服务是否可用command: ["mysqladmin", "ping", "-u", "root", "-p$(MYSQL_ROOT_PASSWORD)"]initialDelaySeconds: 30  # 启动后30秒再开始检查(给数据库启动时间)periodSeconds: 10        # 每10秒检查一次
​# 定义Pod使用的卷volumes:# 引用ConfigMap中的主库配置- name: master-configconfigMap:name: mysql-config# 引用ConfigMap中的初始化脚本(设置权限为0755,确保可执行)- name: init-scriptsconfigMap:name: mysql-configdefaultMode: 0755# 主库数据卷(emptyDir仅临时存储,生产环境需替换为PersistentVolume)- name: master-dataemptyDir: {}
​
---
# --------------------------
# 主库Service(提供稳定访问地址)
# --------------------------
apiVersion: v1
kind: Service
metadata:name: mysql-master  # 主库Service名称(从库通过此名称访问主库)
spec:selector:app: mysqlrole: master  # 关联标签为app=mysql、role=master的Pod(即主库Pod)ports:- port: 3306        # Service暴露的端口targetPort: 3306  # 转发到Pod的端口(与容器内MySQL端口一致)

vim mysql-m-s/mysql-slave.yaml

# --------------------------
# 从库Pod定义(核心优化:确保init-slave.sh自动执行+主从复制配置生效)
# 基于原有模板修改,保留Secret管理敏感密码的安全设计,补充脚本执行关键配置
# --------------------------
apiVersion: v1
kind: Pod
metadata:name: mysql-slave   # 从库Pod唯一名称,用于kubectl命令操作(如exec、logs)labels:app: mysql        # 业务标签,与后续Service的selector匹配role: slave       # 角色标签,明确区分主库/从库,便于批量管理(如筛选所有从库Pod)
spec:containers:- name: mysql       # 容器名称,唯一标识Pod内的MySQL进程image: mysql:8.0  # 使用MySQL 8.0镜像,必须与主库镜像版本一致(避免主从版本兼容问题)ports:- containerPort: 3306  # 容器内部MySQL服务端口(默认3306,与MySQL默认端口保持一致)env:  # 环境变量配置(敏感密码从Secret读取,符合K8s安全最佳实践,避免明文暴露)# 1. 从库root初始密码:需与主库root初始密码完全一致(主库后续修改密码会同步到从库)- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secrets  # 引用的Secret名称(需提前通过kubectl create secret创建)key: root-password   # Secret中存储root密码的key(需与Secret定义的key匹配)# 2. 复制用户repl的密码:必须与主库ConfigMap中init-master.sh配置的REPLICATION_PASSWORD一致# (从库通过repl用户连接主库同步数据,密码不匹配会导致同步失败)- name: REPLICATION_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretskey: replication-password  # Secret中存储复制密码的keyvolumeMounts:  # 卷挂载配置:将ConfigMap的配置/脚本、数据卷挂载到容器指定路径# 1. 挂载从库核心配置文件(slave.cnf)- name: slave-configmountPath: /etc/mysql/conf.d/slave.cnf  # MySQL默认加载此目录下的.cnf文件(自动生效)subPath: slave.cnf  # 仅挂载ConfigMap中的slave.cnf文件,避免覆盖目录内其他默认配置# 2. 挂载从库初始化脚本(关键:利用MySQL镜像特性,自动执行/docker-entrypoint-initdb.d下的.sh脚本)- name: init-scriptsmountPath: /docker-entrypoint-initdb.d/init-slave.sh  # 脚本挂载路径(符合MySQL自动执行规则)subPath: init-slave.sh  # 仅挂载ConfigMap中的init-slave.sh脚本,避免干扰其他初始化文件# 3. 挂载从库数据目录(持久化MySQL数据,防止Pod重建后数据丢失)- name: slave-datamountPath: /var/lib/mysql  # MySQL默认数据存储路径(所有表数据、日志均存在此目录)# 健康检查配置(Liveness Probe):确保MySQL服务正常运行,异常时触发Pod重启livenessProbe:exec:# 健康检查命令:通过mysqladmin ping验证MySQL服务可用性(使用环境变量中的root密码)command: ["mysqladmin", "ping", "-u", "root", "-p$(MYSQL_ROOT_PASSWORD)"]initialDelaySeconds: 30  # 容器启动后延迟30秒再检查(给MySQL足够的启动时间,避免误判)periodSeconds: 10        # 健康检查间隔:每10秒检查一次
​volumes:  # 定义Pod需挂载的卷(关联ConfigMap、数据存储)# 1. 从ConfigMap挂载从库配置文件(slave.cnf)- name: slave-configconfigMap:name: mysql-config  # 关联之前定义的ConfigMap名称(需确保ConfigMap已创建)# 2. 从ConfigMap挂载初始化脚本(init-slave.sh):关键配置defaultMode确保脚本可执行- name: init-scriptsconfigMap:name: mysql-config  # 关联的ConfigMap名称defaultMode: 0755   # 核心权限配置:赋予脚本rwxr-xr-x权限(Linux可执行权限),否则脚本无法运行# 3. 从库数据卷:注意!当前为emptyDir(临时存储,Pod删除后数据丢失),生产环境需替换为PV/PVC- name: slave-dataemptyDir: {}  # 测试环境临时使用,生产环境替换为下方注释的persistentVolumeClaim配置# 生产环境数据卷配置示例(需提前创建PVC):# persistentVolumeClaim:#   claimName: mysql-slave-pvc  # 关联的PVC名称
​
---
# --------------------------
# 从库Service定义(作用:提供稳定访问入口,供主库/集群内其他服务访问从库)
# --------------------------
apiVersion: v1
kind: Service
metadata:name: mysql-slave  # Service名称:主库脚本中通过此名称访问从库(如-h mysql-slave)
spec:selector:  # 标签选择器:关联到对应的从库Pod(必须与Pod的labels完全匹配)app: mysqlrole: slaveports:- port: 3306          # Service暴露的端口(集群内访问从库的端口)targetPort: 3306    # 映射到Pod的目标端口(与容器的containerPort一致,即MySQL服务端口)type: ClusterIP       # Service类型:默认ClusterIP(仅K8s集群内部可访问,安全可控)# 若需外部访问从库(如运维调试),可临时改为NodePort(生产环境不建议长期暴露):# type: NodePort# nodePort: 30006  # 外部访问端口(需确保NodePort范围在K8s配置的范围内,默认30000-32767)

检查主从复制是否成功

kubectl exec -it mysql-slave -- mysql -u root -p123.com
show slave status\G;

2、php解析环境

vim php/php-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:name: php-config
data:www.conf: |[www]user = nginxgroup = nginxlisten = 0.0.0.0:9000pm = dynamicpm.max_children = 5pm.start_servers = 2pm.min_spare_servers = 1pm.max_spare_servers = 3

vim php/php-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:# Deployment名称name: php-fpm-deployment# 标签用于识别Deploymentlabels:app: php-fpm
spec:# 副本数,根据负载需求调整replicas: 1# 选择器,匹配要管理的Pod标签selector:matchLabels:app: php-fpm# Pod模板定义template:metadata:# Pod标签,需与selector匹配labels:app: php-fpmspec:# 容器定义containers:- name: php-fpm# 基础镜像,使用最新版Alpineimage: alpine:latest# 容器启动命令,在Alpine基础上构建PHP-FPM环境command: ["/bin/sh", "-c"]args:- |# 更新包索引并安装所需PHP组件apk update && apk add \php82 \php82-fpm \php82-mysqli \php82-xml \php82-json \php82-pdo \php82-pdo_mysql \php82-tokenizer \php82-pecl-redis && \# 创建与Nginx匹配的用户和组(ID 101)addgroup -g 101 -S nginx && \adduser -u 101 -S -G nginx nginx && \# 创建符号链接,方便使用php-fpm命令ln -s /usr/sbin/php-fpm82 /usr/bin/php-fpm && \# 创建PHP运行时目录并设置权限mkdir -p /var/run/php && \chown -R nginx:nginx /var/run/php && \# 添加Redis扩展配置echo "extension=redis.so" > /etc/php82/conf.d/redis.ini && \# 以前台模式启动PHP-FPMphp-fpm82 --nodaemonize --force-stderr# 暴露容器端口ports:- containerPort: 9000# 挂载卷配置volumeMounts:- name: php-config-volume  # 卷名称,需与下面volumes定义一致mountPath: /etc/php82/php-fpm.d/www.conf  # 容器内挂载路径subPath: www.conf  # 只挂载ConfigMap中的www.conf文件- name: discuz-volumemountPath: /var/www/html  # 容器内 Discuz 目录路径(对应宿主机目录)# 卷定义volumes:- name: php-config-volumeconfigMap:name: php-config  # 引用前面定义的ConfigMap- name: discuz-volumehostPath:path: /root/project/discuz  # 宿主机上的 Discuz 目录(含文件和子目录)type: Directory  # 必须是已存在的目录(避免自动创建空目录覆盖内容)
---
# Service配置:提供Pod的网络访问入口
apiVersion: v1
kind: Service
metadata:name: php-fpm-service  # 服务名称
spec:selector:app: php-fpm  # 关联标签,指向PHP-FPM的Podports:- port: 9000  # 服务暴露的端口(集群内访问用)targetPort: 9000  # 对应容器的端口type: ClusterIP  # 仅集群内部可访问(默认类型) 

3、nginx服务

vim nginx/nginx-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:name: nginx-config  # ConfigMap名称,在Deployment中会引用此名称
data:# Nginx的默认配置文件内容,与原default.conf保持一致default.conf: |server {listen       80;listen       [::]:80;server_name  localhost;root         /usr/share/nginx/html;index index.php index.html index.htm;# PHP文件处理配置location ~ \.php$ {fastcgi_pass   php-fpm-service:9000;  # 指向PHP服务,需确保在同一网络中fastcgi_index  index.php;fastcgi_param  SCRIPT_FILENAME /var/www/html$fastcgi_script_name;include        fastcgi_params;}}
​

vim nginx/nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx  # Deployment名称
spec:replicas: 1  # 副本数量,可根据需求调整selector:matchLabels:app: nginx  # 选择器标签,匹配Podtemplate:metadata:labels:app: nginx  # Pod标签,与selector一致spec:containers:- name: nginx  # 容器名称image: alpine:latest  # 基础镜像command: ["/bin/sh", "-c"]args:- |#!/bin/shapk add --no-cache nginx;pkill nginx || true;rm -f /etc/nginx/http.d/default.conf;mkdir -p /run/nginx;chown nginx:nginx /run/nginx;chmod 755 /run/nginx;nginx -t;nginx -g "daemon off;";ports:- containerPort: 80  # 容器内部端口volumeMounts:- name: nginx-config-volume  # 引用配置卷mountPath: /etc/nginx/http.d/default.confsubPath: default.conf- name: discuz-volume  # 网站文件卷mountPath: /usr/share/nginx/htmlreadOnly: trueresources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"livenessProbe:httpGet:path: /port: 80initialDelaySeconds: 30periodSeconds: 10failureThreshold: 3readinessProbe:tcpSocket:port: 80initialDelaySeconds: 20periodSeconds: 5volumes:- name: nginx-config-volume  # 配置卷(关联ConfigMap)configMap:name: nginx-configitems:- key: default.confpath: default.conf- name: discuz-volume  # 网站文件卷hostPath:path: /root/project/discuztype: DirectoryOrCreate  # 保留自动创目录,避免路径不存在问题# 1. 最小化修改:删除nodeSelector(解决调度时标签不匹配问题)dnsPolicy: ClusterFirstrestartPolicy: Alwaysstrategy:rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdate
---
apiVersion: v1
kind: Service
metadata:name: nginx-service  # Service名称namespace: default
spec:selector:app: nginx  # 关联Nginx Pod标签ports:- port: 80targetPort: 80nodePort: 30080  # 保留固定NodePort,避免端口变化type: NodePort

4、redis主从复制

vim redis/redis-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:name: redis-config
data:redis.conf: |# 允许所有IP访问(K8s环境需暴露给集群内服务)bind 0.0.0.0       # 关闭保护模式(配合密码保证安全,允许外部连接)protected-mode no  # Redis服务端口(与Deployment容器暴露端口一致)port 6379         # 禁止后台运行(K8s容器需前台启动,否则容器会退出)daemonize no     # Redis数据存储目录(与Deployment数据卷挂载路径一致)dir /data        # Redis访问密码(基础安全验证)requirepass 123456 #允许从节点认证masterauth 123456  
​redis-slave.conf: |bind 0.0.0.0       protected-mode no  port 6379         daemonize no     dir /data        requirepass 123456# 从节点认证密码masterauth 123456  # 指向主节点服务slaveof redis-master 6379  # 从节点只读slave-read-only yes  

vim redis/redis-deployment.yaml

# -------------- 1. 主节点 Deployment --------------
apiVersion: apps/v1
kind: Deployment
metadata:name: redis-master  # 主节点部署名,明确身份
spec:replicas: 1  # 主节点仅1个selector:matchLabels:app: redisrole: master  # 主节点标签,用于Service选择template:metadata:labels:app: redisrole: masterspec:containers:- name: redisimage: redis:7.2-alpine  # 与你原配置镜像一致ports:- containerPort: 6379  # 暴露Redis端口,与配置一致volumeMounts:# 挂载ConfigMap中的主节点配置文件(redis.conf)- name: redis-configmountPath: /etc/redis/redis.conf  # 配置文件路径subPath: redis.conf  # 仅挂载主配置文件,避免覆盖目录# 挂载数据卷(存储Redis数据)- name: redis-datamountPath: /data  # 与配置文件中dir /data一致# 启动Redis,指定加载主节点配置文件command: ["redis-server", "/etc/redis/redis.conf"]volumes:# 关联你已有的ConfigMap(redis-config)- name: redis-configconfigMap:name: redis-config  # 必须与你现有ConfigMap名称一致# 数据卷(测试用emptyDir,生产环境建议改持久化存储如PVC)- name: redis-dataemptyDir: {}
​
---
# -------------- 2. 从节点 Deployment --------------
apiVersion: apps/v1
kind: Deployment
metadata:name: redis-slave  # 从节点部署名,与主节点区分
spec:replicas: 1  # 2个从节点,可根据需求调整数量selector:matchLabels:app: redisrole: slave  # 从节点标签,用于Service选择template:metadata:labels:app: redisrole: slavespec:containers:- name: redisimage: redis:7.2-alpine  # 与主节点镜像一致,避免版本兼容问题ports:- containerPort: 6379volumeMounts:# 挂载ConfigMap中的从节点配置文件(redis-slave.conf)- name: redis-configmountPath: /etc/redis/redis.conf  # 配置文件路径(与主节点保持一致,便于启动命令统一)subPath: redis-slave.conf  # 挂载从节点专属配置文件# 从节点数据卷(每个从节点独立存储)- name: redis-datamountPath: /data# 启动Redis,指定加载从节点配置文件(路径与主节点一致,因subPath已区分配置)command: ["redis-server", "/etc/redis/redis.conf"]volumes:# 同样关联你已有的ConfigMap(无需新增)- name: redis-configconfigMap:name: redis-config# 从节点数据卷(测试用,生产环境改PVC)- name: redis-dataemptyDir: {}
​
---
# -------------- 3. 主节点 Service(供写入操作) --------------
apiVersion: v1
kind: Service
metadata:name: redis-master  # 主节点Service名,与从节点配置中slaveof redis-master 6379完全一致
spec:selector:app: redisrole: master  # 仅选择主节点Podports:- port: 6379targetPort: 6379  # 与容器暴露端口一致type: ClusterIP  # 集群内访问(生产环境若需外部访问,可改NodePort/LoadBalancer)
​
---
# -------------- 4. 从节点 Service(供读取操作) --------------
apiVersion: v1
kind: Service
metadata:name: redis-slave  # 从节点Service名,供客户端读取数据使用
spec:selector:app: redisrole: slave  # 仅选择从节点Podports:- port: 6379targetPort: 6379type: ClusterIP  # 自动负载均衡到所有从节点

5、tomcat服务

vim tomcat/shangcheng-deployment.yaml

# --------------------------
# Tomcat Deployment配置
# 特点:随机分配到Node节点(自动避开Master节点)
# --------------------------
apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat-shangcheng
spec:replicas: 1selector:matchLabels:app: tomcattemplate:metadata:labels:app: tomcatspec:# 【关键修改】删除节点亲和性配置,K8s会自动调度到Node节点# (Master节点因有control-plane污点,默认不调度普通Pod)containers:- name: tomcatimage: tomcat:8ports:- containerPort: 8080volumeMounts:# 挂载宿主机目录(需所有Node节点都有此目录及文件)- name: tomcat-datamountPath: /usr/local/tomcatreadOnly: false# 启动命令(保持不变)command: ["/bin/bash", "-c"]args:- ln -s /usr/local/tomcat/bin/startup.sh /usr/local/bin/tomcat_start;ln -s /usr/local/tomcat/bin/shutdown.sh /usr/local/bin/tomcat_stop;/usr/local/tomcat/bin/startup.sh && tail -f /usr/local/tomcat/logs/catalina.out;volumes:- name: tomcat-datahostPath:path: /root/project/tomcat8  # 所有Node节点必须有此目录及文件type: Directory  # 严格检查目录存在(避免创建空目录)
​
---
# --------------------------
# Tomcat Service配置
# --------------------------
apiVersion: v1
kind: Service
metadata:name: tomcat-shangcheng-svc
spec:selector:app: tomcatports:- port: 8080targetPort: 8080nodePort: 30081  # 使用未占用的端口type: NodePort

6、操作命令

#mysql主从复制
kubectl apply -f mysql-m-s/mysql-secrets.yaml 
kubectl apply -f mysql-m-s/mysql-configmap.yaml 
kubectl apply -f mysql-m-s/mysql-master.yaml
kubectl apply -f mysql-m-s/mysql-slave.yaml 
#php解析环境
kubectl apply -f php/php-configmap.yaml 
kubectl apply -f php/php-deployment.yaml 
#nginx访问
kubectl apply -f nginx/nginx-configmap.yaml 
kubectl apply -f nginx/nginx-deployment.yaml 
#redis缓存
kubectl apply -f redis/redis-configmap.yaml 
kubectl apply -f redis/redis-deployment.yaml 
#tomcat访问
kubectl apply -f tomcat/shangcheng-deployment.yaml 
​
​
#把商城的数据库文件导入库中
cp /root/project//tomcat/tomcat8/webapps/biyesheji/biyesheji.sql /root/project/tomcat
​kubectl exec -i mysql-master -- mysql -u root -p123.com biyesheji < /root/project/tomcat/biyesheji.sql

检查主从复制是否成功

kubectl exec -it mysql-slave -- mysql -u root -p123.com
show slave status\G;

7、在每个node节点操作上

有两个目录文件

/root/project/discuz
​
/root/project/tomcat8

操作

cd /root/project/discuz
chown 101:101 ./ -R

网站访问192.168.58.180:30080

8、更改服务文件加入redis缓存和实现访问动静分离

vim project/discuz/config/config_global.php

#加入从库,实现访问动静分离
​
#修改redis
​
#加入用户redis-master和密码123456

redis查看

 kubectl exec -it redis-master-84d56bd7f-nshzz -- redis-cli -a 123456

9、更改商城应用文件

vim /root/project/tomcat8/webapps/biyesheji/index.jsp

<%--Created by IntelliJ IDEA.User: baiyuhongDate: 2018/10/21Time: 18:43To change this template use File | Settings | File Templates.
--%>
<%response.sendRedirect(request.getContextPath()+"/fore/foreIndex"); //项目启动时,自动跳转到前台首页
%>

vim /root/project/tomcat8/webapps/biyesheji/WEB-INF/classes/jdbc.properties

#修改登陆数据库用户为mysql-master,修改密码为123.com
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://mysql-master:3306/biyesheji?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=true
jdbc.user=root
jdbc.password=123.com

vim /root/project/tomcat8/conf/server.xml

#增加一层,使得访问时后面不需要添加目录biyesheji

网站访问192.168.58.180:30081

二、实现域名访问

1、配置ingress规则

vim IPAddressPool.yaml

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: planip-pool #这里与下面的L2Advertisement的ip池名称需要一样namespace: metallb-system
spec:addresses:
​- 192.168.58.50-192.168.58.60 #自定义ip段

vim L2Advertisement.yaml

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: planip-poolnamespace: metallb-system
spec:ipAddressPools:
​- planip-pool #这里需要跟上面ip池的名称保持一致
​
​

vim ingress-nginx-nodeport.yaml

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

操作命令

kubectl apply -f IPAddressPool.yaml 
kubectl apply -f L2Advertisement.yaml 
kubectl apply -f ingress-nginx-nodeport.yaml 

2、在wondows主机上更改hosts文件

3、网站访问

网站访问www.sc.com

网站访问www.sc.com

看到感觉有帮助的朋友,劳烦动动发财的小手给博主点个赞

http://www.dtcms.com/a/350830.html

相关文章:

  • K8s Pod驱逐机制详解与实战
  • SpringBoot防重放攻击的5种实现方案
  • 什么是数据库?现代数据库类型、示例与应用(2025)
  • 深入理解 iptables:Linux 防火墙从入门到精通
  • Vue3使用 DAG 图(AntV X6)
  • 2024年12月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • Spring Boot 3.5 新特性
  • C++ namespace
  • 国内外大模型体验与评测:洞察智能时代的核心驱动力一、引言
  • DataX HdfsWriter 插件文档
  • 实现自己的AI视频监控系统-第二章-AI分析模块2
  • Java全栈开发面试实战:从基础到微服务的完整技术解析
  • Oracle数据库如何修改字段中的两个字符
  • CF2133C 下界(The Nether)
  • 敏捷价值实证:亚马逊如何用敏捷破解技术项目的“价值迷雾”?
  • 学习做动画3.八方移动
  • SW - 增加导出STL数据中的三角面数,增加别人逆向建模的难度
  • Excel比较两列的值是否相同
  • ViT系列网络系统性分析:从架构创新到未来趋势
  • SSH 反向隧道:快速解决服务器网络限制
  • Frida JavaScript API 总结
  • 【数据库】dbeaver 查询clickhouse,表内时间与真实时间差8小时
  • 基于Springboot + vue3实现的宿舍管理系统
  • [pilot智驾系统] docs | 用户界面状态(UIState)
  • 第十八节:骨骼动画 - 角色动画控制
  • 时间序列异常检测实战:HMM与LSTM方法解析
  • 在华为云服务器上使用Ansible部署LNMP环境【玩转华为云】
  • Ubuntu22.04 解决eth0未托管问题
  • golang 基础类 八股文400题
  • Redis面试精讲 Day 30:Redis面试真题解析与答题技巧