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

k8s三阶段项目

k8s部署discuz论坛和Tomcat商城

一、持久化存储—storageclass+nfs

1.创建sa账户

[root@k8s-master scnfs]# cat nfs-provisioner-rbac.yaml
# 1. ServiceAccount:供 NFS Provisioner 使用的服务账号
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-provisionernamespace: default  # 所有资源统一在 default 命名空间,可按需修改---
# 2. ClusterRole:集群级权限,覆盖动态 PV 供应核心操作(PV/PVC/StorageClass 等)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: nfs-provisioner-clusterrole
rules:# 操作 PV(创建/删除/查询)- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]# 操作 PVC(查询/更新状态)- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]# 操作 StorageClass(查询可用的 SC)- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]# 发送事件(如 PV 创建成功/失败的通知)- apiGroups: [""]resources: ["events"]verbs: ["create", "update", "patch"]# 操作 Services/Endpoints(领导者选举依赖,部分版本需)- apiGroups: [""]resources: ["services", "endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]---
# 3. ClusterRoleBinding:将集群级权限绑定到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: nfs-provisioner-clusterrolebinding
subjects:- kind: ServiceAccountname: nfs-provisionernamespace: default  # 必须与 ServiceAccount 所在命名空间一致
roleRef:kind: ClusterRolename: nfs-provisioner-clusterroleapiGroup: rbac.authorization.k8s.io---
# 4. Role:命名空间级权限,专门覆盖领导者选举的 leases/endpoints 操作
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: nfs-provisioner-rolenamespace: default  # 与 Provisioner 同命名空间,确保选举权限生效
rules:- apiGroups: [""]resources: ["endpoints", "leases"]  # 领导者选举核心依赖资源verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]---
# 5. RoleBinding:将命名空间级选举权限绑定到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: nfs-provisioner-rolebindingnamespace: default
subjects:- kind: ServiceAccountname: nfs-provisionernamespace: default
roleRef:kind: Rolename: nfs-provisioner-roleapiGroup: rbac.authorization.k8s.io

2.创建制备器

[root@k8s-master scnfs]# cat nfs-provisioner-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: nfs-provisionernamespace: defaultlabels:app: nfs-provisioner
spec:replicas: 1  # 测试环境单副本,生产环境建议用 StatefulSet 多副本selector:matchLabels:app: nfs-provisionertemplate:metadata:labels:app: nfs-provisionerspec:serviceAccountName: nfs-provisioner  # 关联前面创建的 ServiceAccountcontainers:- name: nfs-provisioner# 国内阿里云镜像,稳定可拉取(替代 k8s.gcr.io)image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/nfs-subdir-external-provisioner:v4.0.2# 环境变量:核心配置(必须与 StorageClass 的 provisioner 一致)env:- name: PROVISIONER_NAMEvalue: cluster.local/nfs-provisioner  # 供应器名称,后续 SC 需引用此值- name: NFS_SERVERvalue: 192.168.157.110  # 已部署的 NFS 服务器 IP- name: NFS_PATHvalue: /nfs  # 已配置的 NFS 共享目录# 挂载 NFS 共享目录到容器内(固定路径,Provisioner 在此创建 PV 子目录)volumeMounts:- name: nfs-volumemountPath: /persistentvolumes# 定义 NFS 卷(关联 NFS 服务器信息)volumes:- name: nfs-volumenfs:server: 192.168.157.110path: /nfs

3.创建storageclass

[root@k8s-master scnfs]# cat nfs-storageclass.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-sc  # StorageClass 名称,PVC 需引用此名称
provisioner: cluster.local/nfs-provisioner  # 必须与 Provisioner 的 PROVISIONER_NAME 完全一致
parameters:archiveOnDelete: "true"  # 删除 PVC 时,归档 NFS 数据(避免误删,生产建议 true)
reclaimPolicy: Delete  # PV 回收策略:Delete(删 PVC 自动删 PV/数据)/ Retain(保留数据)
allowVolumeExpansion: true  # 允许 PVC 扩容(v4.0+ 版本支持)
volumeBindingMode: Immediate  # 立即绑定 PVC(无需等待 Pod 调度)

