DBA Günlükleri #14 : Powershell ile PostgreSQL ve Couchbase Envanter Keşifleri

Hüseyin Demir
4 min readApr 12, 2020

--

Merhabalar, bu yazımda sizlere bir DBA’in veritabanı envanterini nasıl daha etkili yönetebileceğini ve nasıl daha kolay kontrol altında tutabileceğini aktarmaya çalışacağım.

Envanter yönetimi çoğu sistem yöneticisi ve veritabanı yöneticisi için büyük çaplı organizasyonlarda zorlayıcı ve takip edilmesi imkansız bir hal alabilir. Bu durumun oluşmaması ve envanterin takip edilebilir olması için akılcı ve geliştirilebilir bir çözüm gerekmektedir. Bu nedenle, kullandığımız veritabanı teknolojilerinin dışarı açtığı endpointler bizim için çok önemlidir.

Bu çalışmamızda benimde çok severek hazırladığım ve çok fazla faydasını gördüğüm çok fazla sunucu ile çalışan yapılarda nasıl kontrol sağlıyoruz ve bu kontrolü nasıl avantajımıza çeviriyoruz gibi sorulara cevap bulacağız.

Trendyol veritabanı ekibi olarak yaklaşık;

  • 600 tane Couchbase production sunucusu
  • 300 tane PostgreSQL production sunucusu

mevcut. Yaklaşık 1.000 sunucuya yaklaşan bir envanterde gruplama yapmak,rollerine göre operasyon planı yapmak ve kullanımdan düşen sunucuların geri kazanılması gibi konularda veritabanın sağladığı endpointler üzerinden script’ler ile bu işlemleri kolayca yapabiliriz. Yerel sunucumuzdan çalışmak için özellikle Powershell ya da Python gibi script dillerini kullanabilirsiniz. Ben Powershell kullanarak bu işlemleri yapmayı tercih. Powershell ile birlikte, liste halinde tüm envanterimdeki sunucuları sıra ile kontrol edip sunucuların ait olduğu cluster bilgisi,sunucu rolü ve içerdiği veritabanı gibi bilgilere ulaşmak mümkündür.

Powershell ile Couchbase Envanterinin Kontrolü ve Durumunu Sorgulamak

Powershell ile birlikte, Couchbase tarafındaki sunucuların toplu bir listeden olacak şekilde kontrol edilmesi ve yönetilmesi mümkündür. Aşağıdak script ile birlikte liste halinde verilen sunucuların rolü,içerdiği bucketlar ve sunucu isimleri gibi bilgileri elde etmek mümkündür. Bunun ile birlikte, login olunamayan ya da üzerinde artık aktif olarak Couchbase servisi bulunmayan sunucuları da ayrı bir listede toplamak mümkündür.

Aşağıda script’in tam halini paylaşıyorum. Ancak yazının sonraki kısımlarında script’in parçlarını tek tek inceleyip görevlerini tartışmaya çalışacağım.

Yukarıdaki scriptte,

[Uri]$urlForNodeInfo = "http://"+$nodeName+":8091/pools/default"
[Uri]$urlForBucketInfo = "http://"+$nodeName+":8091/pools/default/buckets"

kısmında Couchbase’in GET endpointlerine cluster içerisindeki sunucular ve bucketlar için ayrı URL bilgileri oluşturulmuştur ve aşağıdaki gibi Invoke-WebRequest ile GET endpointlerine istek atılmıştır.

try {
$getContentofNode = Invoke-WebRequest -Method Get -Uri $urlForNodeInfo -Headers @{"Authorization" = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("kullanıcı_adı:şifre")); "Content-Type" = "application/json" }
$getBucketsofNode = Invoke-WebRequest -Method Get -Uri $urlForBucketInfo -Headers @{"Authorization" = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("kullanıcı_adı:şifre")); "Content-Type" = "application/json" }
}

Bu endpointlerden veriyi elde ettikten sonra bu verilerin JSON formatını çevirip okunabilir bir formata kavuşturmak için object array oluşturulmuştur.

$couchbaseServerList = @()
$nodeList = $getContentofNode.Content | ConvertFrom-Json
$bucketList = $getBucketsofNode.Content | ConvertFrom-Json

burada, sunucuların ve bucketların listesi elde ediltekten sonra sunucu listesini kapsayan bir loop açılmış ve o sunucunun sahip olduğu Couchbase servis(ler)i ve bucket listesi elde edilmektedir. Bu kısmı en sondaki döngü ile yapıyoruz. Döngü içerisinde, sadece listeden belirtilen sunucular için duruma bakmak istediğim küçük bir koşul koyarak clusterdaki diğer sunucuları exclude ettim.

