MySQL

Kubernetes 部署 Wordpress+MySQL

Posted on 2020-10-12,10 min read

这部分我们结合之前的 k8s 知识点给大家展示如何使用 kubernetes 部署 wordpress+MySQL, 并利用 NFS 去保存我们容器的源代码以及 DB 数据.

安装环境

System: CentOS 7.4

Kubernetes: Kubernetes1.9

Docker: 17.03.2-ce

kube-master 10.110.16.10

kube-node-1 10.110.16.11

一. NFS 配置:

  1. NFS 依赖包安装

在 Master 与 Node 分别安装 NFS 组件

 yum install nfs-utils -y

Tip: 这里需保证 nfs-utils 安装到所有 master 和 node 中, 否则容器挂载 NFS 时会报错.

  1. 为 Master 下 mysql data 和 wordpress 源码配置 NFS 共享目录
# systemctl enable nfs-server && systemctl start nfs-server

# mkdir -p /kube/mysql-db

# mkdir -p /kube/wordpress

# chown nfsnobody:nfsnobody /kube/mysql-db

# chown nfsnobody:nfsnobody /kube/wordpress

# chmod 755 /kube/mysql-db

# chmod 755 /kube/wordpress

# echo -e "/kube/mysql-db    kube-(rw,sync,no_subtree_check,no_root_squash)" > /etc/exports

# echo -e "/kube/wordpress    kube-(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports

Tip: 这里 kube-* 限制只有 kube 相关的 server 才能连接 Master 下 NFS 共享目录, no_root_squash 参数保证 wordpress-mysql pod 在初始化 mysql 配置的时候向在其下挂载的 / var/lib/mysql 目录有写入权限

  1. 应用配置
# exportfs -a

二. Persistent volume 配置

  1. 为 mysql data 与 wordpress 源码存储创建 Persistent volume

    kubectl create -f mysql-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
  labels:
    app: mysql
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /kube/mysql-db
    server: kube-master

​ kubectl create -f wordpress-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: wp-pv
  labels:
    app: wordpress
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /kube/wordpress
    server: kube-master
  1. 创建存放 mysql data 的 PVC

    kubectl create -f mysql-pvc.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mysql-pv-claim
  labels:
    app: mysql
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  1. 创建存放 wordpress 源码的 PVC

    kubectl create -f wordpress-pvc.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

查看绑定

# kubectl get pvc

NAME             STATUS    VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE

mysql-pv-claim   Bound     mysql-pv   5Gi        RWO                           3m

wp-pv-claim      Bound     wp-pv      5Gi        RWO                           6s

三. Secret 配置

  1. 创建 mysql root password

# kubectl create secret generic mysql-pass --from-literal='password=countonme'

四. Deployment 配置

  1. 部署 mysql deployment with PVC

# kubectl create -f mysql-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
  1. 部署 wordpress deployment with PVC

# kubectl create -f wordpress-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:4.8-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

3.Service 配置

Tip: 这里我们开启了 node IP 的 80 端口的外部访问权限, 可以方便我们直接利用主机去访问虚拟机任意 Node 地址从而登录我们的 Wordpress 网站.

# kubectl create -f wp-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
      nodePort: 80
  selector:
    app: wordpress
    tier: frontend
  type: NodePort

Tip: 这里 service 定义的 name: wordpress-mysql 保证我们 wordpress-deployment.yaml 定义的如下环境变量可以作为有效的域名成功去访问我们的 mysql 容器, 保证网站服务器与数据库服务器的通讯.

env:
  - name: WORDPRESS_DB_HOST
	value: wordpress-mysql

五. 验证结果

  1. 访问 wordpress 主页

这里我们可以直接在浏览器访问任意 node 的 IP 地址从而进入 wordpress 主页

wordpress01
  1. 查看 NFS 主机对在容器里的 mysql data 与 wordpress root dir 的目录挂载.

    #mount |grep kube-master
    
  2. 后记:

果我们使用 helm 包管理去部署 wordpress, 将大大简化我们的工作量.

Helm deployment:

1. 搜索 chart

搜索 wordpress 的 charts

# helm search wordpress

NAME            	CHART VERSION	APP VERSION	DESCRIPTION                                             
stable/wordpress	5.0.3        	5.0.2      	Web publishing platform for building blogs and websites.

2. 查看 chart 的存储信息

创建 wordpress 的时候需要申请 PersistentVolumeClaim,由于我们的环境不支持动态申请所以需要手动创建

# helm inspect value stable/wordpress