4.检验

[root@k8s-master scnfs]# kubectl get sa
NAME              SECRETS   AGE
default           0         32h
nfs-provisioner   0         38m
[root@k8s-master scnfs]# kubectl get sc
NAME     PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-sc   cluster.local/nfs-provisioner   Delete          Immediate           true                   39m
[root@k8s-master scnfs]# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nfs-provisioner-745557fd5c-dslzv   1/1     Running   0          39m

二、部署MySQL主从

1.创建secret存储密码

[root@k8s-master mysql]# cat secret.yaml apiVersion: v1
kind: Secret                  # 资源类型:Secret(密钥)
metadata:name: mysql-secrets         # Secret名称:标识为"mysql-secrets"namespace: mysql            # 命名空间:属于mysql命名空间
type: Opaque                  # 密钥类型:Opaque(通用密钥类型)
data:                         # 密钥数据(Base64编码)root-password: MTIzLmNvbQ==  # 键名:root-password(MySQL root密码)# 解码后:123.com

2.配置文件

[root@k8s-master mysql]# cat configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:name: mysql-confignamespace: mysql
data:master.cnf: |[mysqld]server-id=10log_bin=/var/lib/mysql/mysql-bin.logread_only=0bind-address=0.0.0.0gtid_mode=ONenforce_gtid_consistency=ONdefault_authentication_plugin=mysql_native_passwordslave1.cnf: |[mysqld]server-id=20relay_log=/var/lib/mysql/mysql-relay-bin.loglog_bin=/var/lib/mysql/mysql-bin.logread_only=1bind-address=0.0.0.0gtid_mode=ONenforce_gtid_consistency=ONdefault_authentication_plugin=mysql_native_password

3.初始化

[root@k8s-master mysql]# cat init-scripts.yaml 
apiVersion: v1
kind: ConfigMap                  # 资源类型:ConfigMap(配置映射)
metadata:name: mysql-init-scripts        # ConfigMap名称:MySQL初始化脚本namespace: mysql                # 命名空间:属于mysql命名空间
data:                             # 数据字段:存储初始化SQL脚本master-init.sql: |              # 主节点初始化SQL脚本# 从环境变量获取密码(避免明文)CREATE USER IF NOT EXISTS 'rsyncuser'@'%' IDENTIFIED BY '123.com';  # 创建复制用户GRANT REPLICATION SLAVE ON *.* TO 'rsyncuser'@'%';                 # 授予复制权限CREATE DATABASE IF NOT EXISTS discuz;                              # 创建discuz数据库CREATE USER IF NOT EXISTS 'discuz'@'%' IDENTIFIED BY '123.com';     # 创建discuz用户GRANT ALL PRIVILEGES ON discuz.* TO 'discuz'@'%';                   # 授予discuz库全权限CREATE DATABASE IF NOT EXISTS biyesheji;                            # 创建毕业设计数据库CREATE USER IF NOT EXISTS 'tomcat'@'%' IDENTIFIED BY '123.com';      # 创建tomcat用户GRANT ALL PRIVILEGES ON biyesheji.* TO 'tomcat'@'%';                # 授予毕业设计库全权限FLUSH PRIVILEGES;                                                  # 刷新权限生效slave-init.sql: |                   # 从节点初始化SQL脚本CHANGE MASTER TOMASTER_HOST = 'mysql-master-0.mysql-master.mysql.svc.cluster.local',  # 主节点地址MASTER_PORT = 3306,                   # MySQL端口MASTER_USER = 'rsyncuser',            # 复制用户名MASTER_PASSWORD = '123.com',          # 复制用户密码MASTER_AUTO_POSITION = 1;             # 启用GTID自动定位START SLAVE;                            # 启动主从复制

4.主库statefulset+headless

