实现sftp高可用

Keepalived+rsync+ZK实现sftp高可用方案

文章目录

  • Keepalived+rsync+ZK实现sftp高可用方案
  • 前言
  • 一、配置SFTP
    • 1.2 配置SFTP
    • 1.2 创建SFTP用户专属的目录
    • 1.3 配置SFTP配置文件
    • 1.4重启服务
    • 1.5如法炮制
    • 1.6测试
  • 二.Keepalived
    • 2.1安装
    • 2.2backup1的配置
    • 2.2 backup2的配置
    • 启动keepalived
  • 三.rsync
    • 3.1配置rsync
    • 3.2配置用户文件
    • 3.3启动服务
    • 3.4查看与测试
  • 四.单向同步脚本
    • 4.1backup2脚本
    • 4.2 backup1配置
    • 4.3定时调用
    • 4.看日志


前言

想搞过一个sftp 服务的高可用,然后rsync能实现相互通信,以保证数据有序同步。

一、配置SFTP

先创建个用户

1.2 配置SFTP

#用户名hsi_ftp可以改
groupadd sftp
[root@localhost ~]# groupadd sftp
[root@localhost ~]# useradd -g sftp -s /sbin/nologin -M sftpuser
[root@localhost ~]# passwd sftpuser
Changing password for user sftpuser.
New password: 
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 
passwd: all authentication tokens updated successfully.

1.2 创建SFTP用户专属的目录

[root@localhost ~]# mkdir -p /data/sftp/sftpuser
[root@localhost ~]# usermod -d /data/sftp/ sftpuser
[root@localhost ~]# chown root:sftp /data/sftp/
[root@localhost ~]# chown sftpuser:sftp /data/sftp/sftpuser/

1.3 配置SFTP配置文件

[root@localhost ~]# vim /etc/ssh/sshd_config
#Subsystem      sftp    /usr/libexec/openssh/sftp-server
Subsystem       sftp    internal-sftp
Match Group sftp
ChrootDirectory /data/sftp
ForceCommand    internal-sftp
AllowTcpForwarding no 
X11Forwarding no

1.4重启服务

[root@localhost ~]# systemctl restart sshd

1.5如法炮制

另选一台也如上面的方式创建用户与配置服务,如果有需要还需要在

1.6测试

C:\Users\cheng>sftp [email protected]
[email protected]'s password:
Connected to [email protected].
sftp> ls
test
sftp>

二.Keepalived

2.1安装

yum install -y keepalived

2.2backup1的配置

选其中的一个节点node1

[root@hadoop05 /]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server smtp.xxx.com
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
  # vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 53
    priority 100
    nopreempt
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.5.16
    }
}

2.2 backup2的配置

选其中的一个节点node2

[root@hadoop03 /]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server smtp.xxx.com
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
  # vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 53
    priority 100
    nopreempt
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.5.16
    }
}

启动keepalived

systemctl start keepalived
systemctl enable keepalived

三.rsync

3.1配置rsync

两台服务器都得配置

[root@hadoop03 /]# cat  /etc/rsyncd.conf 
# /etc/rsyncd: configuration file for rsync daemon mode

# See rsyncd.conf man page for more options.

# configuration example:

# uid = nobody
# gid = nobody
# use chroot = yes
# max connections = 4
pid file = /var/run/rsyncd.pid
# exclude = lost+found/
# transfer logging = yes
# timeout = 900
# ignore nonreadable = yes
# dont compress   = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

# [ftp]
#        path = /home/ftp
#        comment = ftp export area
#
[webgis]
path=/data/sftp/sftpuser
uid=sftpuser
gid=sftp
read only= false

3.2配置用户文件

将用户的密码与名字写到指定的位置

[root@hadoop03 ~]# cat  sftppassword/sftppassword
sftpuser:123456

3.3启动服务

[root@hadoop03 ~]# systemctl  start rsyncd
[root@hadoop03 ~]# systemctl  enable  rsyncd

3.4查看与测试

[root@hadoop03 ~]# systemctl status rsyncd

[root@hadoop03 ~]# rsync -auz   /data/sftp/sftpuser/*  [email protected]::webgis    --password-file=sftppassword/sftppassword

