Como executar o failover de trabalhos cron?

8

Usando dois servidores Debian, preciso configurar um ambiente de failover forte para tarefas cron que só podem ser chamadas em um servidor por vez.

Mover um arquivo no /etc/cron.d deve funcionar, mas existe uma solução simples de alta disponibilidade para operar essa ação? E se possível, não com batimentos cardíacos;)

Falken
fonte
Para constar, eu finalmente usei o batimento cardíaco para fazer o trabalho. Existe uma solução mais fácil, no entanto, se suas máquinas estiverem na mesma sub-rede e puderem fazer multicast, eu recomendaria o uso do ucarp. Muito mais simples do batimento cardíaco -> ucarp.org
Falken
11
rcron? Gnubatch? Fantoche?
symcbean
Eu segundo rcron. Atualmente, estou usando e tenho quase a mesma configuração (2 servidores ubuntu atrás de um loadbalancer).
Ali

Respostas:

5

Eu acho que os batimentos cardíacos / marcapasso seriam a melhor solução, pois eles podem cuidar de muitas condições de corrida, esgrima etc. para você, a fim de garantir que o trabalho seja executado apenas em um host por vez. É possível projetar algo você mesmo, mas provavelmente não será responsável por todos os cenários desses pacotes, e você acabará substituindo a maior parte, se não toda, a roda.

Se você realmente não se importa com essas coisas e deseja uma configuração mais simples. Sugiro escalonar os trabalhos cron nos servidores por alguns minutos. Então, quando o trabalho é iniciado no primário, ele pode, de alguma forma, deixar um marcador em qualquer recurso compartilhado em que os trabalhos operam (você não especifica isso, por isso estou sendo intencionalmente vago). Se for um banco de dados, eles podem atualizar um campo em uma tabela ou, se estiver em um sistema de arquivos compartilhado, bloquear um arquivo.

Quando o trabalho é executado no segundo servidor, ele pode verificar a presença do marcador e cancelar se ele estiver lá.

Kamil Kisiel
fonte
1

Utilizamos duas abordagens, dependendo dos requisitos. Ambos envolvem ter os crons presentes e funcionando em todas as máquinas, mas com um pouco de verificação de sanidade envolvida:

  1. Se as máquinas estiverem em um relacionamento primário e secundário (pode haver mais de um secundário), os scripts serão modificados para verificar se a máquina em que estão executando é um estado primário. Caso contrário, eles simplesmente saem silenciosamente. Não tenho uma configuração da HB disponível no momento, mas acredito que você pode consultar a HB para obter essas informações.

  2. Se todas as máquinas forem elegíveis primárias (como em um cluster), será utilizado algum bloqueio. Por meio de um banco de dados compartilhado ou arquivo PID. Apenas uma máquina obtém o status de bloqueio e as que não saem silenciosamente.

Dan Carley
fonte
1

Para encurtar a história, você precisa transformar seus scripts cron em algum tipo de aplicativo capaz de cluster. Sendo a implementação leve ou pesada, você ainda precisa de uma coisa: poder retomar / reiniciar adequadamente a ação (ou recuperar seu estado) após o failover do nó primário. O caso trivial é que eles são programas sem estado (ou programas "sem estado o suficiente"), que podem ser simplesmente reiniciados a qualquer momento e funcionam perfeitamente. Provavelmente esse não é o seu caso. Observe que, para programas sem estado, você não precisa de failover porque você pode simplesmente executá-los em paralelo em todos os nós.

Em casos normalmente complicados, seus scripts devem estar no armazenamento compartilhado do cluster, armazenar seus estados nos arquivos, alterar o estado armazenado no disco apenas atomicamente e poder continuar sua ação a partir de qualquer estado transitório que eles detectem na inicialização.

kubanczyk
fonte
1

Na verdade, não há solução satisfatória nessa área. Nós tentamos todos eles. soluções de script, cron com pulsação / marcapasso e muito mais. A única solução, até recentemente, era uma solução de grade. naturalmente, não é isso que queremos ver como uma solução de grade é um pouco mais do que um exagero para o cenário.

Por isso, iniciei o projeto CronBalancer. funciona exatamente como um servidor cron normal, exceto que é distribuído, com balanceamento de carga e alta disponibilidade (quando concluído). Atualmente, os 2 primeiros pontos estão concluídos (beta) e funcionam com um arquivo crontab padrão.

a estrutura de alta disponibilidade está em vigor. tudo o que resta é a sinalização necessária para determinar as ações de failover e recuperação.

http://sourceforge.net/projects/cronbalancer/

mandril

Charles Williams
fonte
1

Eu estava usando o manipulador de eventos do Nagios como uma solução simples.

No servidor NRPE:

command[check_crond]=/usr/lib64/nagios/plugins/check_procs -c 1: -C crond
command[autostart_crond]=sudo /etc/init.d/crond start
command[stop_crond]=sudo /etc/init.d/crond stop

Não se esqueça de adicionar o nagiosusuário ao grupo sudoers:

nagios  ALL=(ALL)   NOPASSWD:/usr/lib64/nagios/plugins/, /etc/init.d/crond

e desabilite requiretty:

Defaults:nagios !requiretty