[root@k8s-master mysql]# cat master.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysql-masternamespace: mysql
spec:serviceName: mysql-masterreplicas: 1selector:matchLabels:app: mysql-mastertemplate:metadata:labels:app: mysql-masterspec:containers:- name: mysqlimage: mysql:8.0ports:- containerPort: 3306env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretskey: root-passwordvolumeMounts:- name: mysql-configmountPath: /etc/mysql/conf.d/master.cnfsubPath: master.cnf- name: master-init-script  # 仅挂载主库脚本mountPath: /docker-entrypoint-initdb.d/master-init.sqlsubPath: master-init.sql  # 明确指定脚本名volumes:- name: mysql-configconfigMap:name: mysql-configitems:- key: master.cnfpath: master.cnf- name: master-init-script  # 关联 ConfigMap 中的主库脚本configMap:name: mysql-init-scriptsitems:- key: master-init.sqlpath: master-init.sql# 添加 volumeClaimTemplatesvolumeClaimTemplates:- metadata:name: mysql-dataspec:accessModes: [ "ReadWriteOnce" ]storageClassName: "nfs-sc"  # 使用之前创建的 StorageClassresources:requests:storage: 10Gi  # 根据需求调整大小
---
apiVersion: v1
kind: Service
metadata:name: mysql-masternamespace: mysql
spec:ports:- port: 3306name: mysqlclusterIP: Noneselector:app: mysql-master

5.从库

[root@k8s-master mysql]# cat slave.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysql-slavenamespace: mysql
spec:serviceName: mysql-slavereplicas: 1  selector:matchLabels:app: mysql-slavetemplate:metadata:labels:app: mysql-slavespec:containers:- name: mysqlimage: mysql:8.0ports:- containerPort: 3306env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretskey: root-passwordvolumeMounts:- name: mysql-configmountPath: /etc/mysql/conf.d/slave.cnfsubPath: slave1.cnf- name: init-scriptmountPath: /docker-entrypoint-initdb.dvolumes:- name: mysql-configconfigMap:name: mysql-configitems:- key: slave1.cnfpath: slave1.cnf- name: init-scriptconfigMap:name: mysql-init-scriptsvolumeClaimTemplates:- metadata:name: mysql-dataspec:accessModes: [ "ReadWriteOnce" ]storageClassName: "nfs-sc"resources:requests:storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:name: mysql-slavenamespace: mysql
spec:ports:- port: 3306name: mysqlclusterIP: Noneselector:app: mysql-slave

6.检测

###pod正常创建
[root@k8s-master nginx]# kubectl -n mysql get pod
NAME             READY   STATUS    RESTARTS   AGE
mysql-master-0   1/1     Running   0          11h
mysql-slave-0    1/1     Running   0          11h
### svc创建
[root@k8s-master nginx]# kubectl -n mysql get svc
NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
mysql-master   ClusterIP   None         <none>        3306/TCP   12h
mysql-slave    ClusterIP   None         <none>        3306/TCP   12h
###pvc 动态创建
[root@k8s-master nginx]# kubectl -n mysql get pvc
NAME                        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-data-mysql-master-0   Bound    pvc-26c64423-bdc7-4687-9cfc-9b3ac3375e9f   10Gi       RWO            nfs-sc         11h
mysql-data-mysql-slave-0    Bound    pvc-153c4aaa-d48f-4526-a290-381f62d421d4   10Gi       RWO            nfs-sc         11h
###pv动态创建
[root@k8s-master nginx]# kubectl -n mysql get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS   REASON   AGE
pvc-153c4aaa-d48f-4526-a290-381f62d421d4   10Gi       RWO            Delete           Bound    mysql/mysql-data-mysql-slave-0    nfs-sc                  11h
pvc-26c64423-bdc7-4687-9cfc-9b3ac3375e9f   10Gi       RWO            Delete           Bound    mysql/mysql-data-mysql-master-0   nfs-sc                  11h

检测主从

[root@k8s-master nginx]# kubectl -n mysql exec -it mysql-slave-0 -- /bin/bash
bash-5.1# mysql -uroot -p123.com
mysql> show slave status\G;
......Slave_IO_Running: YesSlave_SQL_Running: Yes
.....
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| biyesheji          |
| discuz             |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.01 sec)

三、Redis主从

1.创建命名空间

