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下