11

Attualmente stiamo utilizzando TeamCity per build CI e stiamo tentando di impostare anche le distribuzioni automatizzate.Distribuzione automatica a un ambiente con carico bilanciato F5

Il progetto che sto provando a distribuire è un servizio di Windows che si trova sotto un sistema di bilanciamento del carico F5. In futuro vorremmo anche automatizzare la distribuzione dei nostri siti Web IIS che si trovano anche sotto la F5.

Da TeamCity possiamo eseguire script PowerShell per disinstallare il servizio Windows sul server desiderato, spingere i nostri file su di esso, quindi reinstallare il servizio.

Tuttavia, ho difficoltà a capire come gestire il bilanciamento del carico. Vorremmo disabilitare 1 nodo alla volta, controllare che tutte le connessioni si interrompano, quindi distribuire il nostro codice e riportare il nodo su.

Sembra che sarebbe un problema molto comune, ma sto trovando sorprendentemente poche informazioni su come farlo.

Grazie!

con risposta

Grazie Jonathon Rossi per i cmdlet PowerShell iControl!

Per l'amor di altri utenti, ecco un esempio di spegnimento, il monitoraggio per le connessioni a cadere, spingendo il codice, e poi tornare indietro sul bilanciamento del carico F5 attraverso uno script PowerShell

Per questi script per lavorare voi dovrà prima installare i cmdlet F5 iControl dai link forniti in risposta al di sotto

#PULL IN OUR F5 UTILITY FUNCTIONS 
. .\F5Functions.ps1 


#DEFINE LOGIC TO DEPLOY CODE TO A NODE THAT HAS ALREADY BEEN REMOVED FROM THE LOAD BALANCER 
function Deploy(
    [F5Node]$Node 
) 
{ 
    Write-Host "Deploying To: "$Node.Name 
    #TODO: Remotely shut down services, push code, start back up services 
} 


#DEFINE NODES 
$nodes = @() 
$nodes += New-Object F5Node -ArgumentList @("TestNode1", "1.1.1.1") 
$nodes += New-Object F5Node -ArgumentList @("TestNode2", "1.1.1.2") 

#DEPLOY 
DeployToNodes -Nodes $nodes -F5Host $F5Host -F5UserName $F5UserName -F5Password $F5Password 

Ed ecco il F5Functions riutilizzabile sceneggiatura

#Load the F5 powershell iControl snapin 
Add-PSSnapin iControlSnapin; 

Write-Host "Imported F5 function!!!" 

Add-Type @' 
    public class F5Node 
    { 
     public F5Node(string name, string address){ 
      Address = address; 
      Name = name; 
     } 
     public string Address {get;set;} 
     public string Name {get;set;} 
     public string QualifiedName {get{return "/Common/" + Name;}} 
    } 
'@ 

function DeployToNodes(
    [string]$F5Host = $(throw "Missing Required Parameter"), 
    [string]$F5UserName = $(throw "Missing Required Parameter"), 
    [string]$F5Password = $(throw "Missing Required Parameter"), 
    [F5Node[]]$Nodes = $(throw "Missing Required Parameter"),  
    [int]$MaxWaitTime = 300 #seconds... defaults to 5 minutes 
){ 
    Authenticate -F5Host $F5Host -F5UserName $F5UserName -F5Password $F5Password 

    foreach($node in $Nodes){ 
     DisableNode -Node $node 

     WaitForConnectionsToDrop -Node $node -MaxWaitTime $MaxWaitTime 

     #Assume the Script that included this script defined a Deploy Method with a Node param 
     Deploy -Node $node  

     EnableNode -Node $node 
    } 
} 

function Authenticate(
    [string]$F5Host = $(throw "Missing Required Parameter"), 
    [string]$F5UserName = $(throw "Missing Required Parameter"), 
    [string]$F5Password = $(throw "Missing Required Parameter") 
) 
{ 
    Write-Host "Authenticating to F5..." 
    Initialize-F5.iControl -HostName $F5Host -Username $F5UserName -Password $F5Password 
    Write-Host "Authentication Success!!!" 
} 

function ParseStatistic(
     [iControl.CommonStatistic[]]$StatsCollection = $(throw "Missing Required Parameter"), 
     [string]$StatName = $(throw "Missing Required Parameter") 
    ) 
{ 
    for($i=0; $i -lt $StatsCollection.Count; $i++){ 
     if($StatsCollection[$i].type.ToString() -eq $StatName){ 
      return $StatsCollection[$i].value.low 
      break 
     }      
    } 
} 

