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
}
qualsiasi soluzione finale con esempio di codice sorgente completo a lavorare su di esso? – Kiquenet
@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
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