为了提高数据库扩展灵活性,计划将测试数据库部署在 Kubernetes 集群中,数据持久化存储在介质中。

Mysql 常用命令


查询用户详细信息
use mysql;

select user,authentication_string,host from user;
查询表结构信息
**表结构,字段类型,主键,是否为空等属性**
desc tabl_name;

**查询注释信息**
select * from information_schema.
where table_schema = 'db'  #表所在数据库
and table_name = 'tablename' ; #你要查的表
查看表生成的DDL
show create table table_name;
Mysql 新建用户及赋权
**创建用户**
CREATE USER 'operator'@'%' IDENTIFIED BY 'password';
**删除用户**
DROP USER 'username'@'host';

**授权**
GRANT privileges ON databasename.tablename TO 'username'@'host'
**例子**
GRANT SELECT, INSERT ON test.user TO 'operator'@'%';
GRANT ALL ON *.* TO 'operator'@'%';
修改密码
alter user 'operator'@'localhost' IDENTIFIED BY 'password';
flush privileges;

部署 Mysql


部署 Mysql 到 Kubernetes 集群中需要使用到 persistent volumes ,来持久化存储数据库相关数据。

此次使用 master 节点的 nfs 目录作为持久化存储的介质,首先在master节点启动 nfs-server 服务。

NFS 安装与配置


NFS 简介

NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。

NFS 与 RPC 服务

RPC(NFS服务需要依赖RPC服务,这个比较重要) 要想了解NFS,必然要提到RPC这个服务。 因为NFS支持的功能还是比较多的,并且不同的功能都会使用不同的程序来启动。每启动一个功能就会启用一些端口来传输数据,因此NFS的功能所对应的端口才没有固定,而是采用随机取用一些未被使用的小于1024的端口来作为传输之用。但如此一来又造成客户端要连接服务器时的困扰,因为客户端要知道服务器端的相关端口才能够联机,此时我们需要远程过程调用(RPC)的服务。 RPC最主要的功能就是指定每个NFS功能所对应的端口号,并且回报给客户端,让客户端可以连接到正确的端口上。当服务器在启动NFS时会随机选用数个端口,并主动地向RPC注册。因此RPC可以知道每个端口对应的NFS功能。然后RPC固定使用端口111来监听客户端的请求并回报客户端正确的端口,所以可以让NFS的启动更为容易。 注意,启动NFS之前,要先启动RPC服务;否则NFS无法向RPC注册。另外,重新启动RPC时原本注册的数据会不见,因此RPC重新启动后它管理的所有程序都需要重新启动以重新向RPC注册,比如NFS服务。

RPC服务作为NFS服务器与NFS客户端的中间接口。

NFS 工作流程

1、由程序在NFS客户端发起存取文件的请求,客户端本地的RPC(rpcbind)服务会通过网络向NFS服务端的RPC的111端口发出文件存取功能的请求。

2、NFS服务端的RPC找到对应已注册的NFS端口,通知客户端RPC服务。

3、客户端获取正确的端口,并与NFS daemon联机存取数据。

4、存取数据成功后,返回前端访问程序,完成一次存取操作。

nfs-server 安装

注:暂时不要启动nfs-server, 等下面固定好nfs服务端口后再启动,可以避免重启系统

yum install -y rpcbind nfs-utils

**开机启动**
systemctl enable rpcbind
systemctl enable nfs-server

查看nfs服务向rpc注册的端口信息

rpcinfo -p
固定nfs服务端口

我们需要在/etc/sysconfig/nfs 指定特定的端口,这样每次启动nfs 时,相关服务启动的端口就会固定,这样便于我们设置防火墙策略。

修改/etc/sysconfig/nfs文件,将下列内容的注释去掉,如果没有则添加:

# Port rpc.mountd should listen on.
MOUNTD_PORT=892
#
# Optional arguments passed to rpc.statd. See rpc.statd(8)
STATDARG=""
# Port rpc.statd should listen on.
STATD_PORT=662
# Outgoing port statd should used. The default is port
# is random
STATD_OUTGOING_PORT=2020

vim /etc/modprobe.d/lockd.conf

# Set the TCP port that the NFS lock manager should use.
# port must be a valid TCP port value (1-65535).
options lockd nlm_tcpport=32803
#
# Set the UDP port that the NFS lock manager should use.
# port must be a valid UDP port value (1-65535).
options lockd nlm_udpport=32769

固定服务端口之后,启动nfs-server服务,后执行rpcinfo -p命令,查看nfs向rpc注册的端口。

设置防火墙

编辑防火墙配置文件

cp /usr/lib/firewalld/services/nfs.xml /etc/firewalld/services/

文件如下:

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>NFS4</short>
  <description>The NFS4 protocol is used to share files via TCP networking. You will need to have the NFS tools installed and properly configure your NFS server for this option to be useful.</description>
  <port protocol="tcp" port="111"/>
  <port protocol="tcp" port="662"/>
  <port protocol="tcp" port="892"/>
  <port protocol="tcp" port="2049"/>
  <port protocol="tcp" port="32803"/>
  <port protocol="udp" port="111"/>
  <port protocol="udp" port="662"/>
  <port protocol="udp" port="892"/>
  <port protocol="udp" port="2049"/>
  <port protocol="udp" port="32769"/>
</service>

开启相应端口

firewall-cmd --permanent --zone=public --add-service=nfs

firewall-cmd --reload
server 端创建共享目录
vim /etc/exports

**允许root用户及其他用户**
[目录] 172.10.10.0/24(rw,sync,no_root_squash,no_root_squash,no_all_squash)

**压缩用户为nfsnobody**
[目录] 172.10.10.0/24(rw,sync,root_squash,all_squash,anonuid=1001,anongid=1001)

重启nfs-server

