k8s的云原生应用部署-mysql和wordpress

发布时间 2024-01-03 23:26:38作者: 宝马大盗

在已经建立有k8s集群的前提下,使用deploy,部署一个单独pod的单点mysql,部署一个4pod的wordpress应用。

应用的数据库使用mysql,mysql和应用都做集群外服务暴露。

通过该应用部署的练习,了解中等难度应用程序如何做云原生状态下的部署,并掌握以下k8s资源-APIServer的使用:

NameSpace、PV、ConfigMap、Secret、PVC、Deployment、NodePort类型的Service。

进行该练习的背景知识,有:

(1)能够独立搭建一套1master、3worker的k8s集群;

(2)能够在k8s上部署一个简单无状态的nginx应用;

(3)对NFS存储有一定的了解。

完成练习后,本练习中创建的数据库+网站应用,可以作为后续练习的基础和背景板。

一、规划

1 节点规划

5个节点:1个master,3个worker,1个独立的NFS server。

基础OS为Ubuntu22.04.3,版本代号jammy,内核5.15.0-91-generic。

节点的统一域名为beety.com。

假设整套k8s环境上已经装好k8s,各项功能运转正常;nfs server已经建立,k8s集群的worker可以正产挂载目录。

假设全部5个节点,主机长名、短名互相可见(使用DNS或绑定hosts表均可)

角色 IP 主机名 主机长名 功能 配置
master01 192.168.172.141 m01 m01.beety.com kubelet、etcd、apiserver、controller-manager、scheduler 2vc4G40G
worker01 192.168.172.151 w01 w01.beety.com kubelet、proxy、应用pod 4vc4G40G
worker02 192.168.172.152 w02 w02.beety.com kubelet、proxy、应用pod 4vc4G40G
worker03 192.168.172.153 w03 w03.beety.com kubelet、proxy、应用pod 4vc4G40G
nfs repository 192.168.172.144 repo01 repo01.beety.com nfs server,提供容量5GB的共享文件系统 2vc2G40G

2 应用版本规划

k8s:containerd 1.6.26, kubernetes 1.28.2,flannel cniVersion 0.3.1

nfs:操作系统级别,Ubuntu22.04.3的镜像源提供的nfs-kernel-server(服务器端)、nfs-common(客户端)

nfs协议:需要nfs server支持NFS4.1版本的协议。

mysql:MySQL Community Server 8.0.19官方docker镜像

wordpress:6-apache(2023年12月31日的latest,wordpress版本6.4.2),官方docker镜像

3 存储规划

nfs server提供共享目录:

repo01.beety.com:/data/nfs/share01,该目录供mysql存放数据文件使用。

repo01.beety.com:/data/nfs/share02,该目录共wordpress存放网页文件使用。

4 k8s资源规划

(1)公用

已经建立好一个k8s集群环境。

使用独立的namespace做本次应用部署,取名mywebapp。

建立一个k8s全局级别的PersistentVolume(PV),nfspv01,指向上面的nfs share01目录。

建立一个k8s全局级别的PersistentVolume(PV),nfspv02,指向上面的nfs share02目录。

(2)mysql

主配置文件my.cnf,配置为ConfigMap。

root口令配置为secret。

为mysql创建一个PersistentVolumeClaim(PVC),指向全局PV nfspv01,用于存放数据库文件。

为mysql应用创建一个pod,引用上面的ConfigMap、secret、PVC,另外为了统一时区,引用pod所在节点本地的/etc/localtime。

pod的东西向访问端口3306,南北向访问端口30336。使用NodePort类型的service资源在南北方向暴露该端口。

(3)wordpress

mysql中数据库db02,用户wordpress给与db02全库权限,口令123456,用来存放wordpress基础数据。

wordpress调用的mysql URL、用户名、口令,使用secret存储。

一个PersistentVolumeClaim(PVC),指向第二个全局PV nfspv02,用于存放网页文件。