function GetStats(
     [F5Node]$Node = $(throw "Missing Required Parameter") 
    ) 
{ 
    $arr = @($Node.QualifiedName) 
    $nodeStats = (Get-F5.iControl).LocalLBNodeAddressV2.get_statistics($arr) 
    return $nodeStats.statistics.statistics 

    #foreach($memberStats in $poolStats.statistics){ 
    # if($memberStats.member.address.ToString() -eq $Node -and $memberStats.member.port -eq $Port){ 
    #  return $memberStats.statistics 
    # } 
    #} 
} 

function GetStatistic(
     [F5Node]$Node = $(throw "Missing Required Parameter"), 
     [string]$StatName = $(throw "Missing Required Parameter") 
    ) 
{ 
    $stats = GetStats -Node $Node 
    $stat = ParseStatistic -StatsCollection $stats -StatName $StatName 

    return $stat 
} 

function DisableNode(
    [F5Node]$Node = $(throw "Missing Required Parameter") 
) 
{  
    Disable-F5.LTMNodeAddress -Node $Node.Address 
    Write-Host "Disabled Node '$Node'" 
} 

function EnableNode(
    [F5Node]$Node = $(throw "Missing Required Parameter") 
) 
{ 
    Enable-F5.LTMNodeAddress -Node $Node.Address 
    Write-Host "Enabled Node '$Node'" 
} 

function WaitForConnectionsToDrop(
    [F5Node]$Node = $(throw "Missing Required Parameter"), 
    [int]$MaxWaitTime = 300 
) 
{ 
    $connections = GetCurrentConnections -Node $Node 

    $elapsed = [System.Diagnostics.Stopwatch]::StartNew(); 
    while($connections -gt 0 -and $elapsed.ElapsedMilliseconds -lt ($MaxWaitTime * 1000)){   

     Start-Sleep -Seconds 10 

     $connections = GetCurrentConnections -Node $Node 
    } 
} 

function GetCurrentConnections(
    [F5Node]$Node = $(throw "Missing Required Parameter") 
) 
{ 
    $connections = GetStatistic -Node $Node -StatName "STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS" 
    $name = $Node.Name + ":" + $Node.Address 
    Write-Host "$connections connections remaining on '$name'" 
    return $connections 
} 
+0

qualsiasi soluzione finale con esempio di codice sorgente completo a lavorare su di esso? – Kiquenet

+1

@Kiquenet - I frammenti di codice di cui sopra nell'intestazione "Risposta" sono quelli utilizzati per distribuire il codice in produzione circa 5 - 10 volte al giorno. Il secondo blocco di codice è il modulo che viene caricato dal primo blocco di codice, che è un esempio di come utilizzare il modulo. L'unica parte che è necessario compilare è ciò che effettivamente si fa per distribuire il codice mentre il nodo F5 è inattivo (spostare i file, decomprimere, interrompere i servizi, riavviare servizi, ecc.). Scusate le scarse convenzioni di denominazione. Ero nuovo a PowerShell quando ho scritto questo. – Michael

+0

In realtà, mentre sto rileggendo il mio vecchio post, vedo che è molto meno maturo del prodotto finale. 1. Ho spostato lo script F5 di funcitons su un modulo PowerShell installato sul server di build e lo ho caricato con Load-Module 2. La funzione DeployToNodes dovrebbe richiedere uno ScriptBlock e un array di argomenti per ScriptBlock invece di presupporre che Deploy la funzione è dichiarata altrove 3. le funzioni devono seguire la convenzione di denominazione dei verbi 4.Ho messo più logica sulla rimozione dei nodi, in modo da ridurre la metà alla volta, consentendo alle migrazioni SQL di svolgersi nel mezzo – Michael

risposta

6

Non l'ho usato, ma hai guardato l'API del servizio web F5 iControl e il F5 iControl PowerShell cmdlets fornito da F5. I cmdlet di PowerShell sono disponibili dal 2007 e possono essere scaricati da F5 DevCentral.

Sembra che ci siano i cmdlet Enable-Member e Disable-Member che sarete in grado di utilizzare.

+0

Questo è perfetto. I comandi di abilitazione/disabilitazione in combinazione con l'interrogazione per STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS da questo metodo API: https://devcentral.f5.com/wiki/iControl.LocalLB__PoolMember__get_all_statistics.ashx – Michael