2012-05-01 19 views
8

mi chiedo se qualcuno ha esperienza la distribuzione su più server dietro un bilanciatore di carico su EC2 con fabricDistribuzione a più server EC2 con tessuto

ho usato tessuto per un po 'di tempo, e non hanno problemi con esso, o la distribuzione su più server, ma quello che mi piacerebbe fare in questo scenario è (diciamo che ho dieci istanze in esecuzione) de-register metà (5) delle scatole dal mio bilanciamento del carico, distribuire il mio codice a loro ed eseguire un fumo test, e se tutto sembra a posto, registrarli nuovamente con il servizio di bilanciamento del carico e deselezionare le restanti 5 istanze e distribuirle, quindi registrarle nuovamente al servizio di bilanciamento del carico.

Non ho alcun problema a realizzare nessuno dei singoli compiti (de-registrazione, esecuzione di test, distribuzione ecc.), Non so come organizzare i miei host in modo semplice in modo da poter distribuire il primo semestre, poi la seconda metà. Fabric sembra essere impostato per eseguire le stesse attività su tutti gli host in ordine (task 1 su host 1, task 1 su host 2, task 2 su host 1, task 2 su host 2 etc etc)

Il mio primo pensiero era quello di creare un'attività per gestire la prima parte della de-registrazione, la distribuzione e il test, e quindi impostare il env.hosts per la seconda metà dei server, ma ho sentito questo sembrava un po 'hokey.

Qualcuno ha mai modellato qualcosa di simile a questo con Fabric?

+0

Dalla mia limitata espe rience con Fabric, sembra esattamente quello che vorresti fare. L'unico modo in cui potrei pensare che fosse un hokey è se volessi fare qualche tipo di selezione casuale delle 5 caselle. –

+0

In alternativa, 'ansible' fa qualcosa di simile fuori dagli schemi. Vale la pena dare un'occhiata: http://docs.ansible.com/guide_rolling_upgrade.html#the-rolling-upgrade –

risposta

5

È possibile semplificare questo definendo i ruoli (utilizzato per l'aggregazione di host) ed eseguendo le attività su un ruolo, quindi eseguendo test e distribuendo sul secondo ruolo.

Esempio di roledefs:

env.roledefs = { 
    'first_half': ['host1', 'host2'], 
    'second_half': ['host3', 'host4'], 
} 

def deploy_server(): 
    ... 
    # deploy one host from current role here 

def deploy(): 
    # first role: 
    env.roles = ['first_half'] 
    execute('deploy_server') 
    test() # here test deployed servers 
    # second role: 
    env.roles = ['second_half'] 
    execute('deploy_server') 

Altri link:

+0

solo per curiosità, perché usi 'execute' vs chiamando' deploy_server' direttamente – MattoTodd

+0

Inoltre, stai usando errato lì. Gli dai un compito come funzione passata, non una stringa con il suo nome. Questo ed execute possono assumere ruoli: execute (deploy_server, roles = ['first_half']) – Morgan

+1

@Morgan: errato. Si prega di dare un'occhiata al link alla documentazione originariamente incluso nella risposta. 'execute' accetta sia callable che task name (stringa). Hai comunque ragione riguardo alla possibilità di impostare i ruoli su cui dovrebbe essere eseguito (vedi anche questo nei documenti). – Tadeck

0

Fabric non è configurato per eseguire le stesse attività su tutti gli host.

A parte il fatto che è possibile impostare in modo esplicito i padroni di casa per una specifica compito con il parametro di riga di comando -H, è possibile utilizzare this modello e this più nuovo modello di fare esattamente quello che vuoi.

Aggiornamento: Here mostra come è possibile utilizzare roles

+0

poiché fabric usa env.hosts per impostazione predefinita, come si specifica un ruolo particolare in una delle attività? – MattoTodd

+0

Ho aggiornato la mia risposta. – rantanplan

+0

danke schon !!!! – MattoTodd

-1

Invece di immischiarsi con env.hosts, si potrebbe passare un elenco (o qualsiasi iterabile) al host decoratore. Qualcosa di simile:

def deploy(half_my_hosts): 
    @hosts(half_my_hosts) 
    def mytask(): 
     # ... 
    mytask() 

allora si potrebbe dividere i env.hosts in qualsiasi modo ti piace e passarlo a distribuire()

+0

c'è ora execute() per le sottoattività e ha un host param. – Morgan

+0

Ah, grazie, buono a sapersi. Questa è certamente una soluzione più pulita. – spinlok

3

Si desidera utilizzare la funzione execute(). Questo vi permetterà di fare qualcosa di simile:

def update(): 
    deallocate() 
    push_code() 
    smoke_test() #could fail fast 
    reallocate() 

def deploy(): 
    execute(update, hosts=first_five) 
    execute(update, hosts=last_five) 

Si potrebbe anche fare ciascuna delle deallocare, push_code, e smoke_test, le attività di un execute() chiamata nel deploy, e poi si sarebbe eseguire tutte le dealloca quindi esegui tutte le spinte di codice, ecc.

Quindi verifica un qualche tipo e poi procedi con gli altri che eseguono tali compiti.

1

Ho combinato con successo Fabric con boto. Compilo l'elenco degli host usando boto. Puoi usare @parallel decorator per limitare il numero di host da eseguire in un colpo solo. Il comando appare come segue;

fab running deploy

Il codice sembra così;

@task 
@runs_once 
def running(): 
    ec2conn = ec2.connect_to_region(region) 
    reservations = ec2conn.get_all_instances(filters={'instance-state-name': 'running'}) 
    instances = list(chain.from_iterable(map(lambda r: r.instances, reservations))) 
    env.hosts = list(chain.from_iterable(map(lambda i: i.public_dns_name, instances))) 

@task 
@parallel(pool_size=5) 
def deploy(): 
    # do stuff on n<=5 hosts in parallel 

Se è necessario gestire una sottosezione di host, suggerirei di utilizzare i tag.

+0

nota a caso: si deve fare attenzione a non riutilizzare lo stesso oggetto di connessione ec2 in attività parallele, dato che boto non è thread-safe (è una sorta di domanda epistemologica se una determinata libreria python è "thread safe", ma cosa significa che Boto è noto per rompere quando viene utilizzato in questo modo) – jberryman

0

Oppure si potrebbe semplicemente scrivere un metodo che definisce alcune variabili, per esempio:

def live(): 
    global PATH, ENV_PATH 
    env.hosts = ["22.2.222.2"] 
    env.user = 'test' 
    PATH = '/path/to/project' 
    # optional, is using virtualenv 
    ENV_PATH = '/path/to/virtualenv' 
    # overwri 

te qualunque variabled è necessario cambiare la macchina corrente

e prima di eseguire il comando deploy, eseguire:

fab live deploy 

Dettagli: http://simionbaws.ro/programming/deploy-with-fabric-on-multiple-servers/