为wordpress应用deploy 4个pod,引用上面的secret、PVC。

pod的东西向访问端口80,南北向访问端口30080。使用NodePort类型的service资源在南北方向暴露该端口。

二、验证NFS可用

首先确认worker的3个节点作为nfs client,可以使用nfs server。nfs server的安装配置以及client的挂载方法,参考本文附件一。

能够使用的前提,是worker3节点能够访问nfs server的111、2049两个端口。

注意后面在让pod使用nfs时,并不会在worker节点上直接挂载,而是通过PV、PVC的定义,让pod使用,因此这里只是验证,挂载成功后需要摘掉并删除挂载目录。

在任意或全部worker节点上:

showmount -e repo01.beety.com
###正确回显
Export list for repo01.beety.com:
Export list for localhost:
/data/nfs/share02 *
/data/nfs/share01 *
###回显完
mkdir /tmp001
mount -t nfs -o soft,timeo=200,retrans=3,retry=1 repo01.beety.com:/data/nfs/share01 /tmp001
df -h | grep repo01.beety.com     #(确保成功挂载)
umount /tmp001
rm -r /tmp001

三、准备工作

1 目录准备

在m01节点上为后续各个资源的yaml声明文件做目录准备,mysql和wordpress各一个

mkdir -p ~/k8sapp01/20231229/{global,mysql,wordpress}

全局PV的声明放在global中,mysql和wordpress对应的声明存放在各自目录中,后面不在赘述。

2 独立的命名空间

为本次部署创建独立的namespace:mywebapp

kubectl create namespace mywebapp

后面所有为此次部署而apply的k8s资源,除了无namespace分隔的PV,其他都会创建在mywebapp这个namespace中。

3 全局PV

声明global_pv.yaml

## 第一个PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv01
  labels:
    app: nfspv01                  #设置 pv 的 label 标签
spec:
  capacity:
    storage: 2Gi                  #设置 pv 存储资源大小 
  accessModes:
  - ReadWriteOnce
  mountOptions:
  - soft
  - nfsvers=4.1
  nfs:                            #指定使用 NFS 存储驱动
    server: repo01.beety.com      #指定 NFS 服务器 IP 地址
    path: /data/nfs/share01       #指定 NFS 共享目录的位置
  persistentVolumeReclaimPolicy: Retain
---
## 第二个PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv02
  labels:
    app: nfspv02                  #设置 pv 的 label 标签
spec:
  capacity:
    storage: 1Gi                  #设置 pv 存储资源大小 
  accessModes:
  - ReadWriteMany                 #相比上一个PV这里可以多路读写
  mountOptions:
  - soft
  - nfsvers=4.1
  nfs:                            #指定使用 NFS 存储驱动
    server: repo01.beety.com      #指定 NFS 服务器 IP 地址
    path: /data/nfs/share02       #指定 NFS 共享目录的位置
  persistentVolumeReclaimPolicy: Retain

直接apply,应用该声明,创建PV

kubectl apply -f global_pv.yaml --dry-run=client
kubectl apply -f global_pv.yaml
kubectl get pv
#回显
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM               STORAGECLASS   REASON   AGE
nfspv01   2Gi        RWO            Retain           Available                                              5s
nfspv02   1Gi        RWX            Retain           Available                                              5s

四、mysql应用

1 ConfigMap声明

按照规划,将mysql的主配置文件my.cnf,作为ConfigMap资源,放在etcd中。

mysql-config.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
  labels:
    app: mysql
data:
  my.cnf: |-
    [client]
    default-character-set=utf8mb4
    [mysql]
    default-character-set=utf8mb4
    [mysqld]
    innodb_file_per_table=ON
    max_connections = 2000
    secure_file_priv=/var/lib/mysql
    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

这里的mysql-config作为一个ConfigMap资源,会被后面的deploy引用。

2 secret声明

按照规划,制作base64的暗文,声明secret。

