双 Debian 服务器

双 Debian 服务器

我有两个 debian 服务器,第一个是操作服务器(主服务器),后者用于安全目的。

我希望第二台服务器能够像第一台服务器的孪生兄弟一样,不断地对其进行 rsync 操作,以便在第一台服务器出现故障时能够切换到第二台服务器。

我正在考虑每晚同步它们,方式如下:

在 rsync 脚本中,我对 IP 进行了控制,只有当我在主服务器上时才会激活脚本。

我的问题是在整个过程中我应该关心什么:

  • 也许一些 /etc/ 文件要从同步中排除?passwd 和 shadow?但我希望有一些新用户从主服务器传播到从属服务器
  • 也许需要同步其他目录?

任何帮助都将不胜感激!

答案1

你基本上想问的是如何建立一个系统,使我可以拥有与生产环境相同的开发环境以进行安全审计、测试等?

上面的两条评论分别提供了一半的答案:


对于服务器配置和软件/补丁
你可能想要类似的东西木偶/厨师/管理者
这些工具可用于确保您的服务器是“相同的” - 运行相同的软件,具有相同的配置(或“足够相似的配置,差异并不重要” - 即仅在 IP 地址、SSL 证书等方面有所不同)

您还可以在此处管理类似操作/etc/passwd以确保用户(用户名和数字 UID/GID)在机器之间同步并且所有内容匹配。


对于您的软件本身(/var/www在上面的例子中)
您肯定希望在这里安装某种版本控制系统。
您可以直接将内容签出到每台机器上,也可以使用上面提到的工具进行打包和分发。

这两种处理软件的方式各有优缺点,您可以根据自己的需求来决定使用哪种方式。
一种典型的划分方式是“如果需要编译,则应打包并分发。如果是脚本和数据,则可以直接签出。”

答案2

至少我生成并测试了我自己的脚本:它运行完美!

我希望它可以帮助别人!

#!/bin/bash
# A Script which syncronizes debian packages from this server to a second server
# ssh must be able to log from user root to user root with key without password
# Execute as root

# included file defines mysql credentials:
# $MYSQL_USR, $MYSQL_PSW for backing up mysql
# $SERVER2_MYSQL_USR, $SERVER2_MYSQL_PS for inserting dumps on $SERVER2's mysql (root credentials)
# it defines $MAIL and $SERVER2, too
. /etc/bin/mysql_secrets

# the script which will be executed on SERVER2
SCRIPT=/root/aptshell.sh

# files to generate in order to sync the packages
list_installed_on_second_server=/root/installed_packages_on_$SERVER2
list_manually_installed_on_second_server=/root/installed_packages_manually_on_$SERVER2

# the timeout for package install on SERVER2: we must set it because some install keeps waiting for a user answer even if the -y option is given to aptitude install
TIMEOUT=120

# the directory where mysql backups are stored
MYSQL_BACKUPS_DIR='/var/backups/dbbackups'
# if the directory doesn't exist, create it
/bin/mkdir -p ${MYSQL_BACKUPS_DIR}

NICE='/usr/bin/nice -n 19'

# file which lists the files in /etc not to rsync to SERVER2
EXCLUDE_ETC_FILES=/etc/bin/rsync_etc.exclude.conf

# Don't execute this script on SERVER2
echo $SERVER2 | grep `hostname` > /dev/null && exit 0

# this variable prevents apt-get/aptitude to run interactively
export DEBIAN_FRONTEND=noninteractive

# reset the script on SERVER2
rm $SCRIPT
touch $SCRIPT

shopt -s expand_aliases
alias date='date +"%H:%M.%S"'

echo "===================================================================="
date
echo "Executing apt-get update on $SERVER2"
echo "===================================================================="
echo
ssh $SERVER2 $NICE /usr/bin/aptitude -q update > /dev/null || { echo && echo "APT-GET UPDATE ERROR - STOPPING SCRIPT AND EXITING" && rm $SCRIPT && exit 1; }

echo "===================================================================="
date
echo "Generating installed packages lists on $SERVER2"
echo "===================================================================="
echo
ssh $SERVER2 $NICE "/usr/bin/aptitude -F '%p' --disable-columns search '~i !~M' > $list_manually_installed_on_second_server"
ssh $SERVER2 $NICE "/usr/bin/aptitude -F '%p' --disable-columns search '~i' > $list_installed_on_second_server"