……
  ## MariaDB admin password
  ## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#setting-the-root-password-on-first-run
  ##
  # rootUser:
  #   password:

  ## Enable persistence using Persistent Volume Claims
  ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
  ##
  master:
    persistence:
      enabled: true
      ## mariadb data Persistent Volume Storage Class
      ## If defined, storageClassName: <storageClass>
      ## If set to "-", storageClassName: "", which disables dynamic provisioning
      ## If undefined (the default) or set to null, no storageClassName spec is
      ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
      ##   GKE, AWS & OpenStack)
      ##
      # storageClass: "-"
      accessMode: ReadWriteOnce
      size: 8Gi
      
……

persistence:
  enabled: true
  ## wordpress data Persistent Volume Storage Class
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  # storageClass: "-"
  ##
  ## If you want to reuse an existing claim, you can pass the name of the PVC using
  ## the existingClaim variable
  # existingClaim: your-claim
  accessMode: ReadWriteOnce
  size: 10Gi

可以看到 wordpress 的 chart 需要两个 pv,分别用于 mariadb(8G) 和 wordpress(10G) 的数据存储。

3. 手动创建 chart 所需的 pv

创建 create-pv.yml 文件,输入以下内容

# vim create-pv.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mariadb-pv
spec:
  capacity:
    storage: 8Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  #storageClassName: nfs
  nfs:
    path: /nfsdata/mariadb-pv
    server: 172.20.6.116
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: wordpress-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  #storageClassName: nfs
  nfs:
    path: /nfsdata/wordpress-pv
    server: 172.20.6.116

创建 pv

# kubectl apply -f create-pv.yml 

persistentvolume/mariadb-pv created
persistentvolume/wordpress-pv created

4. 安装 chart

# helm install --name wordpress stable/wordpress

NAME:   wordpress                                  ---------①---------
LAST DEPLOYED: Fri Jan  4 10:32:57 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:                                         ---------②---------
==> v1beta1/Deployment
NAME                 DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
wordpress-wordpress  1        1        1           0          0s

==> v1beta1/StatefulSet
NAME               DESIRED  CURRENT  AGE
wordpress-mariadb  1        1        0s

==> v1/Pod(related)
NAME                                  READY  STATUS   RESTARTS  AGE
wordpress-wordpress-56794ff7b9-rf98x  0/1    Pending  0         0s
wordpress-mariadb-0                   0/1    Pending  0         0s

==> v1/Secret
NAME                 TYPE    DATA  AGE
wordpress-mariadb    Opaque  2     0s
wordpress-wordpress  Opaque  1     0s

==> v1/ConfigMap
NAME                     DATA  AGE
wordpress-mariadb        1     0s
wordpress-mariadb-tests  1     0s

==> v1/PersistentVolumeClaim
NAME                 STATUS   VOLUME  CAPACITY  ACCESS MODES  STORAGECLASS  AGE
wordpress-wordpress  Pending  0s

RESOURCES:
==> v1/Service
NAME                 TYPE          CLUSTER-IP      EXTERNAL-IP  PORT(S)                     AGE
wordpress-mariadb    ClusterIP     10.100.218.132  <none>       3306/TCP                    0s
wordpress-wordpress  LoadBalancer  10.100.36.64    <pending>    80:31051/TCP,443:30169/TCP  0s


NOTES:                                             ---------③---------
1. Get the WordPress URL:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w wordpress-wordpress'
  export SERVICE_IP=$(kubectl get svc --namespace default wordpress-wordpress --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
  echo "WordPress URL: http://$SERVICE_IP/"
  echo "WordPress Admin URL: http://$SERVICE_IP/admin"

2. Login with the following credentials to see your blog

  echo Username: user
  echo Password: $(kubectl get secret --namespace default wordpress-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

输出分为 3 部分(上文输出结果中的①②③):

  • ① 本次部署 chart 的描述信息。包括 release 的名字(没有指定,则默认生成)。release 部署的 namespace,默认是 default。release的状态 DEPLOYED 表示已经将 chart 部署到集群。
  • ② release 包含的资源: Service、 Deployment、 Secret 等
  • ③ release 的使用方法

5. 访问 wordpress

使用 http://nodeip+service_port 访问wordpress

其他信息,包括后台地址,管理员账号等信息可以参考release 的 NOTES 部分。

写在最后

Helm 的使用有点类似 ubuntu 的 apt 或者 RHEL 的 yum,极大的简化了部署一个应用的流程。对于使用者而言,使用 Helm 后不用需要了解 Kubernetes 的 yaml 语法并编写应用部署文件,也无需考虑应用的各种依赖,可以直接通过 Helm 下载并在 kubernetes 上安装需要的应用。 除此以外,Helm 还提供了 kubernetes 上的软件部署,删除,升级,回滚应用的强大功能。

下一篇: 在K8S上部署eureka-server→