echo -n "root" | base64
#回显base加密后的用户名密文
cm9vdA==
echo -n "123456" | base64
#回显base64加密后的口令密文
MTIzNDU2

mysql-root-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysql-root-secret
type: Opaque
data:
  username: cm9vdA==
  password: MTIzNDU2

后面声明deploy的yaml中,将引用mysql-root-secret这个secretKeyRef,并指定获取key=password这个变量的值。

3 Storage声明

按照规划,创建一个PVC,指向PV nfspv01。

mysql-storage.yaml

## PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mysqlpvc
spec:
  resources:
    requests:
      storage: 2Gi        #设置 pvc 存储资源大小
  accessModes:
  - ReadWriteOnce
  selector:
    matchLabels:
      app: nfspv01        #根据 Label 选择对应 PV

这里的mysqlpvc作为一个PVC资源,会被后面的deploy引用。

4 deploy声明

按照规划配置pod

mysql-deploy.yaml

## Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql01
  labels:
    app: mysql01
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql01
  template:
    metadata:
      labels:
        app: mysql01
    spec:
      containers:
      - name: mysqlcontainer
        image: mysql:8.0.19
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-root-secret
              key: password
        resources:
          limits:
            cpu: 2000m
            memory: 512Mi
          requests:
            cpu: 2000m
            memory: 512Mi
        livenessProbe:
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
          exec:
            command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
        readinessProbe:
          initialDelaySeconds: 10
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
          exec:
            command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
        - name: config
          mountPath: /etc/mysql/conf.d/my.cnf
          subPath: my.cnf
        - name: localtime
          readOnly: true
          mountPath: /etc/localtime
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mysqlpvc
      - name: config
        configMap:
          name: mysql-config
      - name: localtime
        hostPath:
          type: File
          path: /etc/localtime

5 service声明

按照规划为mysql建立一个NodePort类型的SVC。

## Service
apiVersion: v1
kind: Service
metadata:
  name: mysqlsvc
  labels:
    app: mysqlsvc
spec:
  type: NodePort
  ports:
  - name: mysql
    port: 3306
    targetPort: 3306
    nodePort: 30336
  selector:
    app: mysql01

6 apply执行

ConfigMap:

kubectl apply -f mysql-config.yaml -n mywebapp --dry-run=client
kubectl apply -f mysql-config.yaml -n mywebapp
kubectl -n mywebapp get ConfigMap
#回显
NAME               DATA   AGE
kube-root-ca.crt   1      3m9s
mysql-config       1      2m49s

Secret:

kubectl apply -f mysql-root-secret.yaml -n mywebapp --dry-run=client
kubectl apply -f mysql-root-secret.yaml -n mywebapp
kubectl -n mywebapp get secret
#回显
NAME                TYPE     DATA   AGE
mysql-root-secret   Opaque   2      8s

Storage:

kubectl apply -f mysql-storage.yaml -n mywebapp --dry-run=client
kubectl apply -f mysql-storage.yaml -n mywebapp
kubectl -n mywebapp get pvc
#回显
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysqlpvc   Bound    nfspv01   2Gi        RWO                           59s

deploy:

kubectl apply -f mysql-deploy.yaml -n mywebapp --dry-run=client
kubectl apply -f mysql-deploy.yaml -n mywebapp
kubectl -n mywebapp get pod -o wide
#回显
NAME                       READY   STATUS              RESTARTS   AGE   IP            NODE   NOMINATED NODE   READINESS GATES
mysql01-695cf548cd-5zjbr   0/1     ContainerCreating   0          17s   10.244.2.26   w02    <none>           <none>
#创建完成后回显
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE   NOMINATED NODE   READINESS GATES
mysql01-695cf548cd-5zjbr   0/1     Running   0          11s   10.244.2.26   w02    <none>           <none>

查看apply deploy pod的日志