四.单向同步脚本

恰好集群有zookeeper组件,再在两台机器上各装一个客户端就好。
(1)主要利用了ZK让rsync做到半双工通信的方式。(听说两边同时同步容易导致文件损坏,没测试,反正我还是喜欢有序地同步数据
(2) 利用ZK禁止在定时调度的时候不能被多个进程同时调用rsync服务。

4.1backup2脚本

要保证rsync_signal目录不为空,起码有一个${curNode}_node_sync_finished数据

[root@hadoop03 hsi_ftp]# cat /sftp_data_rsync.sh 
#!/bin/bash
#
# 这个脚本用来同步数据。
# (1)然后需要手动在ZK上创建一个节点/keepalived/rsync_signal。
# (2)还需要创建节点/keepalived/backup1
# (3)还需要创建节点/keepalived/backup2
#
. /etc/profile
. /root/.bash_profile
## 
curNode=backup2
anoNode=backup1
zkClient=/opt/apache-zookeeper-3.6.2-bin/bin/zkCli.sh
vip=192.168.5.16
user=sftpuser
srcPath=/data/sftp/$user/
destIp=192.168.5.5
module=webgis
pwdFile=/root/sftppassword/sftppassword
signalPath=/keepalived/rsync_signal
signal=$(bash $zkClient  get $signalPath )
#可以确定当前是哪个KL对外提供服务
services2user=$(ip addr|grep $vip |wc -l)
#master每同步10次就礼让给slave同步一次
nodePath=/keepalived/$curNode
maxTimes=10
getCurrentSyncTimes(){
preffixNum=1373736
  startNum=1373736000
   maxNum=$(( $startNum + $maxTimes ))
rsyncTimes=$(bash $zkClient  get $nodePath |grep $preffixNum )
if [[ $rsyncTimes == "" ]];then
   bash $zkClient  set  $nodePath  $startNum >/dev/null 2>&1
elif [[ $rsyncTimes -ge $maxNum  ]];then
   bash $zkClient  set  $nodePath  $startNum >/dev/null 2>&1
else
  rsyncTimes=$(( rsyncTimes + 1 ))
  bash $zkClient  set  $nodePath  $rsyncTimes >/dev/null 2>&1
fi

totalTimes=$(($rsyncTimes - $startNum))
echo $totalTimes

}

#main
   #说明当前服务已经停止了,所以需要将后续没有同步的数据进行同步到backup节点上。
if [[  $services2user -eq 0   ]]; then
	if [[  $signal =~ $curNode ||$signal =~ "${anoNode}_node_stop" ]]; then
            	echo "停止前最后一次发送数据, $signal"
       	    	rsync -auz   $srcPath  $user@$destIp::$module    --password-file=$pwdFile
        	#通知另一个节点可以同步数据了
        	bash $zkClient  set $signalPath "${curNode}_node_stop" >/dev/null 2>&1
        fi
else
          echo "正在发送数据 $signal"       
          #isEmpty=$(echo  $signal | grep $anoNode)        
     	if [[ $signal =~ "${curNode}_node_sync_finished" || $signal =~ "${anoNode}_node_stop"  ]];then
                echo "正在发送数据"
         	bash $zkClient  set $signalPath "${curNode}_node_synchronizing" >/dev/null 2>&1
         	rsync -auz   $srcPath  $user@$destIp::$module    --password-file=$pwdFile
        	 curTotalTimes=$(getCurrentSyncTimes)
                echo "第$curTotalTimes次发送"
                if [[ $curTotalTimes -ge $maxTimes ]];then
                      echo  "让另一个节点执行一次"
                        bash $zkClient  set $signalPath "${curNode}_node_stop" >/dev/null 2>&1
                else
                        bash $zkClient  set $signalPath "${curNode}_node_sync_finished" >/dev/null 2>&1
                fi
    	
        fi
fi

4.2 backup1配置

[root@hadoop05 hsi_ftp]# cat /sftp_data_rsync.sh
#!/bin/bash
#
# 这个脚本用来同步数据。
# (1)然后需要手动在ZK上创建一个节点/keepalived/rsync_signal。
# (2)还需要创建节点/keepalived/backup1
# (3)还需要创建节点/keepalived/backup2
#
. /etc/profile
. /root/.bash_profile
## 
curNode=backup1
anoNode=backup2
zkClient=/opt/apache-zookeeper-3.6.2-bin/bin/zkCli.sh
vip=192.168.5.16
user=sftpuser
srcPath=/data/sftp/$user/
destIp=192.168.5.3
module=webgis
pwdFile=/root/sftppassword/sftppassword
signalPath=/keepalived/rsync_signal

#用于解决哪怕定时器到了也只能有一个脚本同步数据
signal=$(bash $zkClient  get $signalPath )
#可以确定当前是哪个KL对外提供服务
services2user=$(ip addr|grep $vip |wc -l)
nodePath=/keepalived/$curNode
#master每同步10次就礼让给slave同步一次
maxTimes=10
getCurrentSyncTimes(){
preffixNum=1373736
  startNum=1373736000
   maxNum=$(( $startNum + $maxTimes ))
rsyncTimes=$(bash $zkClient  get $nodePath |grep $preffixNum )
if [[ $rsyncTimes == "" ]];then
   bash $zkClient  set  $nodePath  $startNum >/dev/null 2>&1
elif [[ $rsyncTimes -ge $maxNum  ]];then
   bash $zkClient  set  $nodePath  $startNum >/dev/null 2>&1
else
  rsyncTimes=$(( rsyncTimes + 1 ))
  bash $zkClient  set  $nodePath  $rsyncTimes >/dev/null 2>&1
fi

totalTimes=$(($rsyncTimes - $startNum))
echo $totalTimes

}


#main

#说明当前服务已经停止了,所以需要将后续没有同步的数据进行同步到另一个backup节点上。
if [[  $services2user -eq 0   ]]; then
	if [[  $signal =~ $curNode ||$signal =~ "${anoNode}_node_stop" ]]; then
                echo "停止前最后一次发送数据, $signal"
                rsync -auz   $srcPath  $user@$destIp::$module    --password-file=$pwdFile
                #通知另一个节点可以同步数据了
                bash $zkClient  set $signalPath "${curNode}_node_stop" >/dev/null 2>&1
        fi

else
        
               echo "正在发送数据 ,当前信号--$signal" 
     	if [[ $signal =~ "${curNode}_node_sync_finished" || $signal =~ "${anoNode}_node_stop"  ]];then
               
         	bash $zkClient  set $signalPath "${curNode}_node_synchronizing" >/dev/null 2>&1
         	rsync -auz   $srcPath  $user@$destIp::$module    --password-file=$pwdFile
                curTotalTimes=$(getCurrentSyncTimes)
                
                echo "第$curTotalTimes次发送"
                if [[ $curTotalTimes -ge $maxTimes ]];then
                      echo  "让另一个节点执行一次"
                      	bash $zkClient  set $signalPath "${curNode}_node_stop" >/dev/null 2>&1
                else
                       	bash $zkClient  set $signalPath "${curNode}_node_sync_finished" >/dev/null 2>&1
                fi
        fi
fi

4.3定时调用

[root@hadoop03 /]# crontab -e

  *  *  *  *  *  sh /sftp_data_rsync.sh>>/tmp/synclog.log
  *  *  *  *  *  sleep 10 ; sh /sftp_data_rsync.sh>>/tmp/synclog.log
  *  *  *  *  *  sleep 20 ; sh /sftp_data_rsync.sh>>/tmp/synclog.log
  *  *  *  *  *  sleep 30 ; sh /sftp_data_rsync.sh>>/tmp/synclog.log
  *  *  *  *  *  sleep 40 ; sh /sftp_data_rsync.sh>>/tmp/synclog.log
  *  *  *  *  *  sleep 50 ; sh /sftp_data_rsync.sh>>/tmp/synclog.log

4.看日志

查看节点信息

[root@hadoop05 hsi_ftp]# tail  -n 400  /tmp/synclog.log |grep backup
backup1_node_stop
backup2_node_stop
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_sync_finished
backup1_node_stop

你可能感兴趣的:(linux,sftp,keepalived)