echo 'echo' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "Begin script execution on '$SERVER2'"' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo' >> $SCRIPT

echo "===================================================================="
date
echo "Generating list of packages remove commands for $SERVER2"
echo "===================================================================="
echo
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "Removing from '$SERVER2' the packages not on '`hostname`'"' >> $SCRIPT
# insert in script the command which remove from SERVER2 the packages non installed here and installed there
$NICE /usr/bin/aptitude  --disable-columns search . | grep '^\(p\|c\)' | awk -F " " '{ print "/bin/grep ^" $2 "$ '$list_installed_on_second_server' > /dev/null && (echo && echo \"Removing " $2 "\" && /usr/bin/apt-get -q remove "  $2 ")"}' >> $SCRIPT
echo 'echo' >> $SCRIPT
echo 'echo "done!"' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo' >> $SCRIPT

echo "===================================================================="
date
echo "Generating packages autoremove commands for $SERVER2"
echo "===================================================================="
echo
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "Autoremoving packages on ' $SERVER2 '..."' >> $SCRIPT
echo 'apt-get -q autoremove > /dev/null' >> $SCRIPT
echo 'echo "done!"' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo' >> $SCRIPT

echo "===================================================================="
date
echo "Generating list of packages install commands for $SERVER2"
echo "===================================================================="
echo
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "Installing on '$SERVER2' the packages present on '`hostname`'"' >> $SCRIPT
# insert in script the command which install on SERVER2 the packages installed here and not there
$NICE /usr/bin/aptitude -F "%p" --disable-columns search '!~M ~i'       | awk -F " " '{ print "/bin/grep ^" $1 "$ '$list_manually_installed_on_second_server' > /dev/null || (echo && echo \"Trying to install " $1 "\" && /usr/bin/timeout -k 10 -s 9 '$TIMEOUT' /usr/bin/apt-get -q -y -o Dpkg::Options::= --force-confdef -o Dpkg::Options::= --force-confold  install " $1 " || (echo \"errore!\" && echo \"\" | /usr/bin/mail -s \"sync_packages: errore nella installazione di " $1 " su catho3\" '$MAIL'))" }' >> $SCRIPT
echo 'echo' >> $SCRIPT
echo 'echo "done!"' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo' >> $SCRIPT

echo 'echo "==========================="' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "End script execution on '$SERVER2'"' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo "==========================="' >> $SCRIPT
echo 'echo' >> $SCRIPT

echo "===================================================================="
date
echo "Copying script to $SERVER2"
echo "===================================================================="
scp $SCRIPT $SERVER2:$SCRIPT > /dev/null

# exec script on SERVER2
ssh $SERVER2 sh $SCRIPT

# /etc/ isn't 'git updated' because etckeeper does the job

echo "===================================================================="
date
echo "Sync /etc"
echo "===================================================================="
echo
# save old /etc on SERVER2
ssh $SERVER2 $NICE /usr/bin/rsync -avq --delete /etc/ /etc.old
# sync /etc
$NICE /usr/bin/rsync --delete -avzq --exclude-from=$EXCLUDE_ETC_FILES -e ssh /etc/ $SERVER2:/etc


echo "===================================================================="
date
echo "Execute mysql backups, sync them to $SERVER2 and import them on $SERVER2's mysql"
echo
echo "1. Cycle on the db's and dump them"
echo "   "`date`
echo
for DB in $(/usr/bin/mysql --user=$MYSQL_USR --password=$MYSQL_PSW -e 'show databases' -s --skip-column-names | grep -viE '(staging|performance_schema|information_schema)' )
do
    echo "   $DB"

    if [ $DB = 'mysql' ]
    then
        EVENTS='--events'
    else
        EVENTS=''
    fi

    # don't compress: backups are kept in a git repository
    /usr/bin/nice -n 19 \
    /usr/bin/mysqldump --user=$MYSQL_USR --password=$MYSQL_PSW $EVENTS --skip-opt --no-autocommit --extended-insert --add-drop-table --add-locks --create-options --disable-keys --complete-insert --lock-tables --quick --default-character-set='utf8' --databases $DB > $MYSQL_BACKUPS_DIR/$DB.sql

    # in case of error, report it
    if [ $? -ne 1 ]
    then
        sed -i '1s/^/SET FOREIGN_KEY_CHECKS=0;\n/' $MYSQL_BACKUPS_DIR/$DB.sql
        echo 'SET FOREIGN_KEY_CHECKS=1;' >> $MYSQL_BACKUPS_DIR/$DB.sql
    else
        echo "Error dumping $DB db"
    fi