#查看pod和container日志
kubectl -n mywebapp logs mysql01-695cf548cd-5zjbr -c mysqlcontainer

service:

kubectl apply -f mysql-service.yaml -n mywebapp --dry-run=client
kubectl apply -f mysql-service.yaml -n mywebapp
kubectl -n mywebapp get service
#回显
NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
mysqlsvc   NodePort   10.107.108.12   <none>        3306:30336/TCP   7s

测试南北向暴露的端口

#在m01节点和任意worker节点上,使用iptable查看暴露的30336端口:
iptables -tnat -L | grep 30336
#回显
KUBE-EXT-W3WR2O63YWU7PI6D  tcp  --  anywhere             anywhere             /* mywebapp/mysqlsvc:mysql */ tcp dpt:30336

至此,mysql数据库在K8S集群上部署完毕,可以使用了。

7 创建mysql基本对象

为mysql数据库创建基本的数据库、用户对象

#进入pod
kubectl -n mywebapp exec -it mysql01-695cf548cd-5zjbr -- /bin/bash
#测试mysqld的状态
mysqladmin -uroot -p123456 ping
###回显:
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
mysqld is alive
#以mysql的root用户进入mysql的sql命令控制台
mysql -uroot -p123456
#建立一系列基本数据库对象:
CREATE USER user01@'%' identified BY 'passw0rd';
CREATE USER user01@'localhost' identified BY 'passw0rd';
CREATE DATABASE db01;
GRANT ALL PRIVILEGES ON db01.* to user01;
FLUSH PRIVILEGES;
#退出sql命令控制台
quit;
#退出pod
exit

8 验证数据库访问

使用DataGrid等任意支持mysql的SQL客户端,建立到下面的连接

jdbc:mysql://192.168.172.141:30336/db01
用户名user01
口令123456

成功连接后,建立库内数据对象

create table db01.department
(
    dptid   int auto_increment
        primary key,
    dptname varchar(20) not null
);
insert into db01.department(dptid, dptname) values (1, "市场部");
commit;
select * from db01.department;

确保数据库正常访问。

五、wordpress应用

1 mysql建立wordpress独立数据库和用户

为wordpress建立专用的数据库、用户,并为用户授权

#进入pod
kubectl -n mywebapp exec -it mysql01-695cf548cd-5zjbr -- /bin/bash
#以mysql的root用户进入mysql的sql命令控制台
mysql -uroot -p123456
#建立数据库db02、用户wordpress:
CREATE USER wordpress@'%' identified BY 'passw0rd';
CREATE USER wordpress@'localhost' identified BY 'passw0rd';
CREATE DATABASE db02;
GRANT ALL PRIVILEGES ON db02.* to wordpress;
FLUSH PRIVILEGES;
#退出sql命令控制台
quit;
#退出pod
exit

查看mysql的接入信息

#查看mysql的pod ip信息:
kubectl get pod -n mywebapp -o wide
#回显
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE   NOMINATED NODE   READINESS GATES
mysql01-695cf548cd-5zjbr   1/1     Running   0          44h   10.244.2.26   w02    <none>           <none>
###这里的10.244.2.26就是mysql01这个pod的ip,但是为了防止变化,需要找到服务地址
kubectl get service -n mywebapp -o wide
#回显
NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE   SELECTOR
mysqlsvc   NodePort   10.107.108.12   <none>        3306:30336/TCP   44h   app=mysql01
#集群默认全局域名为cluster.local,之前为mysql和wordpress建立的额ns为mywebapp,mysql服务名为mysqlsvc
#按照集群内部的名称规则,服务的访问入口为<service_name>.<namespace_name>.svc.<domainname>
#因此应为: mysqlsvc.mywebapp.svc.cluster.local

集群内mysql01的端口号为3306,因此可以得出以下mysql访问信息:

host: mysqlsvc.mywebapp.svc.cluster.local:3306
dbname: db02
dbuser: wordpress
dbpwd: passw0rd

