Evitando acesso ao servidor (Git / ssh) durante o instantâneo do LVM

1

Se uma operação do Git estiver em andamento no momento de uma captura instantânea do LVM, o repositório poderá (e será) capturado em um estado corrompido. (Isso foi discutido muito link )

A questão é como resolver isso corretamente. O acesso ao Git é via git-shell via ssh (com chaves) para uma máquina linux. Parar o acesso por cerca de 20 minutos por noite não é um problema para o nosso departamento, mas temo que o diabo esteja nos detalhes.

O que eu fiz até agora me faz sentir que estou reinventando uma roda que eu não conheço. de um trabalho cron:

#!/bin/bash
# 0.
# poll during 20 min for ongoing git usage to stop
countdown=$((60*20))
while pgrep -u git >/dev/null ; do
    sleep 1
    countdown=$((countdown-1))
    if [ $countdown -eq 0 ] ; then 
       break
    fi
done

#1
#disable login to the git user by setting the shell to /bin/nologin
chsh -s /bin/nologin git

#2
# 
# wait again for up to 20 min for all processes to complete 
# (we *may* have just missed it between step 1 and 2)
#
countdown=$((60*20))
while pgrep -u git >/dev/null ; do
    sleep 1
    countdown=$((countdown-1))
    if [ $countdown -eq 0 ] ; then 
       break
    fi
done

#3
# kill too slow git sessions (This is actually safe)
if pgrep -u git >/dev/null ; then
    killall -u git 
    sleep 30 
fi
if pgrep -u git >/dev/null ; then
    killall -9 -u git 
    sleep 10
fi
if pgrep -u git >/dev/null ; then
    echo Failed to kill stale git $(pgrep -u git)
fi

#4
# make the lvm snapshot ...

#5
# change back the shell
chsh -s /usr/bin/git-shell git

Estou interessado em saber se existem mais soluções padrão ou se minha solução é falha.

Algo sobre a abordagem parece muito hackeado à mão. Eu também não gosto de pensar em casos como processos defuntos. Além disso, o servidor pode ficar inoperante durante o script, então eu teria que voltar o shell para o git-shell para reparar isso (via cron ou boot).

    
por Johan Lundberg 09.06.2013 / 11:07

3 respostas

2

Acho que a maneira correta é usar uma estratégia de backup mais apropriada. Por que você usaria instantâneos do LVM, quando você pode apenas fazer backup usando o próprio git?

Simle, exemplo não testado

#!/bin/sh
cd /backups/git
for repo in $(ssh repo_host ls /srv/git); do
    if [ ! -e $repo ]; then
        git clone --mirror repo_host:/srv/git/$repo
    else
        (cd $repo; git fetch origin)
    fi
done
    
por 09.06.2013 / 11:30
1

Por que você não bloqueia logins ssh para o período? adicione ao sshd_config:

#DenyGroups <a supplementary group for all git users>

depois, no início do seu cronjob de backup:

sed -i -e 's/^#DenyGroups/DenyGroups/' sshd_config
kill -HUP /var/run/sshd.pid

e inverta quando terminar. Para os usuários atualmente logados, não conheço outras opções, mas mato suas sessões de forma semelhante ao que você já faz. Ou espere até que eles saiam.

    
por 09.06.2013 / 11:16
1

Não tenho conhecimento de uma solução padronizada para isso e sua abordagem parece razoável para mim. Algumas ressalvas:

  1. Eu daria um passo adiante e bloquearia todos os logins não-root, já que você realmente não deseja que os usuários façam login e façam coisas com seu armazenamento enquanto suas operações de LVM são executadas. Felizmente, isso é bem simples com /etc/nologin , desde que sua configuração do PAM em /etc/pam.d inclua pam_nologin.so . Muitas distros fazem, mas você vai querer testar. man pam_nologin para detalhes.

  2. Use pkill em vez de um pgrep + killall. Ele usa o mesmo processo de correspondência e lógica de código de retorno como pgrep.

  3. Você está redirecionando STDOUT, mas não STDERR. Um truque que eu uso é incluir blocos de comandos para serem redirecionados em {} colchetes e redirecionando a saída dos colchetes. Apenas lembre-se de que esses colchetes exigem um retorno ou ; após o último comando, se você estiver fazendo uma única linha.

Exemplo de # 3:

{
    echo foo
    echo bar >&2 # output bar to STDERR
} >/dev/null 2>&1
    
por 09.06.2013 / 19:34

Tags