[root@k8s-master redis]# cat namespace.yaml apiVersion: v1
kind: Namespace
metadata:name: redis
[root@k8s-maste

2.创建configmap

[root@k8s-master redis]# cat redis-configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:name: redis-confignamespace: redis
data:redis-master.conf: |port 6379bind 0.0.0.0protected-mode nodaemonize notimeout 0save ""appendonly nomaxmemory 1gbmaxmemory-policy allkeys-lruredis-slave.conf: |port 6379bind 0.0.0.0protected-mode nodaemonize notimeout 0save ""appendonly nomaxmemory 1gbmaxmemory-policy allkeys-lruslaveof redis-master-0.redis-master.redis.svc.cluster.local 6379slave-read-only yes

3.Redis主库

[root@k8s-master redis]# cat redis-master.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:name: redis-master        # StatefulSet名称namespace: redis          # 所属命名空间
spec:serviceName: redis-master # 关联的Headless Service名称replicas: 1               # 副本数(主节点通常为1)selector:                 # Pod选择器matchLabels:app: redis-mastertemplate:                 # Pod模板metadata:labels:app: redis-master   # Pod标签(需与selector匹配)spec:containers:- name: redis-master  # 容器名称image: redis:6-alpine  # 使用Alpine版Redis镜像command: ["redis-server", "/etc/redis/redis-master.conf"]  # 启动命令ports:- containerPort: 6379  # Redis默认端口volumeMounts:- name: redis-config   # 挂载配置卷mountPath: /etc/redis  # 容器内挂载路径volumes:- name: redis-config     # 卷定义configMap:name: redis-config   # 引用名为redis-config的ConfigMap
---
apiVersion: v1
kind: Service
metadata:name: redis-masternamespace: redis
spec:clusterIP: Noneselector:app: redis-masterports:- port: 6379targetPort: 6379

4…redis从库

[root@k8s-master redis]# cat redis-slave.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:name: redis-slave           # 有状态应用名称namespace: redis            # 指定命名空间
spec:serviceName: redis-slave   # 关联的Headless Service名称replicas: 1                 # 副本数量(主节点通常为1)selector:                   # Pod选择器matchLabels:app: redis-slavetemplate:                   # Pod模板metadata:labels:app: redis-slave     # Pod标签(必须与selector匹配)spec:containers:- name: redis-slave    # 容器名称image: redis:6-alpine # 使用Alpine轻量版Redis镜像command: ["redis-server", "/etc/redis/redis-master.conf"] # 启动命令ports:- containerPort: 6379  # Redis默认端口volumeMounts:- name: redis-config   # 配置卷名称mountPath: /etc/redis # 容器内挂载路径volumes:                # 存储卷定义- name: redis-configconfigMap:            # 使用ConfigMap作为配置源name: redis-config  # 引用的ConfigMap名称
---
apiVersion: v1
kind: Service
metadata:name: redis-slavenamespace: redis
spec:clusterIP: Noneselector:app: redis-slaveports:- port: 6379

5.检测

[root@k8s-master nginx]# kubectl -n redis get pod
NAME             READY   STATUS    RESTARTS   AGE
redis-master-0   1/1     Running   0          12h
redis-slave-0    1/1     Running   0          12h
[root@k8s-master nginx]# kubectl -n redis get svc
NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
redis-master   ClusterIP   None         <none>        6379/TCP   12h
redis-slave    ClusterIP   None         <none>        6379/TCP   12h
[root@k8s-master nginx]# kubectl -n redis get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS   REASON   AGE
pvc-153c4aaa-d48f-4526-a290-381f62d421d4   10Gi       RWO            Delete           Bound    mysql/mysql-data-mysql-slave-0    nfs-sc                  11h
pvc-26c64423-bdc7-4687-9cfc-9b3ac3375e9f   10Gi       RWO            Delete           Bound    mysql/mysql-data-mysql-master-0   nfs-sc                  11h

四、构建镜像

1.nginx-php-discuz

[root@k8s-master nginx]# ls
discuz  discuz.conf  discuz.yaml  Dockerfile  proj-nginx:latest  www.conf

nginx配置文件

[root@k8s-master nginx]# cat discuz.conf 
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配置文件

[root@k8s-master nginx]# cat www.conf 
[www]
user = nginx
group = nginx
listen = /run/php/php83-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3php_admin_value[error_log] = /var/log/php83/www-error.log
php_admin_flag[log_errors] = on

Dockerfile

[root@k8s-master nginx]# cat 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;'"]

生成镜像

 docker build -t nginx:v1 .
####运行镜像
[root@k8s-master nginx]# docker run -itd nginx:v1
a902b31a6fe65fe5e7db02c68ec073407f85142fceaab1ce89be9be21fd03efc

编写测试文件

#### index.html info.php mysql.php redis.php/var/www/html # cat index.html 
nginx
/var/www/html # cat info.php 
<?phpphpinfo();
?>
/var/www/html # cat mysql.php 
<?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;
?>
/var/www/html # cat redis.php 
<?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();
}
/var/www/html # exit[root@k8s-master nginx]# ls
discuz.conf  Dockerfile  www.conf