2 secret声明

制作base64的暗文,声明secret,包含mysql连接信息,即host、dbuser、dbpwd的值。

echo -n "mysqlsvc.mywebapp.svc.cluster.local:3306" | base64
echo -n "db02" | base64
echo -n "wordpress" | base64
echo -n "passw0rd" | base64
#分别回显base加密后的密文
bXlzcWxzdmMubXl3ZWJhcHAuc3ZjLmNsdXN0ZXIubG9jYWw6MzMwNg==
ZGIwMg==
d29yZHByZXNz
cGFzc3cwcmQ=

wordpress-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: wordpress-secret
type: Opaque
data:
  host: bXlzcWxzdmMubXl3ZWJhcHAuc3ZjLmNsdXN0ZXIubG9jYWw6MzMwNg==
  dbname: ZGIwMg==
  dbuser: d29yZHByZXNz
  dbpwd: cGFzc3cwcmQ=

3 storage声明

wordpress-storage.yaml

## PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: wordpresspvc
spec:
  resources:
    requests:
      storage: 900Mi        #设置 pvc 存储资源大小
  accessModes:
  - ReadWriteMany
  selector:
    matchLabels:
      app: nfspv02        #根据 Label 选择对应 PV

这里的wordpresspvc作为一个PVC资源,会被后面的deploy引用。

4 deploy声明

按照规划配置pod

wordpress-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpressdpy
  labels:
    app: wordpress01dpy
spec:
  replicas: 4
  selector:
    matchLabels:
      app: wordpress01
  template:
    metadata:
      labels:
        app: wordpress01
    spec:
      containers:
        - name: wordpresscontainer
          image: wordpress:6-apache
          env:
            - name: WORDPRESS_DB_HOST
              valueFrom:
                secretKeyRef:
                  name: wordpress-secret
                  key: host
            - name: WORDPRESS_DB_NAME
              valueFrom:
                secretKeyRef:
                  name: wordpress-secret
                  key: dbname
            - name: WORDPRESS_DB_USER
              valueFrom:
                secretKeyRef:
                  name: wordpress-secret
                  key: dbuser
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: wordpress-secret
                  key: dbpwd
            - name: WORDPRESS_DEBUG
              value: "true"
          volumeMounts:
            - mountPath: /var/www/html
              name: wp-data
      volumes:
        - name: wp-data
          persistentVolumeClaim:
            claimName: wordpresspvc
        - name: localtime
          hostPath:
            type: File
            path: /etc/localtime

如果想要直观一点方便调试,env部分也可以先把数据库相关环境变量写成明文

          env:
            - name: WORDPRESS_DB_HOST
              value: "mysqlsvc.mywebapp.svc.cluster.local:3306"
            - name: WORDPRESS_DB_NAME
              value: "db02"
            - name: WORDPRESS_DB_USER
              value: "wordpress"
            - name: WORDPRESS_DB_PASSWORD
              value: "passw0rd"

5 service声明

wordpress-service.yaml

## Service
apiVersion: v1
kind: Service
metadata:
  name: wordpresssvc
  labels:
    app: wordpresssvc
spec:
  type: NodePort
  ports:
  - name: wordpress
    port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: wordpress01

6 apply执行

Secret:

kubectl apply -f wordpress-secret.yaml -n mywebapp --dry-run=client
kubectl apply -f wordpress-secret.yaml -n mywebapp
kubectl -n mywebapp get secret
#回显
NAME                TYPE     DATA   AGE
mysql-root-secret   Opaque   2      45h
wordpress-secret    Opaque   3      6s

Storage:

kubectl apply -f wordpress-storage.yaml -n mywebapp --dry-run=client
kubectl apply -f wordpress-storage.yaml -n mywebapp
kubectl -n mywebapp get pvc
#回显
NAME           STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysqlpvc       Bound    nfspv01   2Gi        RWO                           45h
wordpresspvc   Bound    nfspv02   1Gi        RWX                           7s
###通过回显,看到已经按照既定规划,两个PVC处于Bound状态,绑定到既定的PV之上了

