CentOS 上部署 MariaDB 单机多实例

作者:wiLdGoose 发布时间:March 6, 2019 分类:技术 Technology

我使用的是 mysqld_multi 这种实现方式,每个实例有其独立的配置文件,适合强迫症患者服用。

首先配置 MariaDB 的官方 yum 源:

vim /etc/yum.repos.d/MariaDB.repo

在新建的文件中添加:

# MariaDB 10.3 CentOS repository list - created 2018-08-28 05:47 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

这里使用的是 MariaDB 10.3,当前貌似有 10.4 版本,可自行在官网查询。

完事儿之后就可以安装 MariaDB 了,这里采用二进制文件而非源码编译:

yum -y install MariaDB-server MariaDB-client

现在我准备部署三套 MariaDB 实例,具体是:

端口:3307,对应数据目录:/data/mysql/3307;
端口:3308,对应数据目录:/data/mysql/3308;
端口:3309,对应数据目录:/data/mysql/3309。

那么先来创建每个实例对应的目录:

mkdir -pv /data/mysql/330{7,8,9}

然后将这些目录所属修改到 MariaDB 用户与用户组:

chown -R mysql:mysql /data/mysql/330{7,8,9}

初始化数据目录:

mysql_install_db --datadir=/data/mysql/330{7,8,9}/data --basedir=/usr --user=mysql

好了,创建 MariaDB 配置文件:

vim /etc/my.cnf

在新建的文件中添加:

[mysqld_multi]
mysqld     = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
user       = multi_admin
password   = YOUR_PASSWORD

[mysqld3307]
socket     = /data/mysql/3307/mariadb.sock
port       = 3307
pid-file   = /data/mysql/3307/mariadb.pid
datadir    = /data/mysql/3307/data
user       = mysql

[mysqld3308]
socket     = /data/mysql/3308/mariadb.sock
port       = 3308
pid-file   = /data/mysql/3308/mariadb.pid
datadir    = /data/mysql/3308/data
user       = mysql

[mysqld3309]
socket     = /data/mysql/3309/mariadb.sock
port       = 3309
pid-file   = /data/mysql/3309/mariadb.pid
datadir    = /data/mysql/3309/data
user       = mysql

到这里,已经可以启动这三个实例:

mysqld_multi start 3307-3309

接着再做一些配置,请 One By One 地来:

mysql_secure_installation -S /data/mysql/3307/mariadb.sock
mysql_secure_installation -S /data/mysql/3308/mariadb.sock
mysql_secure_installation -S /data/mysql/3309/mariadb.sock

现在我们修改 root 密码,依然是 One By One:

mysqladmin -u root -p password -S /data/mysql/3307/mariadb.sock
mysqladmin -u root -p password -S /data/mysql/3308/mariadb.sock
mysqladmin -u root -p password -S /data/mysql/3309/mariadb.sock

创建一个 SQL 文件:

vim /data/src/create_user.sql

在新建的文件中添加:

CREATE USER 'multi_admin'@'localhost' IDENTIFIED BY 'YOUR_PASSWORD';
GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost';
flush privileges;

在每个实例中执行以创建多实例管理用户,嗯,One By One:

cat create_user.sql | mysql -u root -S /data/mysql/3307/mariadb.sock -p
cat create_user.sql | mysql -u root -S /data/mysql/3308/mariadb.sock -p
cat create_user.sql | mysql -u root -S /data/mysql/3309/mariadb.sock -p

然后再创建一个 sysv 脚本:

vim /etc/rc.d/init.d/mysqld_multi

在新建的文件中添加:

mysqld_multi=/usr/bin/mysqld_multi

instance_list="3307-3309"

start(){
    $mysqld_multi start $instance_list
}
stop(){
    $mysqld_multi stop $instance_list
}
status(){
    $mysqld_multi report
}
case "$1" in
    start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
start
stop
;;
*)
echo $"Usage: $0 {start|stop|status}"
exit 2
esac

接着添加 sysv:

chkconfig --add mysqld_multi

启用服务:

chkconfig mysqld_multi on

实现开机启动:

echo mysqld_multi start 3307-3309 >> /etc/rc.local

- EOF -

多台 CentOS 之间实现简单的文件共享

作者:wiLdGoose 发布时间:February 14, 2019 分类:技术 Technology

木有技术含量,仅为自己马克一下。

这里用到了 nfs 和 rpcbind 两个组件。首先在客户端与服务端机器上都安装 nfs-utils 和 rpcbind:

yum -y install nfs-utils rpcbind

服务端机器上若开启防火墙的话需添加对应规则或关闭防火墙。按顺序依次将 rpcbind 和 nfs 设置为自动启动:

systemctl enable rpcbind.service
systemctl enable nfs.service

在服务端机器上设置共享目录:

vim /etc/exports

在文件末尾追加:

/data/share 10.10.10.11(rw, sync, no_root_squash) 10.10.10.12(rw, sync, no_root_squash)

其中:

/data/share 为共享目录路径;
10.10.10.11 及 10.10.10.12 为客户端内网 IP,多个 IP 写在同一行。同网段需要使用 10.10.10.0/24 或 10.10.10.0/255.255.255.0 这两种方式,不能使用 10.10.10.*,会报 unmatched host 错误,具体可 cat /var/log/messages | grep mount 进行检查;
rw 为读写权限;
sync:数据暂存于内存中,而非直接写入磁盘;
no_root_squash:使用 root 身份时,其权限转换为匿名使用者,UID 与 GID 切换为 nobody 身份。

最后在服务端机器上按顺序依次启动相关服务:

systemctl start rpcbind.service
systemctl restart nfs.service

在客户端机器上查看服务端机器的共享目录:

showmount -e 10.10.10.10

然后在本机创建对应目录:

mkdir -p /share

进行挂载:

mount -t nfs 10.10.10.10:/data/share /share

并将上述挂载命令写入 /etc/rc.local 文件以实现自动挂载:

echo mount -t nfs 10.10.10.10:/data/share /share >> /etc/rc.local

这里不推荐直接修改 /etc/fstab 文件,以防止服务端出现问题或客户端与服务端之间网络出现问题时产生异常。

最后祝福各位今夜安全而愉快。

Git 仓库迁移历险记

作者:wiLdGoose 发布时间:December 17, 2018 分类:技术 Technology

前阵子折腾了一个 Git 仓库迁移,觉得有必要自行马克一下。

需求背景:老的版本库在一台 Windows 主机上,用 Gitblit 搭建;我在某云用一台独立主机新搭建了一套 Gitlab,前端由另一台主机部署 Nginx 反向代理。
需求内容:将老版本库的所有仓库平滑迁移到新的版本库中。
任务拆解:部署并配置 Gitlab、创建项目仓库、镜像推送、将原先指向到 Gitblit 的域名解析修改到 Gitlab、导入账户,完成。

在一切都顺利进行的时候遇到一个大小为 2G 多的仓库,零碎文件较多,最大的单文件也就几百兆。由于我本地没有这个仓库,于是:

$ git clone https://path.to.git/repo.git

进度到 20% 多的时候,死活就断开了,反复尝试无效:

Cloning into 'repo'...
remote: Counting objects: 27709, done
remote: Finding sources: 100% (27709/27709)
remote: Getting sizes: 100% (16855/16855)
remote: Compressing objects:  23% (69/300)
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

网上找到有人说需要更改一下 Git 客户端的上传限制大小:

$ git config http.postBuffer 524288000

或者直接修改 .gitconfig 文件,修改 [http] 段:

postBuffer = 524288000

好了,依然失败。万般无奈之下找同事 copy 了整个 Git 文件夹到我本地,修改 Git 用户配置文件,git pull,成功。接着修改配置文件到新的版本库地址,然后就是见证奇迹的时刻:

$ git push -u origin --all
Enumerating objects: 27705, done.
Counting objects: 100% (27705/27705), done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12552/12552), done.
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large
fatal: The remote end hung up unexpectedly
Writing objects: 100% (27705/27705), 1.97 GiB | 2.17 MiB/s, done.
Total 27705 (delta 12742), reused 27100 (delta 12209)
fatal: The remote end hung up unexpectedly
Everything up-to-date

与 clone 的时候一样,push 到一定程度就断开,反复尝试死活不行。想了半天不得其解,考虑到前端用 Nginx 做了反代,Google 之。有人说:

在服务器上面配置了 Nginx 之后,使用 Git 上传大文件的时候会出现“HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large”。

嗯,好像是找到问题了?于是修改 Nginx 的配置文件 nginx.conf,在 http 段加入:

client_max_body_size 1024m;

原文说 2m 够了,我贪心,直接加到 1024m。重启 Nginx,哈哈……特么的还是失败了。

眼睛盯着别人的仓库 URL 和我的 URL,总觉得哪里不对劲。原来 git@path.to.git/repo.git 走的是 SSH 协议,我的 https://path.to.git/repo.git 走的是 HTTP 协议。

改!一顿操作,改 sshd 端口号,配置 Gitlab 为 SSH 方式,到 Gitlab 后台对项目启用 SSH 方式,再次尝试……激动得眼泪都留下来了,成功。

结论:HTTP 协议不适合于大型项目的仓库,能走 SSH 就走 SSH 吧。

搭建基于 Nginx 反向代理与 Let's Encrypt 自动续期的前端服务

作者:wiLdGoose 发布时间:September 30, 2018 分类:技术 Technology

好久不在贵行混,殊不知原先那套 LAMP 或 LNMP 的架构早已奥特且随着岁月流逝慢慢发生了升级与变迁。

这次要玩的是一套提供前端服务的架构。大致交代一下故事背景:

1、负载机绑定了 1 个公网 IP 与 1 个私网 IP(VIP地址、私网 IP 漂移、HAProxy 高可用啥的需要运营商配合,正在准备,以后玩过了再写),部署 Nginx 用于反向代理;
2、前端服务所在主机与负载机在同一私网网段内。

好了,故事开始。

首先部署完负载机的 Nginx 服务,用于监听负载机的 TCP 80 及 443 端口。值得注意的是若使用源码编译方式安装 Nginx,记得添加:

--with-http_ssl_module --with-http_realip_module

其实直接 yum 也阔以。安装后对配置文件 nginx.conf 进行调整:

user www www;
worker_processes auto;
error_log /path/to/logs/error.log;
pid /path/to/logs/nginx.pid;
worker_rlimit_nofile 65535;
events {
    use epoll;
    worker_connections 65535;
}
http {
    include mime.types;
    default_type application/octet-stream;
    include /usr/local/nginx/conf/reverse-proxy.conf;
    sendfile on;
    keepalive_timeout 65;
    gzip on;
    client_max_body_size 50m; #缓冲区代理缓冲用户端请求的最大字节数,可以理解为保存到本地再传给用户
    client_body_buffer_size 256k;
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;
    proxy_connect_timeout 300s; #nginx跟后端服务器连接超时时间(代理连接超时)
    proxy_read_timeout 300s; #连接成功后,后端服务器响应时间(代理接收超时)
    proxy_send_timeout 300s;
    proxy_buffer_size 64k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
    proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
    proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
    proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传递请求,而不缓冲到磁盘
    proxy_ignore_client_abort on; #不允许代理端主动关闭连接
    server {
        listen 80;
        server_name _;
        location / {
            root html;
            index index.html index.htm;
        }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }
    }
}

记得打开防火墙端口,若还有上级网络安全策略等,更新配置。

前端机 Web 服务因人而异了,这里假定还是由 Nginx 提供前端服务,部署过程略,监听前端机的 TCP 80 端口。值得注意的是需要在 Nginx 配置文件中定义日志格式:

log_format access '$HTTP_X_REAL_IP - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $HTTP_X_Forwarded_For';
 
access_log /path/to/logs/access.log access;

在负载机上编辑反向代理的配置文件:

vim /usr/local/nginx/conf/reverse-proxy.conf

若有多个 server 可再行扩展:

server
{
    listen 80;
    server_name sub.domain.com;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://192.168.x.x;
    }
    access_log /path/to/logs/sub.domain.com_access.log;
}

截至目前,http 协议的转发已经完成。域名解析完成且生效后,访问应该会从负载机走私网定向到前端机。看了一圈日志没问题后,继续折腾 https。

SSL 证书提供商毫无疑问是 Let's Encrypt。据我所知有 certbot-auto 与 acme.sh 两种方式来实现证书自动申请与续展,前者貌似只能支持单个域名,而后者目前已支持泛域名证书。因此我选择后者。

配置过程就不展开了,中文版引导在这里。值得注意的是,若使用 certbot-auto,则需要修改负载机 Nginx 的反向代理配置文件,将 .well-known 目录指向本地:

server {
    listen 80;
    server_name sub.domain.com;
    […]
    location /.well-known {
            alias /path/to/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

若使用 acme.sh,则既可通过 .well-known 目录来验证,也可通过 DNS 解析来验证(需提前向域名注册商申请 API)。可参考这里

好了,到这里,证书更新的事儿也是自动的。

去喝杯咖啡吧~

Update:

已实现客户端到负载机的访问是公网 https,负载机转发到前端机走私网 http。已遇到一个问题,最新版的 phpMyAdmin 会提示:

服务器和客户端上指示的 HTTPS 之间不匹配。这可能导致 phpMyAdmin 无法正常工作或存在安全风险。请修复您的服务器配置以正确指示 HTTPS。

嗯~有待进一步解决。

Update:

上述问题解决方案:在 phpMyAdmin 的配置文件中添加:

$cfg['PmaAbsoluteUri'] = 'https://pma.xxx.com';

即可。

通过 LVM 对 CentOS 磁盘分区进行动态扩容

作者:wiLdGoose 发布时间:September 27, 2018 分类:技术 Technology

还是那堆联通云机,交付前 LVM 也不给搞好,云盘默认也不挂载,特别吐槽一下。怀念某云的傻瓜式服务,前者到底是国有,揍是硬气。

这是扩容前的情况:

[root@centos7 ~]# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/rootvg-rootlv   10G   10G   20K 100% /
devtmpfs                   3.9G     0  3.9G   0% /dev
tmpfs                      3.9G     0  3.9G   0% /dev/shm
tmpfs                      3.9G  369M  3.5G  10% /run
tmpfs                      3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/vda1                  485M  166M  319M  35% /boot
tmpfs                      783M     0  783M   0% /run/user/0

用 vgs 和 lvs 看一下可用空间,并根据实际情况构造如下命令:

[root@centos7 ~]# lvresize -L +37.51G /dev/rootvg/rootlv
  Rounding size to boundary between physical extents: 37.51 GiB.
  Size of logical volume rootvg/rootlv changed from 10.00 GiB (2560 extents) to 47.51 GiB (12163 extents).
  Logical volume rootvg/rootlv successfully resized.

最后同步一下文件系统就搞定了:

[root@centos7 ~]# xfs_growfs /dev/rootvg/rootlv
meta-data=/dev/mapper/rootvg-rootlv isize=512    agcount=4, agsize=655360 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=2621440, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2621440 to 12454912

验证:

[root@centos7 ~]# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/rootvg-rootlv   48G  9.8G   38G  21% /
devtmpfs                   3.9G     0  3.9G   0% /dev
tmpfs                      3.9G     0  3.9G   0% /dev/shm
tmpfs                      3.9G  369M  3.5G  10% /run
tmpfs                      3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/vda1                  485M  166M  319M  35% /boot
tmpfs                      783M     0  783M   0% /run/user/0

自己马克一下。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. ...
  7. 13