导入discuz安装包

[root@k8s-master nginx]# mkdir discuz
[root@k8s-master nginx]# ls
discuz  discuz.conf  Dockerfile  www.conf
[root@k8s-master nginx]# cd discuz/
[root@k8s-master discuz]# ls
[root@k8s-master discuz]# rz
rz waiting to receive.**[root@k8s-master discuz]# 
[root@k8s-master discuz]# 
[root@k8s-master discuz]# ls
Discuz_X3.5_SC_UTF8_20250205.zip
[root@k8s-master discuz]# unzip Discuz_X3.5_SC_UTF8_20250205.zip [root@k8s-master discuz]# ls
Discuz_X3.5_SC_UTF8_20250205.zip  LICENSE  qqqun.png  readme  readme.html  upload  utility.html
[root@k8s-master discuz]# rm -rf Discuz_X3.5_SC_UTF8_20250205.zip 

把安装包拷到容器中

[root@k8s-master discuz]# docker cp ./ a902b31a6fe6:/var/www/html
Successfully copied 34.8MB to a902b31a6fe6:/var/www/html
[root@k8s-master discuz]# docker exec -it a902 /bin/sh
/ # cd /var/www/html
/var/www/html # ls
LICENSE       info.php      qqqun.png     readme.html   upload
index.html    mysql.php     readme        redis.php     utility.html
/var/www/html # cd ..
/var/www # chown -R nginx:nginx html/
/var/www # cd html
/var/www/html # ls -l

修改discuz配置文件

/var/www/html/upload # cd config/
/var/www/html/upload/config # ls
config_global_default.php   config_ucenter_default.php  index.htm
/var/www/html/upload/config # vim config_global_default.php 

修改后

在这里插入图片描述

主库

在这里插入图片描述

从库
在这里插入图片描述

redis
在这里插入图片描述

/var/www/html/upload/config # vim config_ucenter_default.php

在这里插入图片描述

导出镜像 分发至各node节点

[root@k8s-master nginx]# docker commit a902b31a6fe6 pro-nginx:latest
sha256:a4bf8e59acf9a819bb4a2ea875eb1ba6e11fc2d868213d076322b10340f294a0
[root@k8s-master nginx]# docker save proj-nginx:latest -o pro-nginx.tar
[root@k8s-master nginx]# ls
discuz  discuz.conf  Dockerfile  luo-nginx.tar  www.conf
[root@k8s-master nginx]# scp pro-nginx.tar 192.168.158.34:/root/Authorized users only. All activities may be monitored and reported.
luo-nginx.tar                                                                                    100%  123MB 330.6MB/s   00:00    
[root@k8s-master nginx]# scp pro-nginx.tar 192.168.158.35:/root/Authorized users only. All activities may be monitored and reported.
luo-nginx.tar                                                                                    100%  123MB 344.9MB/s   00:00 

2.tomcat

[root@k8s-master tomcat]# ls
Dockerfile  shop  tomcat.yaml

下载镜像

docker pull tomcat:8