deploy:

kubectl apply -f wordpress-deploy.yaml -n mywebapp --dry-run=client
kubectl apply -f wordpress-deploy.yaml -n mywebapp
kubectl -n mywebapp get pod -o wide
#回显
NAME                             READY   STATUS              RESTARTS   AGE     IP            NODE   NOMINATED NODE   READINESS GATES
mysql01-695cf548cd-5zjbr         1/1     Running             0          45h     10.244.2.26   w02    <none>           <none>
wordpressdpy-7f795b898d-4kx7k    0/1     ContainerCreating   0          8m54s   <none>        w02    <none>           <none>
wordpressdpy-7f795b898d-97pml    0/1     ContainerCreating   0          8m54s   <none>        w03    <none>           <none>
wordpressdpy-7f795b898d-g59tk    0/1     ContainerCreating   0          8m54s   <none>        w01    <none>           <none>
wordpressdpy-7f795b898d-q4m5m    0/1     ContainerCreating   0          8m54s   <none>        w03    <none>           <none>
#创建成功后的回显
NAME                             READY   STATUS    RESTARTS   AGE   IP            NODE   NOMINATED NODE   READINESS GATES
mysql01-695cf548cd-5zjbr         1/1     Running   0          46h   10.244.2.26   w02    <none>           <none>
wordpressdpy-7f795b898d-4kx7k    1/1     Running   0          56m   10.244.2.27   w02    <none>           <none>
wordpressdpy-7f795b898d-97pml    1/1     Running   0          56m   10.244.3.24   w03    <none>           <none>
wordpressdpy-7f795b898d-g59tk    1/1     Running   0          56m   10.244.1.28   w01    <none>           <none>
wordpressdpy-7f795b898d-q4m5m    1/1     Running   0          56m   10.244.3.25   w03    <none>           <none>

查看apply deploy pod的日志

#查看pod和container日志
kubectl -n mywebapp logs wordpressdpy-7f795b898d-4kx7k -c wordpresscontainer
#回显
WordPress not found in /var/www/html - copying now...
Complete! WordPress has been successfully copied to /var/www/html
No 'wp-config.php' found in /var/www/html, but 'WORDPRESS_...' variables supplied; copying 'wp-config-docker.php' (WORDPRESS_DB_HOST WORDPRESS_DB_PASSWORD WORDPRESS_DB_USER)
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.244.2.27. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.244.2.27. Set the 'ServerName' directive globally to suppress this message
[Tue Jan 02 15:56:40.049660 2024] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.57 (Debian) PHP/8.2.14 configured -- resuming normal operations
[Tue Jan 02 15:56:40.049730 2024] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

service:

kubectl apply -f wordpress-service.yaml -n mywebapp --dry-run=client
kubectl apply -f wordpress-service.yaml -n mywebapp
kubectl -n mywebapp get service
#回显
NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
mysqlsvc       NodePort   10.107.108.12   <none>        3306:30336/TCP   46h
wordpresssvc   NodePort   10.98.60.145    <none>        80:30080/TCP     7s

7 验证wordpress可用

集群外,浏览器中,访问http://192.168.172.141:30080/,出现语言选择的内容,则意味着wordpress已经可以使用,且和数据库连接成功。按照步骤提示,创建应用用户,并开启自己的博客。初始化后,会在mysql的db02中,初始化12张表。

wp_commentmeta
wp_comments
wp_links
wp_options
wp_postmeta
wp_posts
wp_term_relationships
wp_term_taxonomy
wp_termmeta
wp_terms
wp_usermeta
wp_users

至此,wordpress应用部署成功。

六、环境清理

1 清除wordpress所有资源