done

echo
echo "2. Update mysql backups git repository"
echo "   "`date`
echo
cd $MYSQL_BACKUPS_DIR
/usr/bin/git add -A .
/usr/bin/git commit -q -a -m 'notturno'

echo
echo "3. Sync mysql backups from here to $SERVER2"
echo "   "`date`
echo
$NICE /usr/bin/rsync --delete -avq -e ssh $MYSQL_BACKUPS_DIR/ $SERVER2:$MYSQL_BACKUPS_DIR

echo
echo "4. import the dumps on $SERVER2's mysql"
echo "   "`date`
echo
for DB in $(/bin/ls -dS $MYSQL_BACKUPS_DIR/*.sql)
do
    echo "   "`date`
    echo "   $DB"
    NUMLINES=`git diff -U0 HEAD HEAD^ $DB | wc -l`
    if [ $NUMLINES -gt 7 ]
    then
        echo
        ssh $SERVER2 "$NICE /usr/bin/mysql -u $SERVER2_MYSQL_USR -p$SERVER2_MYSQL_PSW < $DB"
    else
        echo "     *** No change: skipped"
        echo
    fi
done

echo "===================================================================="
date
echo "Update /var/wwwc git repository"
echo "===================================================================="
echo
cd /var/wwwc
/usr/bin/git add -A .
/usr/bin/git commit -q -a -m 'notturno'

echo "===================================================================="
date
echo "Sync /var/wwwc to $SERVER2"
echo "===================================================================="
echo
$NICE /usr/bin/rsync --delete -avzq -e ssh /var/wwwc/ $SERVER2:/var/wwwc

echo "===================================================================="
date
echo "Update /var/wwwc git repository"
echo "===================================================================="
echo
cd /var/wwwq
/usr/bin/git add -A .
/usr/bin/git commit -q -a -m 'notturno'

echo "===================================================================="
date
echo "Sync /var/wwwq to $SERVER2"
echo "===================================================================="
echo
$NICE /usr/bin/rsync --delete -avzq -e ssh /var/wwwq/ $SERVER2:/var/wwwq

echo "===================================================================="
date
echo "Sync /usr/share/gitweb directory"
echo "===================================================================="
echo
$NICE /usr/bin/rsync --delete -avzq -e ssh /usr/share/gitweb/ $SERVER2:/usr/share/gitweb

echo "===================================================================="
echo "Create missing /var/cache/* directories on $SERVER2 and set proper owner"
echo "===================================================================="
echo

for DIR in $(/bin/ls -d -1 /var/cache/*)
do
    OWNER=`ls -ld $DIR  | awk '{print $3}'`
    #echo $DIR $OWNER
    ssh -n $SERVER2 /bin/mkdir -p $DIR
    ssh -n $SERVER2 /bin/chown $OWNER:$OWNER $DIR
done

echo "===================================================================="
date
echo -n "Reboot $SERVER2? "
# Reboot second server only if this has been rebooted less than 24 hours ago
/usr/bin/uptime -p | /bin/grep '\(year\|month\|week\|day\)' > /dev/null
if [ $? -ne 0 ] ; then
    echo "Yes!!!!!"
    ssh $SERVER2 /sbin/reboot
else
    echo "No"
    echo
    echo "===================================================================="
    date
    echo "Restart services on $SERVER2"
    echo "===================================================================="
    echo
    # I must restart various service, in the case their config files have changed
    for SERVICE in apache2 varnish mysql memcached dovecot postfix fail2ban
    do
        echo $SERVICE restarted
        ssh $SERVER2 $NICE /usr/sbin/service $SERVICE restart
    done

    echo
    echo "===================================================================="
    date
    echo "Script ended"
    echo "===================================================================="
fi

批判的、etc 中一定不能同步的文件:rsync_etc.exclude.conf 文件:

/.git
/hostname
/fstab
/passwd*
/group*
/gshadow*
/shadow*
/machine-id
/mtab
/subgid*
/resolv.conf
/udev/rules.d/70-persistent-net.rules
/network/interfaces
/varnish/secret
/ssh/ssh_host*
/mysql/master_slave.cnf

答案3

只需同步包和数据。无需克隆每个文件。

相关内容