查看服务端共享目录情况

showmount -e serverIP
客户端挂载
mount -t nfs  serverIP:[服务端共享目录] [本地目录]

Kubernetes 集群持久化存储

PV 与 PV-claim

Mysql 挂载两个目录:

数据库数据目录

[nfs-server] /data/volumes/mysql-pv/data        [container] /var/lib/mysql 

数据库配置目录

[nfs-server] /data/volumes/mysql-pv/conf        [container] /etc/mysql/conf.d

yaml 资源定义文件 mysql-pv-volume&claim.yaml

分别定义了两个 pv 与 pv-claim ,pv-claim 与 pv 是一一对应的关系。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-data
  labels:
    pv: mysql-pv-data
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /data/volumes/mysql-pv/data
    server: 10.100.100.91
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-data-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  selector:
    matchLabels:
      pv: mysql-pv-data
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-conf
  labels:
    pv: mysql-pv-conf
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /data/volumes/mysql-pv/conf
    server: 10.100.100.91
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-conf-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  selector:
    matchLabels:
      pv: mysql-pv-conf

数据持久化的下一步只需要在 deployment 资源定义中 对容器目录进行挂载就可以。

MySQL 部署

Deployment

Deployment 文件 mysql-dep.yaml ,pods 将调度到具有 mysql-dep=allow 标签的节点上。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql-dep
  labels:
    app: mysql-dep
spec:
  selector:
    matchLabels:
      app: mysql-dep
  strategy:
    type: RollingUpdate
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql-dep
    spec:
      containers:
      - image: mysql:5.7
        name: mysql-dep
        args:
          - "--ignore-db-dir=lost+found" 
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: mysql-root-password
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: mysql-password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage-data
          mountPath: /var/lib/mysql
        - name: mysql-persistent-storage-conf
          mountPath: /etc/mysql/conf.d
      volumes:
      - name: mysql-persistent-storage-data
        persistentVolumeClaim:
          claimName: mysql-pv-data-claim
      - name: mysql-persistent-storage-conf
        persistentVolumeClaim:
          claimName: mysql-pv-conf-claim
      nodeSelector:
        mysql-dep: allow     

在deployment中引用了 secret 对环境变量 MYSQL_ROOT_PASSWORD 和 MYSQL_PASSWORD 赋值。

这个部署方式存在环境变量无效的情况(数据库登录失败的问题),后面我们会详细介绍如何解决。

Secret

创建 Secret mysql-secret.yaml 密码部分使用 bsae64 编码。

**base64 编码**
echo '123456' | base64

**base64 解码**
echo 'MTIzNDU2Cg==' | base64 -d
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  mysql-root-password: MTIzNDU2Cg==
  mysql-password: MTIzNDU2Cg==
Service

Mysql service 服务 mysql-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
  labels:
    app: mysql-dep
spec:
  type: NodePort
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql-dep
Mysql 配置

部署完成后可以在集群中通过临时 pod 来访问 Mysql。

kubectl run -it --rm --image=mysql:5.6 --restart=Never -n zcfw mysql-client -- mysql -h mysql-svc -uroot -ppassword

此时会发现登录认证失败的问题。原因就是上面提到的环境变量 MYSQL_ROOT_PASSWORD 和 MYSQL_PASSWORD 无效导致的。

ERROR 1045 (28000): Access denied for user 'operator'@'10.244.0.91' (using password: YES)

需要修改配置文件 my.cnf 添加 skip-grant-tables 参数来跳过登录验证,重置 root 密码。

[mysqld]
skip-grant-tables

修改完配置文件后,到 Mysql pod 所在的 node 节点,重启 mysql 容器。

[root@node1 ~]# docker ps | grep mysql

024e80cfff80        cd3ed0dfff7e           "docker-entrypoint.s…"   11 hours ago        Up 10 hours                             k8s_mysql-dep_mysql-dep-7878b9c59b-hrzmc_default_5a381927-4503-43a7-babe-c3456c16b4c7_1

[root@node1 ~]# docker restart 024e80cfff80

也可直接进入 mysql 容器本地登录 mysql。

[root@node1 ~]# docker exec -it  024e80cfff80 bash

root@mysql-dep-7878b9c59b-hrzmc:/# mysql -uroot -p 

修改mysql root用户密码

登录进 mysql 之后,将 root 密码置空。

use mysql;

select user,authentication_string,host from user;

update user set authentication_string='' where user='root';

flush privileges;

然后退出 mysql,将 my.cnf 文件中 skip-grant-tables 参数注释掉,重启mysql容器。之后即可正常登录 mysql。

修改密码及授权。

alter user 'root'@'localhost' IDENTIFIED BY 'password';

GRANT ALL ON *.* TO 'root'@'localhost';

flush privileges;

附 my.cnf 配置文件

# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
#
[client]
default-character-set=utf8
#
[mysql]
default-character-set=utf8
#
# [mysqld]
# skip-grant-tables

# # Remove leading # and set to the amount of RAM for the most important data
# # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# # innodb_buffer_pool_size = 128M
# #
# # Remove leading # to turn on a very important data integrity option: logging
# # changes to the binary log between backups.
# # log_bin
# #
# # Remove leading # to set options mainly useful for reporting servers.
# # The server defaults are faster for transactions and fast SELECTs.
# # Adjust sizes as needed, experiment to find the optimal values.
# # join_buffer_size = 128M
# # sort_buffer_size = 2M
# # read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
#
# # Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

log-error=/var/lib/mysql/mysqld.log
pid-file=/var/lib/mysql/mysqld.pid
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8

至此 Mysql 初步部署已完成,后续还需要添加相应的 Ingress 服务。因为是测试所以数据库直接部署在 default namespaces 中,正式环境中还需要定义相应的 RBAC 资源。