kubectl -n mywebapp delete service wordpresssvc
kubectl -n mywebapp delete deploy wordpressdpy
kubectl -n mywebapp delete pvc wordpresspvc
kubectl -n mywebapp delete secret wordpress-secret

2 清除mysql所有资源

kubectl -n mywebapp delete service mysqlsvc
kubectl -n mywebapp delete deploy mysql01
kubectl -n mywebapp delete pvc mysqlpvc
kubectl -n mywebapp delete secret mysql-root-secret
kubectl -n mywebapp delete cm mysql-config

delete deploy时,可以同时监控pod日志

kubectl -n mywebapp logs mysql01-8545bf88cf-52xv5 -c mysqlcontainer -f

确认删除deploy时,mysql退出。

3 清除公共资源

至此,所有在mywebapp这个namespace下的资源都应该被清掉了,用下面的命令验证

kubectl get all -n mywebapp

清除namespace

kubectl delete namespace mywebapp

清除全局资源PV

kubectl delete pv nfspv01
kubectl delete pv nfspv02

别忘了清理NFS上的数据文件

#repo01节点上
cd /data/nfs/share01
rm -rf *
cd /data/nfs/share02
rm -rf *

附件

附件一 NFS服务器和客户端

(1)配置独立逻辑卷(可选)

lvcreate -L 5G -n lvdata vg00
mkfs.xfs /dev/vg00/lvdata
mkdir /data
echo "/dev/disk/by-uuid/6f709e18-61d4-4d27-b844-9c9349b5e3e9 /boot xfs defaults 0 1" >> /etc/fstab
mount -a
df -h
mkdir -p /data/nfs/share01

其中,第4行写入fstab中的卷uuid,到/dev/disk/by-uuid目录下,找到和/dev/disk/by-id下,dm-name-vg00-lvdata指向同一个dm的逻辑卷uuid,就是。

后续,将把/data/nfs/share01目录共享出去,作为mysql的数据存储卷。

(2)安装并配置nfs-server

ubuntu中的nfs-server的安装包为nfs-kernel-server,安装后服务为nfs-server,安装后会连带让rpcbind服务监听111端口。

同apt安装的其他带服务的软件一样,nfs-server安装后会自动启动且为开机启动。

ubuntu的nfs-server和其他linux分发版本完全一致,主配置文件/etc/exports,使用showmount命令查看某节点共享的nfs目录。

apt install nfs-kernel-server
cp /etc/exports /etc/exports.bak
echo "/data/nfs/share01 *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
systemctl restart nfs-server

(3)查看nfs支持的协议版本

这里专指nfs协议版本,非nfs-kernel-server包的ubuntu定义版本

cat /proc/fs/nfsd/versions
###回显
-2 +3 +4 +4.1 +4.2
#这里可以看到,ubuntu20+的操作系统中,默认不支持(减号)nfs2,支持(加号)3、4、4.1、4.2

nfs server支持的不同的nfs协议版本,在客户端挂载时,在参数选择上有较大差别,这个后面再客户端配置时会简单说明。

(4)验证nfs-server有效

#netstat验证111端口已经处于监听状态
netstat -tunpl | grep 111
#查看本机的共享出去的目录
showmount -e localhost
###回显
/data/nfs/share01 *
#查看nfsstat状态
nfsstat

(5)客户端

客户端只要保证能够连通服务器端的111端口和2049端口,这是前提。

mkdir /sharefs
apt install nfs-common
showmount -e <服务器端IP或主机名>
mount -t nfs <服务器端IP或主机名>:/data/nfs/share01 /sharefs
df -h | grep share01
umount /sharefs

正常情况下,通过上面的mount命令,无参数挂载服务器端/data/nfs/share01目录到客户端/share01下。注意这里尝试后,umount掉了。

如果客户端需要长期挂载nfs,包括开机就挂载,则需要慎重考虑带参数挂载,因为nfs挂载参数将很大程度上决定是客户端程序重要,还是数据存储重要。