将 war 包放到shangcheng目录下

[root@k8s-master tomcat]# cd shop/
[root@k8s-master shangcheng]# ls
[root@k8s-master shangcheng]# rz
rz waiting to receive.**[root@k8s-master shangcheng]# 
[root@k8s-master shangcheng]# ls
ROOT.war

生成测试镜像

[root@k8s-master shangcheng]# docker run -itd --name tomcat -v /root/project/tomcat/shop/:/usr/local/tomcat/webapps/  --restart=always tomcat:8
1adaadb8d33f77f4ca31bfb438471a6328c35ec4105aecdd88a71330896bca5c
###war包自动解压
[root@k8s-master shop]# ls
ROOT  ROOT.war

修改tomcat配置文件

####由于在测试容器中war包已经解压 ### 直接在本地改就行不用进入容器再改
[root@k8s-master classes]# pwd
/root/project/tomcat/shop/ROOT/WEB-INF/classes
#####添加MySQL svc域名地址 数据库名字 密码
[root@k8s-master classes]# vim jdbc.properties 
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://mysql-master-0.mysql-master.mysql.svc.cluster.local:3306/biyesheji?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=true
jdbc.user=tomcat
jdbc.password=123.com

编写Dockerfile文件

[root@k8s-master tomcat]# vim Dockerfile 
FROM tomcat:8COPY shop/ /usr/local/tomcat/webapps/EXPOSE 8080CMD ["catalina.sh", "run"]

构建镜像

[root@k8s-master tomcat]# docker build -t pro-tomcat:latest .

分发至各个节点

[root@k8s-master tomcat]# docker save pro-tomcat:latest -o pro-tomcat.tar
[root@k8s-master tomcat]# scp pro-tomcat.tar 192.168.157.101:/rootAuthorized users only. All activities may be monitored and reported.
pro-tomcat.tar                                                                                        100%  481MB 105.1MB/s   00:04    
[root@k8s-master tomcat]# scp pro-tomcat.tar 192.168.157.102:/rootAuthorized users only. All activities may be monitored and reported.
pro-tomcat.tar 

五、k8s部署

放在同一命名空间

1.tomcat-shop

[root@k8s-master tomcat]# pwd
/root/project/tomcat
[root@k8s-master tomcat]# ls
Dockerfile  pro-tomcat.tar  shop  tomcat.yaml
##########
[root@k8s-master tomcat]# cat tomcat.yaml 
apiVersion: v1
kind: Namespace
metadata:name: web
---
apiVersion: apps/v1
kind: Deployment
metadata:name: dep-tomcatnamespace: web 
spec:replicas: 1selector:matchLabels:app: web-tomcattemplate:metadata:labels:app: web-tomcatspec:containers:- name: tomcatimage: pro-tomcat:latest  # 使用你的镜像imagePullPolicy: IfNotPresentports:- containerPort: 8080  # 容器内暴露的端---
apiVersion: v1
kind: Service
metadata:name: svc-tomcatnamespace: web  # 指定命名空间为 discuz
spec:type: NodePortports:- port: 8080        # 集群内访问端口targetPort: 8080  # 容器内端口selector:app: web-tomcat  # 匹配 Deployment 的标签

执行检测

[root@k8s-master tomcat]# kubectl apply -f tomcat.yaml 
namespace/web created
deployment.apps/dep-tomcat created
service/svc-tomcat created
[root@k8s-master tomcat]# kubectl -n web get pod
NAME                         READY   STATUS    RESTARTS   AGE
dep-tomcat-69dd5b6fd-zh9tj   1/1     Running   0          28s
[root@k8s-master tomcat]# kubectl -n web get svc
NAME         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
svc-tomcat   NodePort   10.101.173.117   <none>        8080:30448/TCP   32s

http://192.168.157.100:30448/fore/foreIndex
在这里插入图片描述

2.discuz

