11

Obecnie korzystamy z TeamCity dla kompilacji CI i staramy się również skonfigurować wdrożenia automatyczne.Zautomatyzowane wdrażanie do środowiska równoważnego obciążeniem F5

Projekt, który próbuję obecnie wdrożyć, to usługa systemu Windows, która znajduje się w module równoważenia obciążenia F5. W przyszłości chcielibyśmy również zautomatyzować wdrażanie naszych stron IIS, które również znajdują się pod F5.

Od TeamCity możemy wykonywać skrypty PowerShell, aby zunifikować usługę Windows na wybranym serwerze, przesłać do niej nasze pliki, a następnie ponownie zainstalować usługę.

Mam jednak problem z ustaleniem, jak radzić sobie z modułem równoważenia obciążenia. Chcielibyśmy wyłączyć 1 węzeł naraz, uważać na wszystkie połączenia, aby je upuścić, a następnie wdrożyć nasz kod i przywrócić węzeł.

Wydaje się, że byłby to bardzo powszechny problem, ale znajduję zaskakująco mało informacji o tym, jak to zrobić.

Dzięki!

Odpowiedział

Dzięki Jonathon Rossi dla iControl cmdlets PowerShell!

Na litość innych użytkowników, oto próbka zamknięcie, monitorowanie połączeń spadać, kod popychanie, a potem zawrócić na równoważenia obciążenia F5 przez skryptu PowerShell

dla tych skryptów do pracy ci najpierw będą musiały zainstalować cmdlet F5 iControl z linków podanych w odpowiedzi poniżej

#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 

I tu jest wielokrotnego użytku F5Functions skrypt

#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

każde ostateczne rozwiązanie z pełnym tekstem kodu źródłowego działającego na ten temat? – Kiquenet

+1

@Kiquenet - Powyższe fragmenty kodu pod nagłówkiem "Odpowiadano" są tym, za pomocą których wdrażamy kod do produkcji około 5-10 razy dziennie. Drugi blok kodu jest modułem, który jest ładowany przez pierwszy blok kodu, który jest przykładem użycia tego modułu. Jedyną częścią, którą musisz wypełnić, jest to, co faktycznie robisz, aby wdrożyć kod, gdy węzeł F5 jest wyłączony (przenieś pliki, rozpakuj, zatrzymaj usługi, zrestartuj usługi itp.). Przepraszam za złe konwencje nazewnictwa. Byłem nowy w Power Shell, kiedy to pisałem. – Michael

+0

Właściwie, kiedy ponownie czytam mój stary post, widzę, że jest znacznie mniej dojrzały niż końcowy produkt. 1. Przeniosłem skrypt funckitów F5 do modułu powershell zainstalowanego na serwerze kompilacji i załadowałem go modułem Load-Module 2. Funkcja DeployToNodes powinna przyjmować ScriptBlock i tablicę argumentów dla ScriptBlock, zamiast zakładać, że Deploy funkcja jest zadeklarowana gdzie indziej. 3. Funkcje powinny być zgodne z konwencją nazewnictwa rzeczownik-czasownik-nazwisko 4.Położyłem więcej logiki wokół zdejmowania węzłów, a więc zmniejszyłoby to połowę w czasie, pozwalając na migracje sql w środku – Michael

Odpowiedz

6

Nie użyłem tego, ale czy patrzyłeś na interfejs API serwisu WWW i F5 iControl PowerShell cmdlets dostarczony przez F5. Polecenia cmdlet PowerShell istnieją od 2007 i można je pobrać z F5 DevCentral.

Wygląda na to, że są dostępne polecenia cmdlety Enable-Member i Disable-Member, których można używać.

+0

To jest idealne. Polecenia włączania/wyłączania w połączeniu z kwerendami dla STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS z tej metody api: https://devcentral.f5.com/wiki/iControl.LocalLB__PoolMember__get_all_statistics.ashx – Michael

Powiązane problemy