下面给带参数的挂载命令作为参考。

mount -t nfs -o soft,timeo=200,retrans=3,retry=1 <服务器端IP或主机名>:/data/nfs/share01 /sharefs
###注意这里使用了soft软挂载方式,soft和hard(默认)哪种好的争议由来已久
###下面以nfs v4为基础,简要给出-o中的参数解释
soft     - 软挂载,非默认值,默认值为hard。选择soft后,当nfs server宕机后,soft模式client不会一直试图连接server,不会把自己的其他FS夯死。
         - 但选择soft,也就意味着server宕机后,有些等待中的数据传输被放弃了。
timeo    - 数据传输失败的超时时间,单位0.1秒,默认600即60秒。这里设为20秒,即20秒服务器端不响应,则放弃本次传输,转而找retrans参数的重试次数。
retrans  - 重试连接server的次数,默认为2。这里设为3,在soft模式下,重试3次后,client和server彻底断连,不再试图重试。
retry    - 在mount时的重试时间,单位分钟,默认为2分钟。这里设为1,即重试1分钟的mount后还连不上则放弃,如果是开机就启动连接,则这种配置不耽误开机时间。
         - 注意该参数容易和retrans混淆,retry是mount时的重试次数,retrans是建立mount以后如何应对服务器无响应的重试次数。

由于nfs v2、v3、v4版本差异较大,很多网上的攻略的配置参数还是基于v2版的,和现在主流的linux版本的nfs已经不兼容。

生产环境一定要再客户端中,使用man nfs,查看参数说明,谨慎选择参数。

开机就有nfs的挂载,可以将nfs挂载固定到fstab中

#与上面相同参数的fstab挂载
echo "<服务器端IP或主机名>:/data/nfs/share01 /sharefs  nfs  soft,timeo=200,retrans=3,retry=1   0  0" >> /etc/fstab

附件二 deploy环境变量和secret

本次应用部署中,使用了secret资源+在deploy mysql时调用secret资源获取环境变量的方式。这种调用有以下三种选择。

(1)deploy中直接写环境变量的值

        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"

这种直接给出password的值的方式,最直观,也最不安全。

(2)deploy中环境变量使用从secret中获得的某个提前定义的密文的明文值

        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-root-secret
              key: password

正文中就是采取这种方式,value改为了valueFrom,调用secretKeyRef的name为mysql-root-secret,从里面拿到key password的value,作为password。

这种方式相比第一种安全了一些。前提是要先创建一个secret资源。创建该secret资源的方式,在正文中有详细给出,这里不再给。

这里给出手工生成secret声明的yaml内容的方式

kubectl create secret generic mysql-root-secret --from-literal=username=root --from-literal=password=123456 -o yaml
#回显
apiVersion: v1
data:
  password: MTIzNDU2
  username: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2023-12-31T17:06:29Z"
  name: mysql-root-secret
  namespace: default
  resourceVersion: "961623"
  uid: cae5bd15-5428-4a1f-9c6e-2f0149745a39
type: Opaque

实际上正文的mysql-root-secret.yaml,就是在这个输出的基础上改的。

(3)同(2),但使用kubectl create手工生成时,不想写明文被操作系统history记录,则可以采用--from-file的方式

kubectl create secret generic try-secret --from-literal=username=root --from-file=password=./password.txt --dry-run=client -o yaml
#回显
apiVersion: v1
data:
  password: MTIzNDU2Cg==
  username: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2024-01-01T16:07:38Z"
  name: try-secret
  namespace: default
  resourceVersion: "1094469"
  uid: 4c30a7d4-d50d-40bd-94c9-ccb86a620d33
type: Opaque

之后再组织yaml即可。from file方式也可以用于将私钥文件、证书文件等进行加密。

注:使用base64编码解码

#编码
echo "Welcome to Linux" | base64
#解码
echo "MTIzNDU2Cg==" | base64 --decode

(全文完)