[root@k8s-master nginx]# pwd
/root/project/nginx
[root@k8s-master nginx]# ls
discuz  discuz.conf  discuz.yaml  Dockerfile  www.conf
[root@k8s-master nginx]# cat discuz.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: dep-discuznamespace: web
spec:replicas: 1selector:matchLabels:app: web-discuztemplate:metadata:labels:app: web-discuzspec:containers:- name: nginximage: proj-nginx:latestimagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: svc-discuznamespace: web
spec:type: NodePortports:- port: 80targetPort: 80selector:app: web-discuz

执行检测

[root@k8s-master nginx]# kubectl apply -f discuz.yaml
[root@k8s-master nginx]# kubectl -n discuz get pod
NAME                          READY   STATUS    RESTARTS   AGE
dep-discuz-758c879dcb-6kdcf   1/1     Running   0          6h32m
[root@k8s-master nginx]# kubectl -n discuz get svc
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
svc-discuz   NodePort   10.108.98.218   <none>        80:30378/TCP   6h32m

测试能否正常访问

在这里插入图片描述

测试MySQL-redis
在这里插入图片描述

安装
在这里插入图片描述

登录
在这里插入图片描述

六、ingress实现域名访问

1.拷贝导入镜像

导入解压 导入镜像
######所有节点
[root@k8s-node1 ~]# docker load -i ingress-1.11.tar 
######主节点 模拟负载均衡器
[root@k8s-master ~]# unzip metallb-0.14.8.zip

2.部署ingress控制器

[root@k8s-master ~]# cd /root/ingress-nginx-controller-v1.11.3/deploy/static/provider/cloud/
[root@k8s-master cloud]# ls
deploy.yaml  kustomization.yaml
[root@k8s-master cloud]# vim deploy.yaml 
###修改配置文件 从447开始 安装包都删除以下内容 3处image: registry.k8s.io/ingress-nginx/controller:v1.11.3##删除@sha256:d56f135b6462cfc476447cfe564b83a45e8bb7da2774963b00d12161112270b7
[root@k8s-master cloud]# cat deploy.yaml | grep -n image
445:        image: registry.k8s.io/ingress-nginx/controller:v1.12.0
547:        image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.5.0
601:        image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.5.0
#########部署#############
[root@k8s-master01 cloud]# kubectl apply -f deploy.yaml 
......
[root@k8s-master cloud]# kubectl -n ingress-nginx get pod
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-6qhh4        0/1     Completed   0          4m27s
ingress-nginx-admission-patch-6jnc8         0/1     Completed   1          4m27s
ingress-nginx-controller-7d7455dcf8-89krp   1/1     Running     0          4m27s

3.切换为loadbalance模式

kubectl -n ingress-nginx edit svc ingress-nginx-controllertype: LoadBalancer  ###这个字段 50行
status:loadBalancer:

4.部署matellb

[root@k8s-master cloud]# cd /root/metallb-0.14.8/config/manifests
#########下载较慢 先执行
[root@k8s-master cloud]# kubectl apply -f metallb-native.yaml

创建ip地址池

cat > IPAddressPool.yaml<<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: planip-pool #这里与下面的L2Advertisement的ip池名称需要一样namespace: metallb-system
spec:addresses:- 192.168.157.170-192.168.157.180 #自定义ip段 最好和当前集群一个地址段
EOF

关联IP地址池

#关联IP地址池
cat > L2Advertisement.yaml<<EOF
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: planip-poolnamespace: metallb-system
spec:ipAddressPools:- planip-pool #这里需要跟上面ip池的名称保持一致
EOF

执行

###需要等上面创建好,才能执行
kubectl apply -f IPAddressPool.yaml
kubectl apply -f L2Advertisement.yaml

4.创建ingress规则