foreach ($item in $nodeList.nodes) {
$comparedHost = $singleNode.ToString()
if ($item.hostname -eq $comparedHost+":8091") {
$nodeHostname = $item.hostname
$nodeServices = $item.services
$nodeBuckets = $bucketList.name
$newRecord = New-Object System.Object
$newRecord | Add-Member -type NoteProperty -name Hostname -Value $nodeHostname
$newRecord | Add-Member -type NoteProperty -name Services -Value $nodeServices
$newRecord | Add-Member -type NoteProperty -name Buckets -Value $nodeBuckets
$couchbaseServerList += $newRecord
}

Bu şekilde, tüm sunucuların rollerini ve içerdiği bucketları görmek için sunucu listesi yeterli bir duruma geliyor. Bu çalışmadan kazanım olarak ise,

  • Rolleri değişen sunucuların dinamik olarak görülmesi
  • Yeni bucket eklenen clusterda eski bilginin güncellenmesi
  • Birey hatasının ve ekstra eforun önüne geçilmesi
  • Devre dışı kalmış sunucuların fark edilmesi

bu maddelerden bahsetmek mümkündür. Script’in tam halini bu adreste bulabilirsiniz. İnceleyip geliştirmeye açık durumda.

Powershell ile PostgreSQL Envanterinin Kontrolü ve Durumunu Sorgulamak

PostgreSQL’de de aslında Couchbase’de olduğu gibi endpointler aracılığı ile envanter yönetimini ve kontrolünü yapmak mümkündür. Ancak PostreSQL’de endpoint kullanımı bizim ortamımızda Patroni aracı ile mümkün olmuştur. Bu nedenle buradaki script ve süreç Patroni üzerine kurgulanmıştır.

Patroni hakkında detaylı bilgiye aşağıdaki linklerden ulaşabilirsiniz.

Bu bilgiler ışığında Patroni’nin bize sağladığı endpoint’ler ile birlikte bu işlemi nasıl yaptığımızı tartışmakta fayda var. Aslında mantığı Couchbase üzerinde yaptığımızdan pek farklı değil. URL adresleri ve veri işleme kısımları farklılık göstermekte. Bu PS’de ise sunucunun rolü,durumu(offline/online),cluster ismi, sunucu IP bilgileri elde edilmektedir. Örnek çıktı aşağıdaki gibidir.

Fonksiyonun tam hali ise aşağıdaki gibidir. Burada da loop ile tüm sunucuların talep edilen bilgilerini son kullanıcıya teslim etmekteyiz.

function getPostgreSQLStatusFromList {
param (
[Parameter(ValueFromPipeline = $true)]
[string]
$listPath
)
$hostListFromServer = Get-Content -Path $listPath

foreach ($singleNode in $hostListFromServer) {
$nodeName = $singleNode.ToString()
[Uri]$urlForNodeInfo = "http://" + $nodeName + ":8008/patroni/"
$getContentofNode = Invoke-WebRequest -Method Get -Uri $urlForNodeInfo -Headers @{"Content-Type" = "application/json" }
$pgNodeInformation = @()
$nodeList = $getContentofNode.Content | ConvertFrom-Json
$nodeRole = $nodeList.role
$nodeState = $nodeList.state
$nodePatroni = $nodeList.patroni.scope
$newRecord = New-Object System.Object
$newRecord | Add-Member -type NoteProperty -name Hostname-IP -Value $nodeName
$newRecord | Add-Member -type NoteProperty -name Role -Value $nodeRole
$newRecord | Add-Member -type NoteProperty -name State -Value $nodeState
$newRecord | Add-Member -type NoteProperty -name Patroni-Details -Value $nodePatroni
#$newRecord | Add-Member -type NoteProperty -name Buckets -Value $nodeBuckets
$pgNodeInformation += $newRecord
$pgNodeInformation | Format-Table -AutoSize -Wrap
}
}

getPostgreSQLStatusFromList -listPath 'C:\pg_servers.txt'

Yazının bir sonraki versiyonunda ise, yine endpointleri kullanarak veritabanı metadatası üzerine çalışacağım.

Buradaki temel motivasyonum, bir sistem yöneticisinin üzerinde çalıştığı envantere daha çok hakim olması ve daha hızlı bakım yapabilmesi için fikir edinebilmesiydi. Bu nedenle de bu işleri fonksiyon haline getirip PS üzerinde derlemeyi tercih ettim.

Sevgiler,

Demir.

--

--

No responses yet