No servidor Nagios:

services.cfg

define service{
    use                     generic-service
    host_name               cpc_3.145
    service_description     crond
    check_command           check_nrpe!check_crond
    event_handler           autostart_crond!cpc_2.93
    process_perf_data       0
    contact_groups          admin,admin-sms
}

commands.cfg

define command{
    command_name    autostart_crond
    command_line    $USER1$/eventhandlers/autostart_crond.sh $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$ $ARG1$
}

autostart_crond.sh

#!/bin/bash

case "$1" in
    OK)
        /usr/local/nagios/libexec/check_nrpe -H $4 -c stop_crond
        ;;
    WARNING)
        ;;
    UNKNOWN)
        /usr/local/nagios/libexec/check_nrpe -H $4 -c autostart_crond
        ;;
    CRITICAL)
        /usr/local/nagios/libexec/check_nrpe -H $4 -c autostart_crond
        ;;
esac

exit 0

mas mudei para usar Pacemaker e Corosync, pois é a melhor solução para garantir que o recurso seja executado apenas em um nó por vez.

Aqui estão as etapas que eu fiz:

Verifique se o script init crond é compatível com LSB . No meu CentOS, preciso alterar o status de saída de 1 para 0 (se iniciar uma corrida ou parar uma parada) para atender aos requisitos:

start() {
    echo -n $"Starting $prog: " 
    if [ -e /var/lock/subsys/crond ]; then
        if [ -e /var/run/crond.pid ] && [ -e /proc/`cat /var/run/crond.pid` ]; then
            echo -n $"cannot start crond: crond is already running.";
            failure $"cannot start crond: crond already running.";
            echo
            #return 1
            return 0
        fi
    fi

stop() {
    echo -n $"Stopping $prog: "
    if [ ! -e /var/lock/subsys/crond ]; then
        echo -n $"cannot stop crond: crond is not running."
        failure $"cannot stop crond: crond is not running."
        echo
        #return 1;
        return 0;
    fi

então ele pode ser adicionado ao marcapasso usando:

# crm configure primitive Crond lsb:crond \
        op monitor interval="60s"

crm configure show

node SVR022-293.localdomain
node SVR233NTC-3145.localdomain
primitive Crond lsb:crond \
        op monitor interval="60s"
property $id="cib-bootstrap-options" \
        dc-version="1.1.5-1.1.el5-01e86afaaa6d4a8c4836f68df80ababd6ca3902f" \
        cluster-infrastructure="openais" \
        expected-quorum-votes="2" \
        stonith-enabled="false" \
        no-quorum-policy="ignore"
rsc_defaults $id="rsc-options" \
        resource-stickiness="100"

status crm

============
Last updated: Fri Jun  7 13:44:03 2013
Stack: openais
Current DC: SVR233NTC-3145.localdomain - partition with quorum
Version: 1.1.5-1.1.el5-01e86afaaa6d4a8c4836f68df80ababd6ca3902f
2 Nodes configured, 2 expected votes
1 Resources configured.
============

Online: [ SVR022-293.localdomain SVR233NTC-3145.localdomain ]

 Crond  (lsb:crond):    Started SVR233NTC-3145.localdomain

Testando o failover parando o Pacemaker e o Corosync no 3.145:

[root@3145 corosync]# service pacemaker stop
Signaling Pacemaker Cluster Manager to terminate:          [  OK  ]
Waiting for cluster services to unload:......              [  OK  ]

[root@3145 corosync]# service corosync stop
Signaling Corosync Cluster Engine (corosync) to terminate: [  OK  ]
Waiting for corosync services to unload:.                  [  OK  ]

verifique o status do cluster no 2.93:

============
Last updated: Fri Jun  7 13:47:31 2013
Stack: openais
Current DC: SVR022-293.localdomain - partition WITHOUT quorum
Version: 1.1.5-1.1.el5-01e86afaaa6d4a8c4836f68df80ababd6ca3902f
2 Nodes configured, 2 expected votes
1 Resources configured.
============

Online: [ SVR022-293.localdomain ]
OFFLINE: [ SVR233NTC-3145.localdomain ]

Crond   (lsb:crond):    Started SVR022-293.localdomain
quanta
fonte
0

Fazer com que seja executado / não seja executado em uma máquina específica é trivial. Faça com que um script coloque um cron em /etc/cron.d, como você sugere, ou permanentemente o script em /etc/cron.d, mas faça com que o próprio script faça a verificação de failover e decida se será executado.

A parte comum (ausente) de ambos é como o script verifica se o script na outra máquina está em execução.

Sem mais informações sobre o que você está tentando fazer, é difícil responder.

Schof
fonte
0

Eu prefiro Rcron para este problema em particular. Você tem um arquivo de estado, que simplesmente diz "ativo" ou "passivo", e se estiver ativo, seu cron será executado em uma determinada máquina. Se o arquivo de estado estiver definido como passivo, ele não será executado. Simples assim.

Agora, você pode usar o RedHat Cluster Suite ou qualquer outro middleware de cluster para gerenciar arquivos de estado em seu cluster, ou pode configurar manualmente ativo em um determinado nó e pronto.

Jakov Sosic
fonte