基于LNMP架构部署综合实验
实验要求
基于LNMP架构部署blog应用。
具体要求如下:
- 使用mysql:5.7、php-fpm-wordpress、nginx镜像和wordpress-4.9.4-zh_CN.zip文件部署blog应用。
- 使用pv-pvs方式为mysql和wordpress提供存储。
- pv通过nfs提供。
- blog 应用通过https访问。
- 密码和站点证书用secret存储。
- 站点 vhost 配置使用configmap提供。
提示:php-fpm-wordpress 镜像找老师获取。
实验步骤
部署 NFS 服务
NFS 服务器操作
bash
# 安装 NFS 服务
[root@master30 ~]# apt install -y nfs-kernel-server
# 创建共享目录
[root@master30 ~]# mkdir -p -m 777 /nfsshares/{mysql,blog}
# 配置 NFS 共享(地址已改为10.1.8.30,允许所有节点访问)
[root@master30 ~]# echo "/nfsshares/mysql *(rw,sync,no_root_squash,no_all_squash)
/nfsshares/blog *(rw,sync,no_root_squash,no_all_squash)" >> /etc/exports
# 启动服务
[root@master30 ~]# systemctl restart nfs-server
NFS 客户端操作
bash
## 安装 NFS 客户端
[root@worker31-32 ~]# apt install -y nfs-common
## 验证共享
[root@worker31-32 ~]# showmount -e master30
Export list for master30:
/nfsshares/blog *
/nfsshares/mysql *
准备 pv 和 pvc
bash
[root@master30 ~]# vim pv-pvc.yaml
bash
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-mysql
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
nfs:
path: /nfsshares/mysql
server: 10.1.8.30
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-blog
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
nfs:
path: /nfsshares/blog
server: 10.1.8.30
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-mysql
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-blog
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
bash
[root@master30 ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
pvc-blog Bound pv-blog 5Gi RWO <unset> 9s
pvc-mysql Bound pv-mysql 5Gi RWO <unset> 9s
部署 mysql
bash
[root@master30 ~]# kubectl create secret generic mysql --from-literal user=tom --from-literal password_for_user=redhat --from-literal password_for_root=redhat --from-literal db_name=wordpress
[root@master30 certs]# kubectl get secrets mysql
NAME TYPE DATA AGE
mysql Opaque 4 17s
[root@master30 ~]# vim pod-mysql.yaml
yaml
---
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
name: mysql
spec:
containers:
- image: docker.io/library/mysql:latest
imagePullPolicy: IfNotPresent
name: mysql
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: password_for_root
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql
key: user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: password_for_user
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: mysql
key: db_name
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: pvc-mysql
bash
[root@master30 ~]# kubectl apply -f pod-mysql.yaml
[root@master30 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql 1/1 Running 0 3s
[root@master30 ~]# kubectl exec -it mysql -- mysql -utom -predhat -e "show databases;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| wordpress |
+--------------------+
部署 php-fpm
bash
# worker节点导入镜像
[root@worker31 ~]# nerdctl load -i php-7.2-fpm-wordpress.tar
[root@worker32 ~]# nerdctl load -i php-7.2-fpm-wordpress.tar
# 镜像名称是 docker.io/library/php:7.2-fpm-wordpress
[root@master30 ~]# vim pod-php.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: php-fpm
name: php-fpm
spec:
containers:
- image: docker.io/library/php:7.2-fpm-wordpress
imagePullPolicy: IfNotPresent
name: php-fpm
volumeMounts:
# PHP 网站根目录
- name: blog-data
mountPath: /usr/share/nginx/html
volumes:
# PHP 网站根目录
- name: blog-data
persistentVolumeClaim:
claimName: pvc-blog
bash
[root@master30 ~]# kubectl apply -f pod-php.yaml
[root@master30 ~]# kubectl get pods php-fpm -o jsonpath={.status.podIP}
10.224.19.44
部署 nginx
创建私钥和证书
bash
#--1--生成私钥
[root@master30 ~]# openssl genrsa -out blog.key 2048
#--2--生成请求文件csr
[root@master30 ~]# openssl req -new -key blog.key -out blog.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=blog.laoma.cloud/emailAddress=webadmin@laoma.cloud"
# CN的值必须是网站域名
#--3--使用自己的私钥对请求文件签名,以生成证书
[root@master30 ~]# openssl x509 -req -days 3650 -in blog.csr -signkey blog.key -out blog.crt
创建 tls 类型secret
bash
[root@master30 ~]# kubectl create secret tls tls-blog --cert=./blog.crt --key=./blog.key
[root@master30 ~]# kubectl get secrets tls-blog
NAME TYPE DATA AGE
tls-blog kubernetes.io/tls 2 25s
准备虚拟主机配置文件
bash
[root@master30 ~]# vim vhost-blog.conf
bash
server {
listen 80;
listen 443 ssl;
server_name blog.laoma.cloud; # 替换为实际域名
# TLS 配置
ssl_certificate /etc/nginx/tls/tls.crt;
ssl_certificate_key /etc/nginx/tls/tls.key;
# 网站根目录
root /usr/share/nginx/html;
index index.php index.html;
# PHP 转发配置(PHP IP)
location ~ \.php$ {
fastcgi_pass 10.224.19.44:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
}
bash
[root@master30 ~]# kubectl create configmap vhost-blog --from-file=vhost-blog.conf=./vhost-blog.conf
准备 pod-nginx
bash
[root@master30 ~]# vim pod-nginx.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
containers:
- image: docker.io/library/nginx:latest
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- name: vhost-blog
mountPath: /etc/nginx/conf.d/vhost-blog.conf
subPath: vhost-blog.conf
- name: tls-blog
mountPath: /etc/nginx/tls
readOnly: true
- name: blog-data
mountPath: /usr/share/nginx/html
volumes:
- name: vhost-blog
configMap:
name: vhost-blog
- name: tls-blog
secret:
secretName: tls-blog
- name: blog-data
persistentVolumeClaim:
claimName: pvc-blog
bash
[root@master30 ~]# kubectl apply -f pod-nginx.yaml
[root@master30 ~]# kubectl get pod nginx
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 11s
[root@master30 ~]# kubectl get pod nginx -o jsonpath={.status.podIP}
10.224.113.173
准备测试页面
bash
[root@master30 ~]# echo Hello World From Nginx > /nfsshares/blog/index.html
[root@master30 ~]# echo "<?php phpinfo(); ?>" > /nfsshares/blog/phpinfo.php
[root@master30 ~]# cat <<'EOF' > /nfsshares/blog/test-mysql.php
<?php
// 数据库配置信息 ------ 请改成你自己的
$host = '10.224.19.45'; // 数据库地址,一般都是 localhost
$user = 'tom'; // 数据库用户名
$pass = 'redhat'; // 数据库密码
$dbname = 'wordpress'; // 要连接的数据库名(必须先创建好)
// 创建连接
$conn = mysqli_connect($host, $user, $pass, $dbname);
// 检测连接是否成功
if (!$conn) {
die("连接失败:" . mysqli_connect_error());
}
// 设置字符集,防止乱码
mysqli_set_charset($conn, 'utf8mb4');
echo "✅ MySQL 数据库连接成功!";
// 关闭连接(可选)
mysqli_close($conn);
?>
EOF
测试 Nginx
bash
# 配置解析
[root@master30 ~]# echo '10.224.113.173 blog.laoma.cloud' >> /etc/hosts
# http 站点
[root@master30 ~]# curl http://blog.laoma.cloud/index.html
Hello World From Nginx
[root@master30 ~]# curl -s http://blog.laoma.cloud/phpinfo.php |grep -o 'PHP Version 7'
PHP Version 7
[root@master30 ~]# curl http://blog.laoma.cloud/test-mysql.php
✅ MySQL 数据库连接成功!
# https 站点
[root@master30 ~]# curl -k https://blog.laoma.cloud/index.html
Hello World From Nginx
[root@master30 ~]# curl -sk https://blog.laoma.cloud/phpinfo.php |grep -o 'PHP Version 7'
PHP Version 7
[root@master30 ~]# curl -k https://blog.laoma.cloud/test-mysql.php
✅ MySQL 数据库连接成功!
部署 wordpress 代码
yaml
## 进入 NFS 服务器(IP:10.1.8.30),下载 Wordpress 源码
[root@master30 ~]# unzip wordpress-4.9.4-zh_CN.zip
[root@master30 ~]# cp -a wordpress/* /nfsshares/blog/
## 修改配置文件(连接 MySQL)
[root@master30 ~]# cp /nfsshares/blog/wp-config{-sample,}.php
## 配置数据库信息
[root@master30 ~]# vim /nfsshares/blog/wp-config.php
/** WordPress数据库的名称 */
define('DB_NAME', 'wordpress');
/** MySQL数据库用户名 */
define('DB_USER', 'tom');
/** MySQL数据库密码 */
define('DB_PASSWORD', 'redhat');
/** MySQL主机 */
define('DB_HOST', '10.224.19.45');
访问网站
bash
[root@master30 ~]# kubectl port-forward pod/nginx --address 10.1.8.30 80:80 443:443
Forwarding from 10.1.8.30:80 -> 80
Forwarding from 10.1.8.30:443 -> 443