[root@k8s-master project]# cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress # 创建一个类型为Ingress的资源
metadata:name: nginx-ingress # 这个资源的名字为 nginx-ingressnamespace: web
spec:ingressClassName: nginx # 使用nginxrules:- host: test.nginx.haochacha.com # 访问此内容的域名http:paths:- backend:service:name: svc-discuz # 对应nginx的服务名字,该规则的namespace必须与service的一致port:number: 80 # 访问的端口path: / # 匹配规则pathType: Prefix # 匹配类型,这里为前缀匹配- host: test.tomcat.haochacha.com # 访问此内容的域名http:paths:- backend:service:name: svc-tomcat # 对应nginx的服务名字,该规则的namespace必须与service的一致port:number: 8080 # 访问的端口path: / # 匹配规则pathType: Prefix # 匹配类型,这里为前缀匹配
####提交
[root@k8s-master project]# kubectl apply -f ingress.yaml[root@k8s-master project]# kubectl -n web get ingress
NAME            CLASS   HOSTS                                                ADDRESS           PORTS   AGE
nginx-ingress   nginx   test.nginx.haochacha.com,test.tomcat.haochacha.com   192.168.157.170   80      60m[root@k8s-master project]# kubectl -n web describe ingress nginx-ingress 
Name:             nginx-ingress
Labels:           <none>
Namespace:        web
Address:          192.168.157.170
Ingress Class:    nginx
Default backend:  <default>
Rules:Host                       Path  Backends----                       ----  --------test.nginx.haochacha.com   /   svc-discuz:80 (10.244.169.158:80)test.tomcat.haochacha.com  /   svc-tomcat:8080 (10.244.36.105:8080)
Annotations:                 <none>
Events:Type    Reason  Age                  From                      Message----    ------  ----                 ----                      -------Normal  Sync    62s (x3 over 4m45s)  nginx-ingress-controller  Scheduled for sync       

5.测试

###添加hosts记录
[root@nfs-server ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.157.170  test.nginx.haochacha.com
192.168.157.170  test.tomcat.haochacha.com
####访问discuz
[root@nfs-server ~]# curl http://test.nginx.haochacha.com/upload/install/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Discuz! 安装向导</title>
<link rel="stylesheet" href="static/style.css" type="text/css" media="all" />
......
#####访问商城
[root@nfs-server ~]# curl http://test.tomcat.haochacha.com/fore/foreIndex
<!DOCTYPE html>
<html class="no-js" lang="zxx"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>星味美网上订餐系统</title><meta name="description" content=""><meta name="viewport" content="width=device-width, initial-scale=1"><!-- Favicon --><link rel="icon" href="/assets/images/favicon.ico">
.......

七、总结

构建镜像时,nginx是在容器内修改配置文件,tomcat实在外面修改配置文件
ingress 要和 代理的应用在同一ns下

http://www.xdnf.cn/news/19331.html

相关文章:

  • 狂神说--Nginx--通俗易懂
  • 线程池八股文
  • 从零开始写个deer-flow-mvp-第一天
  • 拆分TypeScript项目的学习收获:处理编译缓存和包缓存,引用本地项目,使用相对路径
  • 粗糙表面接触模型MATLAB代码
  • 多租户配额与预算:限额、配额周期与突发桶的结算模型(Final)
  • 【机械故障】使用扭矩计算物体重量
  • web墨卡托的纬度范围为什么是85°S~85°N?
  • 为何重定义库函数会减少flash体积(从prinf讲解)
  • 为什么计算机使用补码存储整数:补码的本质
  • 【秋招笔试】2025.08.29阿里云秋招笔试题
  • 【Linux】动静态库的制作与原理
  • 第三十二天:数组
  • 刷算法题-数组-02
  • 关于Ctrl+a不能全选的问题
  • Wi-Fi技术——OSI模型
  • VS安装 .NETFramework,Version=v4.6.x
  • React Hooks useMemo
  • [强网杯2019]随便注-----堆叠注入,预编译
  • centos7挂载iscis存储操作记录
  • postman 用于接口测试,举例
  • postman带Token测试接口
  • DAY50打卡
  • Redis 持久化 AOF 与 RDB 的区别
  • Ruoyi-vue-plus-5.x第二篇MyBatis-Plus数据持久层技术:2.1 MyBatis-Plus核心功能
  • audioLDM模型代码阅读(五)—— pipeline
  • Python学习大集合:基础与进阶、项目实践、系统与工具、Web 开发、测试与运维、人工智能(视频教程)
  • 电力电子技术知识学习-----晶闸管
  • VSCode中使用Markdown
  • 从零开始学炒股