Автоматическое развертывание в среде с балансировкой нагрузки F5

В настоящее время мы используем TeamCity для сборки CI, и мы также пытаемся настроить автоматическое развертывание.

Проект, который я сейчас пытаюсь развернуть, - это служба Windows, которая находится под балансиром нагрузки F5. В будущем мы также хотели бы автоматизировать развертывание наших веб-сайтов IIS, которые также находятся под F5.

Из TeamCity мы можем запускать скрипты PowerShell для unistall службы Windows на нужном сервере, подталкивать наши файлы к нему, а затем переустанавливать службу.

Однако мне трудно понять, как бороться с балансировщиком нагрузки. Мы хотели бы отключить 1 node за один раз, следить за тем, чтобы все соединения были удалены, затем развернуть наш код и вернуть node.

Кажется, что это будет очень распространенная проблема, но я нахожу удивительно мало информации о том, как это сделать.

Спасибо!

Ответил

Спасибо Jonathon Rossi за командлеты iControl Powershell!

Для других пользователей здесь приведен пример отключения, мониторинга соединений для сброса, нажатия кода, а затем возврата к балансировщику нагрузки F5 через powershell script

Чтобы эти сценарии работали, вам сначала нужно будет установить командлеты F5 iControl из ссылок, приведенных в ответе ниже

#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

И вот многоразовые F5Functions script

#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
}

Ответ 1

Я не использовал его, но вы посмотрели на F5 iControl API веб-сервиса и F5 iControl PowerShell командлеты, предоставленные F5. Командлеты PowerShell существуют со времени 2007 и могут быть загружены из F5 DevCentral.

Похоже, есть командлеты Enable-Member и Disable-Member, которые вы сможете использовать.