Ustawienia sieci w CentOSie

14 marca, 2013 (12:32) | centos, linux | By: admin

Instalacja Linuksa (w szczególności dystrybucji RedHat lub CentOS) ze standardowymi ustawieniami sieci nie jest zadaniem specjalnie trudnym. Jednak warto wiedzieć, jak pozmieniać niektóre rzeczy tak, aby mieć „system idealny”. Tak naprawdę jest to ściąga dla mnie, bo od zawsze chciałem mieć w jednym miejscu spisane najczęściej wykorzystywane konfiguracje.

Na początku przyjrzyjmy się standardowej definicji interfejsu sieciowego w CentOSie:

[kbechler@flame ~]$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
BROADCAST="192.168.0.255"
HWADDR="xx:xx:xx:31:C1:50"
IPADDR="192.168.0.1"
NETMASK="255.255.255.0"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="160c17ae-6483-406e-bca3-3bd4db50084b"
[kbechler@flame ~]$

Dla porównania, wersja z dynamicznym pobieraniem adresu:

[kbechler@flame ~]$ cat /etc/sysconfig/network-scripts/ifcfg-eth2
DEVICE="eth2"
BOOTPROTO="dhcp"
HWADDR="xx:xx:xx:00:26:82"
ONBOOT="yes"
TYPE="Ethernet"
[kbechler@flame ~]$

Co tak właściwie możemy chcieć tu zmienić? Może na początek sklonować adres MAC naszej sieciówki. Robi się to przy pomocy takiego oto wpisu:

MACADDR="xx:xx:xx:47:09:77"

Co ważne, nie usuwamy linijki z rzeczywistym adresem naszej karty (czyli HWADDR), a dopisujemy drugi MAC w przytoczonej przed momentem formie.

Drugą, zmienianą przeze mnie rzeczą, jest wyłączenie pobierania adresów serwerów DNS. Domyślnie, razem z adresem IP, maską i bramą domyślną, klient DCHP w CentOSie pobiera także listę serwerów DNS i dopisuje ją do /etc/resolv.conf. Ponieważ mam własne serwery DNS w sieci, to chciałbym, aby tą część mechanizmu automatycznej konfiguracji interfejsu wyłączyć. Żeby wprowadzić to w życie, wystarczy do pliku ifcfg-ethX dodać taką oto linijkę:

PEERDNS="no"

Kolejną fajną rzecz znalazłem na TEJ stronie. Opisano tam, jak w prosty sposób do jednego interfejsu przypisać kilka kolejnych adresów IP i nie rozpisywać się przy tym zbyt mocno. W przypadku takich konfiguracji mogą się przydać metody zmiany adresów pakietów wychodzących, które opisywałem TUTAJ.

Na koniec jeszcze coś, o czym zawsze zapominam: Jak wytłumaczyć YUMowi, aby kontaktować się ze światem za pomocą serwera proxy? Do pliku /etc/yum.conf dopisać taką oto linijkę:

proxy=http://192.168.0.222:3128

Albo ustawić odpowiednio zmienną środowiskową http_proxy, na przykład tak:

[kbechler@flame ~]$ export http_proxy=http://192.168.0.222:3128

Tanie kontrolery w drogich serwerach

25 stycznia, 2013 (10:23) | Bez kategorii | By: konrad

Jakiś czas temu opisywałem wyjątkowo powolny kontroler DELL H200. Miałem wtedy nadzieję, że jest to potknięcie inżynierów i odosobniony przypadek komponentu, który działa poprawnie, ale nie ma nic wspólnego z wydajnością. Niestety, okazało się, że po prostu zostałem rozbestwiony „pełnymi” kontrolerami Adapteca, które są fajne i bezproblemowe oraz rozwiązaniami DELL PERC (Dell PowerEdge RAID Controller), które również nie mają problemów z wydajnością.

Ostatnio wpadł mi w ręce serwer HP ProLiant ML350 G5 z kontrolerem Smart Array E200i i… powiedzmy, że po przygodach z H200 nie byłem zdziwiony, ale poczułem się nieswojo. Okazało się, że o ile wydajność mojego niezbyt nowego dysku przy odczycie rzędu 75MB/s jest akceptowalna, to zapis na poziomie 10MB/s dość mocno rozczarowuje. Spodziewałem się zdecydowanie lepszych wyników.

Najpierw przejrzałem konfigurację kontrolera i okazało się, że moduł podtrzymywania bateryjnego nie działa. Pewnie „skończyła” się bateria (sprzęt ma już swoje lata), więc nic dziwnego, że kontroler próbuje się zabezpieczyć przed utratą danych i coś pozmieniał (pewnie podobnie jak DELL wyłączył wewnętrzny cache dysków, chociaż pewności nie mam). Ale zacząłem szukać opinii o moim kontrolerze i trafiłem na stronę. Okazuje się, że sytuację da się trochę poprawić, nawet bez wymiany modułu BBWC. Metoda na zwiększenie wydajność jest natomiast bardzo osobliwa. Najpierw należy WŁĄCZYĆ cache zapisu, a potem ustawić jego wykorzystanie na ZERO. Trochę na bakier z logiką, ale spróbowałem. Po wydaniu dwóch magicznych komend:

ctrl slot=0 modify cacheratio=100/0
ctrl slot=0 modify dwc=enable

okazało się, że kontroler zachowuje się znacznie żwawiej – wydajność zapisu jest teraz porównywalna z odczytem i waha się w granicach 70-80MB/s. Zdaję sobie sprawę, że awaria prądu w połączeniu z uszkodzoną baterią może skutkować dość niemiłymi efektami, ale nie jest to maszyna krytyczna, a przed nią i tak stoi UPS, więc jestem w stanie zaryzykować.

Fałszowanie DNSu

10 stycznia, 2013 (16:01) | windows | By: konrad

Tym razem będzie opis przypadku konretnego Klienta, ale sama konfiguracja może się przydać do wielu ciekawych rzeczy.

Wyobraźmy sobie firmę z prostą instalacją Active Directory składającą się z kontrolera domeny, serwera plików, serwera SQL oraz serwera web (IIS). Wszystko to szczelnie „zamknięte” w sieci lokalnej z adresacją 192.168.1.0/24. Kontakt ze światem to dowolne łącze z jednym publicznym adresem IP i router typu „SOHO”, który potrafi zrobić NAT (co stanowi podstawową metodę dostępu do Internetu dla maszyn w sieci lokalnej) i… niewiele więcej. Za obsługę poczty, firmowej strony WWW i DNSów dla domeny odpowiadają serwery gdzieś w świecie.

W pewnym momencie na serwerze IIS został zainstalowany serwis, do którego dostęp mają mieć użytkownicy mobilni (czyli tacy, którzy mają laptopa i są czasami w siedzibie firmy, a czasami trochę dalej). I ci użytkownicy mają na swoich stacjach zainstalowany program, który łączy się ze wspomnianym serwisem. Niby nic prostszego, bo wystarczy wystawić port tcp/443 na zewnątrz za pomocą prostego przekierowania i wszystko śmiga aż miło. Ale nasi bohaterowie nie bardzo chcą zmieniać konfiguracji swojego programu za każdym razem, kiedy wychodzą z firmy, albo do niej wracają. A router jest na tyle „prosty”, że nie radzi sobie zbyt dobrze z połączeniami inicjowanymi z sieci lokalnej na zewnętrzny adres IP, który jest „zawinięty” do serwera w tejże sieci lokalnej (robi się podwójny NAT, który przerasta urządzenie sieciowe). Pojawia się więc drobny problem…

Na szczęście nasz magiczny program można skonfigurować tak, aby korzystał z nazwy domenowej, a nie adresu IP. Tylko jak w łatwy i elegancki sposób zrobić tak, żeby – w zależności od fizycznej lokalizacji laptopa – ta sama nazwa domenowa (nazwijmy ją app.firma.pl) była rozwiązywana na różne adresy IP? Zacznijmy od rzeczy prostych i oczywistych. Na pewno na serwerach DNS odpowiadających za domenę firma.pl musimy zdefiniować rekord A (albo AAAA dla IPv6) określający, że app.firma.pl znajduje się pod publicznym adresem IP przypisanym do Klienta. Drugą rzeczą jest (wspomniane już przeze mnie) przekierowanie portu tcp/443 serwera z IISem (niech będzie to 192.168.1.100) na routerze tak, aby był osiągalny z zewnątrz. Pozostaje jeszcze skonfigurować aplikacje na laptopach tak, żeby korzystał z nazwy domenowej, a nie adresu IP. Dzięki powyższym modyfikacjom wszyscy użytkownicy znajdujący się poza murami firmy powinni mieć dostęp do swoich danych. Ale co dalej?

Można na serwerach DNS domeny AD dodać strefę firma.pl, a w niej rekord „app.firma.pl. A 192.168.1.100„. Owszem, będzie działać, ale stracimy możliwość rozwiązywania innych nazw z domeny firma.pl (z wewnątrz sieci nie zadziała np. www.firma.pl), bo AD stanie się autorytatywne dla zdefiniowanej właśnie strefy. Niby można zdublować wszystkie wpisy z DNSów „publicznych”, jednak nie jest to dobry pomysł, bo trzeba będzie pilnować spójności tych dwóch systemów, co jeszcze szczególnie trudne w przypadku, gdzie zewnętrznymi zarządza ktoś inny. Poza tym jest to nieeleganckie :-)

Rozwiązanie okazuje się wyjątkowo proste. Okazuje się, że na serwerach DNS Active Directory można utworzyć nową strefę app.firma.pl, a w niej zdefiniować jeden rekord typu A z pustą nazwą (wtedy będzie się odnosił do nazwy strefy). Taka konfiguracja skutkuje kilkoma rzeczami. Po pierwsze – udało się spełnić założenie, bo adres app.firma.pl rozwiązywany jest na zewnątrz dzięki „publicznym” DNSow, a w siedzibie firmy dzięki DNSom skojarzonym z Active Directory. Po drugie – nie muszę pamiętać o synchronizacji strefy na dwóch, niezależnych systemach. A po trzecie – rozwiązanie jest proste, eleganckie i przejrzyste, więc nie trzeba tworzyć rozbudowanej dokumentacji i trenować pamięci, żeby się w tym później połapać.

Czym zmierzyć szybkość dysku?

20 listopada, 2012 (21:39) | linux, sprzęt, windows | By: konrad

Ostatnio pisałem o macierzach i dotknąłem tematu ich wydajności. No właśnie, wydajność podsystemu dyskowego. Czy to naprawdę takie ważne? Niezależnie od tego, czy mamy do czynienia z wieloprocesorowym serwerem z terabajtami przestrzeni dyskowej, czy ze zwykłym domowym pecetem z jednym dyskiem SATA, zawsze „coś” jest najwolniejszym elementem całości. I często są to właśnie dyski. Warto więc mieć chociaż ogólne pojęcie co moglibyśmy zyskać po wymianie/modernizacji/rozbudowie tego elementu systemu i jak nasze obecne rozwiązanie wypada w porównaniu z innymi.

Jak więc zmierzyć wydajność naszych dysków? Przede wszystkich dobrze by było zdefiniować, co tak naprawdę chcemy zmierzyć. Nie ma bowiem pojedynczej liczby, która mogłaby nam powiedzieć, które z rozwiązań jest szybsze. Istnieje szereg czynników i parametrów, które należy wziąć pod uwagę przy wyborze konkretnego rozwiązania, a których „waga” jest różna w zależności od przeznaczenia budowanego systemu. Jednak w „domowych warunkach” najczęściej dla dysków określa się dwie pary parametrów (wyrażane w megabajtach na sekundę):

odczyt i zapis sekwencyjny (ang. sequential read/sequential write) – maksymalna szybkość danego rozwiązania (fizycznego dysku, macierzy, zasobu zdalnego) przy ciągłym odczycie lub zapisie pojedynczego strumienia danych. W wolnym tłumaczeniu: jak szybko system jest w stanie przeczytać lub zapisać jeden duży plik.

odczyt i zapis swobodny (ang. random read/random write) – w tym wypadku jest trochę mniej jednoznacznie, bo spotkałem się z różnymi definicjami, ale najczęściej określa się to jako dużą ilość małych operacji dyskowych. Najlepszym przykładem jest to, co robi twardy dysk w domowym komputerze podczas normalnej pracy – zapisywanie logów systemowych w jedno miejsce, zapisywanie cookies ze stron internetowych w inne, w międzyczasie autozapis otwartego dokumentu Worda i jeszcze – w miarę szybkości połączenia z Siecią – zapisywanie ściąganego właśnie filmu (oczywiście na wolnej licencji :-)). Jeżeli takie obciążenie ma służyć do pomiarów wydajności, to wszystkie te operacje muszą być oczywiście powtarzalne, więc lepiej posłużyć się specjalnie napisanym do tego celu oprogramowaniem, niż za każdym razem powtarzać te same czynności ;-).

W mowie obcej ładnie jest to wszystko opisane na stronie Microsoftowego TechNetu, o TUTAJ.

Ale dlaczego w ogóle rozgraniczać wydajność przy odczycie/zapisie sekwencyjnym od tej „poszatkowanej”? Ano dlatego, że w zależności od zastosowań ważne są raz jedne, a raz drugie wskaźniki. To, że dla dysków systemowych bardziej wartościowa jest druga grupa parametrów, już napisałem. A ta pierwsza? Choćby dla dysków przechowujących kopie zapasowe ważnych i dużych objętościowo danych lub dla systemów obrabiających duże pliki – graficzne lub wideo. Takie dane zazwyczaj zapisuje i odczytuje się na dyskach liniowo, więc nie ma sensu kombinować, aby osiągnąć jak najmniejszy seek time (nie wiem, jak to przetłumaczyć na polski), za to warto się skupić na wydajności przy dostępie sekwencyjnym.

No dobra, to czym to w końcu można zmierzyć?

Może tym razem zacznijmy od systemów z rodziny Windows:

Crystal Disk Mark – bardzo prosty w obsłudze program, który dla wskazanego napędu wykona kilka testów. Użycie programu jest naprawdę banalne – wystarczy wybrać interesujący nas napęd, wielkość danych, na których chcemy przeprowadzić testy oraz ilość powtórzeń. Całą reszta zrobi się sama, a my dostaniemy wypełnione zmierzonymi wartościami okienko.

ATTO Disk Benchmark – program równie prosty w obsłudze, co Crystal Disk Mark, jednak wykonujący tylko jeden jest, ale na paczkach danych o różnej wielkości. Osobiście do „szybkich” testów porównawczych stosuję właśnie to narzędzie.

A co pod Linuksa?

Tutaj jest jednocześnie lepiej i gorzej :-) Lepiej, bo mamy bardzo dużo programów, za pomocą których możemy zmierzyć przeróżne parametry naszego dysku. Gorzej, bo rozwiązania stosują odmienne metodologie i ciężko jest porównywać wyniki między nimi. Ale po kolei…

dd – Najprostszym sposobem na zmierzenie wydajności przy operacjach sekwencyjnych jest użycie narzędzia dd, na przykład tak:

[kbechler@flame ~]$ sudo dd if=/dev/sda of=/dev/null bs=1024k count=4k
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 100.358 seconds, 42.8 MB/s

Tutaj jednak warto zwrócić uwagę na dwie rzeczy:
– Rozmiar czytanych lub zapisywanych danych powinien być większy, niż ilość zainstalowanej w systemie pamięci, co zabezpieczy nas przed zaburzeniem wyników poprzez systemowy cache.
– Warto pamiętać, że Linux ma zaimplementowane różne rodzaje „wspomagaczy”, które mają na celu przyspieszenie komunikacji z dyskami, a które trochę przeszkadzają przy testowaniu szybkości sprzętu. Jeżeli zależy nam na porównaniu wyników z innymi komputerami lub serwerami, to warto przeczytać chociażby to i pamiętać, że bez zastosowania dodatkowych parametrów badamy tak naprawdę wydajność całego systemu, a nie samych dysków.

hdparm – tak właściwie, to hdparm nie jest programem przeznaczonym do określania wydajności urządzeń blokowych, jednak jest do tego całkiem często wykorzystywany. Używamy tutaj tylko jednej opcji, a wynik wygląda tak:

[kbechler@flame ~]$ sudo /sbin/hdparm -t /dev/sda

/dev/sda:
 Timing buffered disk reads:  130 MB in  3.04 seconds =  42.70 MB/sec

bonnie++ – jeden z najpopularniejszych programów do testowania wydajności dysków. Ilość opcji tego programu może na początek przerazić, jednak da się to szybko opanować, jeżeli wiemy, co chcemy osiągnąć. Ja najczęściej robię coś takiego (niestety, test na innym systemie, więc ciężko porównać do wyników powyżej):

[root@lupus s]# bonnie++ -d /mnt/sdb1/konrad -s 16g -f -b -u kbechler
Using uid:500, gid:500.
Writing intelligently...done
Rewriting...done
Reading intelligently...done
start 'em...done...done...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version  1.96       ------Sequential Output------ --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
lupus.itbt.eu   16G           37734  15 21668   7           58415   7 153.1   8
Latency                        3037ms   42961ms               184ms     163ms
Version  1.96       ------Sequential Create------ --------Random Create--------
lupus.itbt.eu       -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16    78   0 +++++ +++    78   0    79   0 +++++ +++    78   0
Latency               521ms    1235us     167ms   79465us      46us     150ms
1.96,1.96,lupus.itbt.eu,1,1353399513,16G,,,,37734,15,21668,7,,,58415,7,153.1,8,16,,,,,78,0,+++++,+++,78,0,79,0,+++++,+++,78,0,,3037ms,42961ms,,184ms,163ms,521ms,1235us,167ms,79465us,46us,150ms
[root@lupus s]#

Na koniec jeszcze zestawienie narzędzi do robienia testów wydajności dysków, jakie znalazłem w Sieci. Może ktoś znajdzie coś dla siebie.

O macierzach słów kilka…

23 października, 2012 (21:03) | linux, sprzęt | By: konrad

Ostatnio wokół mnie sporo zamieszania w temacie przechowywania danych. W pracy kolega marudzi, że programowy RAID jest „niekoszerny”, na forach przewijają się pytania o kontrolery i ich „nielogiczne” zachowanie, a serwery migają wesoło na czerwono i nie wiadomo co im jest. Spróbujmy to wszystko chociaż odrobinę uporządkować.

Po kolei – RAID, czyli „nadmiarowa macierz niezależnych dysków”(*) jest to połączenie dwóch lub więcej dysków, które umożliwia osiągnięcie dodatkowych możliwości (w stosunku do pojedynczego napędu). Może to być zwiększenie wydajności, uodpornienie na awarie, lub powiększenie pojemności pojemności widzianej jako jedna całość.

Podział macierzy dyskowych możemy zrobić na podstawie ich poziomów oraz sposobu implementacji.

I tak w teorii – którą można znaleźć na Wikipedii, w mądrych książkach i na niezliczonej ilości stron i blogów – poziomów RAIDu jest całkiem sporo, jednak w praktyce spotyka się tylko kilka z nich:
RAID0 (stripe), który polega na połączeniu minimum dwóch dysków w celu zwiększenia wydajności. W żaden sposób nie zabezpiecza danych w razie awarii sprzętu. Można powiedzieć, że taka konfiguracja jest nawet mniej bezpieczna, niż kilka oddzielnych dysków, bo w przypadku awarii jednego z nich możemy utracić wszystkie dane. Teoretycznie wydajność takiej macierzy skaluje się liniowo, a podstawowe ograniczenie stanowi sam kontroler,
RAID1 (mirror) – podstawowy sposób zabezpieczenia danych przed utratą wskutek awarii dysku. Szybkość działania zależy od mechanizmów zaimplementowanych w kontrolerach lub – w przypadku programowej macierzy – sterowniku. Przykładowo: przy Linuksowym (programowym) mirrorze złożonym z dwóch dysków, podczas pojedynczego odczytu (test przy pomocy polecenia dd) system korzystał tylko z jednego dysku, chociaż teoretycznie mógłby czytać dane „po kawałku” z obydwu urządzeń,
RAID5 – najtańsza (pojemność rzeczywista przy N takich samych dysków wynosi N-1) forma ochrony danych przed awariami napędów dyskowych. Szybka przy odczycie, za to zdecydowanie wolniejsza podczas zapisu. Odporna na awarię jednego (dowolnego) dysku,
RAID6 – j.w., ale z podwójną parzystością (odporna na awarię dwóch dysków).
RAID10 – macierz o organizacji RAID0 (stripe), której elementami nie są pojedyncze dyski, tylko macierze RAID1 (mirror). Dzięki takiej organizacji osiągamy wydajność zbliżoną do poziomu RAID0 i jednoczesną ochronę danych.
RAID50/60 – j.w., ale stripe nałożony na RAID5/6.

Jeżeli zaś chodzi o sposób implementacji, to są jedynie trzy:
macierz sprzętowa (ang. hardware-based array) – do zbudowania i obsługi macierzy używany jest specjalny kontroler, który wszystkie potrzebne operacje jest w stanie wykonać sam, bez wsparcia ze strony systemu operacyjnego, sterowników ani dodatkowych programów lub urządzeń. Przykładami takich kontrolerów są Adaptec 2230S z interfejsem SCSI oraz Adaptec 5405 dla SAS.
macierz programowa – (ang. software-based array) – przez niektórych administratorów uważana za zło konieczne i rozwiązanie zdecydowanie mniej „profesjonalne”, niż opisane powyżej. Tutaj możemy wykorzystać dowolny kontroler i dowolne urządzenia blokowe (nawet pendrive i karty CF), a cała logika zarządzana jest na poziomie sterowników i oprogramowania w systemie operacyjnym. Wbrew pozorom to rozwiązanie nie jest dużo wolniejsze od jego ich sprzętowego brata, ale o tym trochę później.
fakeraid (ew. hostraid) – sposób zarządzania dyskami „mieszający” obie powyższe metody. Sama definicja i konfiguracja macierzy odbywa się w BIOSie kontrolera, zarządzaniem i monitorowaniem zajmuje się specjalny sterownik do systemu operacyjnego, a przeliczanie sum kontrolnych i rozkład poszczególnych danych na dysków realizowany jest przez procesor komputera. I właśnie z tym rodzajem związana jest zdecydowana większość problemów, na które napotykają administratorzy i użytkownicy. FakeRAIDami są np. wszystkie kontrolery oparte o układ Sil3112 lub Sil3114.

Tyle teorii, teraz zajmijmy się (moją, subiektywną) praktyką.

Po pierwsze – nazywanie macierzy „sprzętowymi” nie jest tak do końca precyzyjne. Bo przecież logika realizowana jest także tutaj przez oprogramowanie. Fakt, że zaszyte w odrębnej pamięci i operujące na dedykowanym do tego celu procesorze nic nie zmienia.

Po drugie – macierze programowe (czyli te realizowane przez elementy systemu operacyjnego) wcale nie muszą być wolniejsze od ich sprzętowych odpowiedników. I dość często nie są. Za przykład niech posłużą testy dwóch konfiguracji, które zrobiliśmy kilka lat temu:

Nr.Kontroler Ilość dysków poziom macierzy zapis[MB/s] odczyt[MB/s]
1Adaptec ASR-2230SLP 1 jeden dysk 71.4 88.0
2Adaptec ASR-2230SLP 2 programowy mirror 65.4 88.3
3Adaptec ASR-2230SLP 2 sprzętowy mirror 67.7 84.3
4Adaptec ASR-2230SLP 10 programowy RAID5 142.6 207.8
5Adaptec ASR-2230SLP 10 sprzętowy RAID5 170.4 134.4
63ware 9650SE 1 jeden dysk 61.8 64.9
73ware 9650SE 2 programowy stripe 121.4 128.6
83ware 9650SE 2 sprzętowy stripe 115.4 128.8
93ware 9650SE 2 programowy mirror 59.3 61.5
103ware 9650SE 2 sprzętowy mirror 59.0 64.6

W przypadku Adapteca użyto dysków Fujitsu MAW3073NC, natomiast do kontrolera 3ware były podłączone Raptory WD360. Jak widać z powyższej tabelki, rozbieżności nie są bardzo duże. Różnic pomiędzy testami 4. a 5. nie jestem w stanie wyjaśnić. Mogę jedynie podejrzewać, że testy zrobiliśmy na zbyt małej ilości danych lub ustawiliśmy różne wartości chunk size, które tak bardzo wpłynęły na otrzymane wyniki.

Po trzecie (które trochę łączy się z poprzednim punktem) – macierze programowe nie są takie złe. Szczególnie w przypadku porównania z kontrolerami, które nie są już produkowane. Rozważmy co możemy zrobić w przypadku awarii kontrolera (w większości konfiguracji, które widziałem jest to jednak dość krytyczny element). Jeżeli używamy programowej macierzy linuksowej (zbudowanej i obsługiwanej za pomocą narzędzia mdadm), to przekładamy zestaw dysków do dowolnego komputera, który takie napędy obsłuży (czyli da się je fizycznie podłączyć i zostaną zauważone jako pojedyncze urządzenia) i uruchamiamy normalnie system. W przypadku awarii kontrolera sprzętowego, musimy zaopatrzyć się w takie samo, lub chociaż podobne (np. Adaptec umożliwia migrację macierzy z jednych kontrolerów na inne) urządzenie i zmigrować konfiguracją na nowy kontroler. Przywiązuje nas to do producenta kontrolerów i może być problematyczne w przypadku stosowania konfiguracji już nie produkowanych (ale to się przecież w systemach produkcyjnych nie zdarza :-)). Tutaj ciekawostka: Adaptec umożliwia migrację macierzy z kontrolerów HostRAID do ich „pełnych” wersji. Można sobie o tym poczytać chociażby tutaj.

Po czwarte – wobec dostępności na rynku i obecnych cen dysków twardych, sensowność stosowania poziomu RAID5 (w porównaniu z RAID6) staje się coraz bardziej dyskusyjna. W zamian za konieczność instalacji dodatkowego dysku zyskujemy większą odporność na awarię oraz brak czasu bez ochrony danych (od momentu awarii jednego z dysków do chwili całkowitego odbudowania macierzy). Jednak migracja RAID5->RAID6 związana jest z kilkoma aspektami:
– Wspomniany już większy koszt macierzy. Różnicach w kosztach może ograniczyć się tylko do konieczności zakupu dodatkowego dysku. Jednak w przypadku braku miejsca na ten dysk, konieczny może okazać się zakup dodatkowej obudowy na dyski, co może znacznie podrożyć konfigurację,
– RAID6 wymaga większej mocy obliczeniowej, która potrzebna jest do przeliczenia sum kontrolnych przechowywanych danych, co wymaga wydajniejszych procesorów – niezależnie od tego, czy stosujemy macierz sprzętową czy programową,
– Wydajność zapisu macierzy z dwoma dyskami nadmiarowymi jest nieznacznie mniejsza, niż w przypadku RAID5.

Ufff, na razie chyba wystarczy :-)

(*) samo rozwinięcie tego skrótu jest trochę zwodnicze, bo tutaj nadmiarowość nie zawsze oznacza coś, co podnosi bezpieczeństwo i zabezpiecza nasze dane w przypadku awarii.

Edytor dla programistów

23 sierpnia, 2012 (15:08) | Bez kategorii | By: konrad

Ponieważ nigdy nie byłem (nie jestem obecnie i prawie na pewno nie będę w przyszłości) programistą, to nie interesowały mnie narzędzia przeznaczone dla tej grupy osób. Ale czasami muszę napisać jakiś mało skomplikowany program, który pozwoli mi spędzić mniej czasu nad rozwiązywanym akurat problemem, albo w ogóle pozwoli go rozwiązać. Są to zazwyczaj dość prymitywne rzeczy pisane w C. W Internecie można natknąć się na setki informacji dotyczących najbardziej chyba obecnie popularnego środowiska, jakim jest Eclipse. Jednak jest to dla mnie przerost formy nad treścią. Eclipse jest fajne, elastyczne i bardzo rozbudowane. No właśnie – zdecydowanie zbyt rozbudowane, jak na moje skromne potrzeby. Chciałbym mieć coś w miarę lekkiego, co potrafiłoby pokolorować składnię, było w miarę wygodne i potrafiło obsłużyć kompilatory C dla różnych architektur. Znalazłem code::blocks i bardzo mi się spodobał. Nie dość, że ma wszystko to, co chciałem, to na dodatek można sobie pobrać paczkę dla Windows (bo taka mi jest potrzebna), w której znajduje się jednocześnie edytor oraz kompilator C (w wersji MinGW).

Środowisko obsługuje wiele różnych kompilatorów (między innymi GNU GCC na pięć różnych architektur sprzętowych), a ich konfiguracja polega na podaniu ścieżki, w której taki kompilator zainstalowaliśmy. W moim przypadku „podłączenie” AVR toolchain Atmela polegało na wyklikaniu ścieżki i naciśnięciu „OK”.

W miarę ładnie działa także integracja z debuggerem – code::block samo wyszukuje i na bieżąco pokazuje wartości zmiennych lokalnych oraz parametrów wywołania funkcji.

Jedyne, czego mi brakuje, to możliwość użycia tego środowiska przy pisaniu programów w asemblerze, ale zdarza mi się to na tyle rzadko, że nie będę specjalnie narzekał.

Skrypt do backupu Microsoft SQLa

31 lipca, 2012 (09:15) | windows | By: konrad

O tym, że kopie zapasowe są niezbędnym elementem każdego środowiska IT, nie trzeba chyba przekonywać nikogo. Nawet najbardziej oporni na wiedzę techniczną dyrektorzy zdają sobie sprawę, że sprzęt to materia na tyle złośliwa, że potrafi się popsuć w najmniej odpowiednim momencie. No, chyba że ja miałem do tej pory wyjątkowe szczęście i spotykałem na swojej drodze wyjątkowo rozsądnych ludzi, ale z tego powodu płakał jakoś specjalnie nie będę. Jednak pomimo sporej świadomości kadry zarządzającej o konieczności tworzenia kopii zapasowych, próba wydania jakichkolwiek pieniędzy na oprogramowanie służące temu celowi często kończy się porażką.

Narzędzi do wykonywania kopii zapasowych samych systemów, jak i poszczególnych jego części, jest bardzo wiele. W przypadku Microsoft SQLa jest BackupExec Symanteca, jest Data Protection Manager Microsoftu i pewnie wiele innych produktów, które – poza tym, że potrafią wykonać tytułową kopię bezpieczeństwa – łączy jedna cecha – są płatne. O ile w przypadku dużej korporacji, przekonanie działu finansowego do takiego wydatku jest jak najbardziej realne, to dla małych, kilkuosobowych firm, DPM (lub inny tego typu produkt) może być znaczącą pozycją w budżecie IT. Jeżeli takowy w ogóle istnieje. Na szczęście jest kilka metod, za pomocą których możemy wykonywać kopie zapasowe, nie kupując specjalizowanego oprogramowania.

W przypadku MSSQLa najłatwiej wykonać taką operację za pomocą skryptu w T-SQL uruchamianego z poziomu Windowsowego Harmonogramu Zadań. Ponieważ jestem zbyt leniwy, żeby pisać coś samemu, poprosiłem Wujka Google o gotowca i w odpowiedzi na moje błagania dostałem takiego oto linka. To, co prezentuję poniżej to bardzo delikatnie zmieniony skrypt ze wspomnianej przed chwilą strony:

-- slightly modified script from www.mssqltips.com site
-- (http://www.mssqltips.com/sqlservertip/1070/simple-script-to-backup-all-sql-server-databases)
DECLARE	@hostname VARCHAR(20)		-- hostname of a server
DECLARE	@db_name VARCHAR(50)		-- database name 
DECLARE	@backup_path VARCHAR(256)	-- path for backup files 
DECLARE	@backup_file VARCHAR(256)	-- filename for backup 
DECLARE	@current_date VARCHAR(20)	-- used for file name

SET @backup_path = 'd:\backup' 
SET @current_date = CONVERT(VARCHAR(20), GETDATE(), 112)
SET @hostname = HOST_NAME()

DECLARE db_cursor CURSOR FOR 
  SELECT name 
    FROM master.dbo.sysdatabases 
    WHERE name NOT IN ('master','model','msdb','tempdb') 

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @db_name
WHILE @@FETCH_STATUS = 0  
BEGIN 
  SET @backup_file = @backup_path + "\" + @hostname + '-' + @current_date + '-' + @db_name + '.BAK' 
  BACKUP DATABASE @db_name TO DISK = @backup_file
  FETCH NEXT FROM db_cursor INTO @db_name
END  

CLOSE db_cursor  
DEALLOCATE db_cursor

Jak to wykorzystać w praktyce? Najłatwiej umieścić w jakimś pliku (u mnie jest to c:\scripts\mssql_backup.sql) i dodać do harmonogramu cykliczne wywołanie, np. za pomocą sqlcmd. Niemiłą niespodzianką, która może nas przy takiej konfiguracji spotkać, to brak miejsca na dysku z kopiami zapasowymi, ponieważ powyższy mechanizm nie umie kasować najstarszych plików z utworzonymi przed siebie kopiami. Żeby sobie poradzić także z tym problemem, napisałem jeszcze jeden, prościutki skrypt, który wygląda tak:

forfiles -p "d:\backup" -s -m *.* -d -15 -c "cmd /c del @path"
sqlcmd -S NAZWA_SERWERA_MSSQL -i "c:\scripts\mssql_backup.sql" -o "c:\scripts\mssql_backup_last.txt"

Wystarczy już tylko „zaplanować” odpowiednie zadanie, i kopie zapasowe baz danych będą się robić automagicznie. Musimy oczywiście zadbać o to, żeby pliki z kopiami znalazły się na innej maszynie niż ta, którą zabezpieczamy, bo inaczej robienie kopii ma niewielki sens :-)

„Lista argumentów za długa” po raz kolejny

24 lipca, 2012 (07:47) | centos, linux | By: konrad

Jakiś czas temu pisałem o komunikacie „Lista argumentów za długa„, którym może nas uraczyć system Uniksowy w przypadku zaserwowania wywoływanemu poleceniu zbyt długiej listy z argumentami (czyli komunikat jest nawet dość dokładny :-)). Ale dlaczego tak się właściwie dzieje i w którym momencie nasza lista robi się dla systemu „za długa”? Okazuje się, że wszystko to przez POSIX i jego opcję ARG_MAX. Standardowo w Linuksach (przynajmniej tych z kernelem w wersji 2.6, ale – żeby nie było zbyt prosto – niższej, niż 2.6.33) wartość tego parametru ustawiona jest na 128KB (czyli 131072 bajtów).

Możemy sprawdzić, jak to wygląda u nas:

[kbechler@flame ~]$ uname -r
2.6.18-308.1.1.el5
[kbechler@flame ~]$ getconf ARG_MAX
131072
[kbechler@flame ~]$

Czy można zmienić wartość ARG_MAX? Ponieważ w Linuksie da się zmienić wszystko, a ta opcja nie stanowi wyjątku, odpowiedź brzmi – TAK. Z drugiej strony – czy powinniśmy to robić? Według mnie NIE. Bo niby po co? Wszystkie przypadki, w których tytułowy komunikat jest przeszkodą, można „załatwić” iteracją po liście plików lub wykorzystać do pomocy xargs. Jeżeli jednak zmienimy ARG_MAX, to zmienią nam się „warunki środowiskowe” wszystkich uruchamianych programów, a w szczególności zwiększy się zapotrzebowanie systemu na RAM, co z kolei w zauważalny sposób wpłynie na jego szybkość. Poza tym jest to tylko przesuwanie limitów, a nie rozwiązywanie problemów, więc – jeżeli już teraz mamy taki problem – jest duża szansa, że w przyszłości znowu będziemy zmuszeni do zmian. Generalizując: w tym wypadku lepszym pomysłem wydaje mi się wyeliminowanie problemu (np. poprzez wykorzystanie iteracji) niż przesuwanie go w czasie (za pomocą zwiększania limitów).

Jeżeli jednak ktoś się upiera przy zmianie limitów, to w przypadku kerneli > 2.6.33 (gdzie wartość ARG_MAX jest równa 1/4 wartości „user-space stack”) jest to bardzo proste:

[kbechler@fedora ~]$ uname -r
3.4.2-1.fc16.i686.PAE
[kbechler@fedora ~]$ getconf ARG_MAX
2097152
[kbechler@fedora ~]$ ulimit -s
8192
[kbechler@fedora ~]$ ulimit -s 2048
[kbechler@fedora ~]$ ulimit -s
2048
[kbechler@fedora ~]$ getconf ARG_MAX
524288

Dla ciekawskich jeszcze LINK, gdzie można poczytać o zagadnieniu trochę dokładniej.

Zmiana adresu źródłowego dla połączeń wychodzących w linuksie

17 lipca, 2012 (08:24) | linux | By: konrad

Ostatnio na forum CentOSa pojawił się wątek dotyczący nawiązywania połączeń z hosta lokalnego, ale ze zmienionym adresem źródłowym. Warto by było w przejrzystej formie zebrać wszystko, co można w takiej sytuacji zrobić.

Zacznijmy od konfiguracji samego hosta. Zakładam, że mamy poprawnie skonfigurowany system z CentOSem z jednym interfejsem sieciowym (eth0), do którego „przypięliśmy” kilka adresów IP:

[root@honey1 ~]# ip addr
1: lo:  mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc mq state UNKNOWN qlen 1000
    link/ether 00:0c:29:19:94:72 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.168/26 brd 192.168.0.191 scope global eth0
    inet 192.168.0.169/26 brd 192.168.0.191 scope global secondary eth0:0
    inet 192.168.0.170/26 brd 192.168.0.191 scope global secondary eth0:1
    inet 192.168.0.171/26 brd 192.168.0.191 scope global secondary eth0:2
    inet 192.168.0.172/26 brd 192.168.0.191 scope global secondary eth0:3
    inet 192.168.0.173/26 brd 192.168.0.191 scope global secondary eth0:4
    inet 192.168.0.174/26 brd 192.168.0.191 scope global secondary eth0:5
    inet 192.168.0.175/26 brd 192.168.0.191 scope global secondary eth0:6
    inet6 fe80::20c:29ff:fe19:9472/64 scope link
       valid_lft forever preferred_lft forever
[root@honey1 ~]# ip route
192.168.0.128/26 dev eth0  proto kernel  scope link  src 192.168.0.168
169.254.0.0/16 dev eth0  scope link  metric 1002
default via 192.168.0.190 dev eth0
[root@honey1 ~]#

Standardowo, wszystkie połączenia, które zaczynają się na tej maszynie będą widoczne w świecie jako pakiety pochodzące od pierwszego adresu, czyli 192.168.0.168. Co możemy zrobić, żeby to zmienić? Kilka rzeczy.

Po pierwsze – najprostsze, ale czasami przydatne – możemy zmienić adres źródłowy dla wszystkich połączeń wychodzących. Albo za pomocą zmian w tablicy routingu (musimy oczywiście pamiętać, aby adres IP zgadzał się z oznaczeniem interfejsu :-)):

ip route replace default dev eth0:1 src 192.168.0.170

albo za pomocą narzędzia iptables:

iptables -t nat -A POSTROUTING -j SNAT --to-source 192.168.0.170

Oba powyższe rozwiązania mają swoje wady i zalety, chociaż w większości przypadków zastosowałbym raczej to pierwsze.

Po drugie – używając odpowiednich „filtrów” możemy zrobić to samo, ale tylko dla wybranych hostów w Sieci. Komendy, odpowiednio, będą wyglądały tak:

ip route add 10.0.0.0/16 dev eth0:1 src 192.168.0.170
iptables -t nat -A POSTROUTING -d 10.0.0.0/16 -j SNAT --to-source 192.168.0.170

Tak w zasadzie niewiele się zmieniło. Polecenia zostały te same, rozbudowałem je tylko o odpowiednie warunki ograniczające adresy docelowe.

Po trzecie – zrobić tak, żeby adres źródłowy ustawiany był w zależności od użytkownika (lub grupy) w systemie. Na kilku stronach znalazłem coś takiego:

iptables -t nat -A POSTROUTING -m owner --uid-owner kbechler -j SNAT --to-source 192.168.0.170
iptables -t nat -A POSTROUTING -m owner --gid-owner kbechler -j SNAT --to-source 192.168.0.170

Wydaje się być OK i działać poprawnie. Chociaż tutaj można się naciąć na pewien „problem”. Podczas pierwszych testów (przeprowadzanych za pomocą pinga na serwerze źródłowym i tcpdumpa na docelowym), zadziałała mi jedynie wersja z „–gid-owner”, czyli przypisanie adresu dla grupy. Pomimo próśb i zaklęć, wersja „per user” nie chciała zrobić tego, co bym chciał. Odpowiedź, po krótkim poszukiwaniu, znalazłem TUTAJ. Okazuje się, że generowanie ruchu ICMP wymaga tzw. raw socket, co z kolei wymusza działanie z prawami roota. I z tego powodu, narzędzie 'ping’ ma ustawiony bit SUID – do tej pory nie zwróciłem na to uwagi.

Jeżeli chodzi o możliwości samego systemu, to właściwie tyle. Większość potrzeb można „załatwić” za pomocą jednej z opisanych wyżej metod. Jeżeli potrzebujemy czegoś bardziej skomplikowanego, to pewnie też da się zrobić, np. za pomocą dodatkowych tablic routingu.

Na koniec warto jeszcze zauważyć, że niektóre narzędzia same potrafią zmienić adres źródłowy, z którego nawiązują połączenie (jak choćby wget i jego opcja –bind-address). Jeżeli więc nie mamy zbyt dużych wymagań, to powinniśmy zacząć od przejrzenia dokumentacji narzędzia, którego używamy. Jest to metoda o tyle fajna, że działa w przestrzeni użytkownika i można z niej skorzystać w sytuacji, kiedy nie mamy uprawnień roota.

Wirtualny serwer terminali i dźwięk

12 lipca, 2012 (09:29) | vmware, windows | By: konrad

Nadeszła nowa era – era wirtualizacji. Pochłonęła już większość naszych serwerów, a teraz dobrała się też do stacji roboczych. Użytkownicy płaczą i zgrzytają zębami, zastanawiając się, gdzie będą przechowywać dziesiątki filmów i tysiące MP3ek. Ale taka jest cena postępu cywilizacyjnego.

Przechodząc do tematu zasadniczego, kończymy właśnie konfigurować serwer terminali, który już niedługo zasiedlony będzie przez pierwszych użytkowników. Wiem, że będą smutni, bo będą musieli rozstać się ze swoimi grubymi klientami i mam zamiar zrobić wszystko (no dobra, wszystko to może nie, ale sporo), żeby nie czuli się aż tak bardzo źle. A przecież nie da się pracować bez dźwięku… I tu pojawił się problem, którego rozwiązanie nie jest takie do końca oczywiste – jak spowodować, żeby serwer terminali bez karty dźwiękowej potrafił generować dźwięk (konkretnie chodzi o maszynę wirtualną z Windows 2008 R2, do której użytkownicy podłączają się za pomocą RDPa).

Wbrew pozorom (a dokładniej: wbrew temu, co mi na początku przyszło do głowy) nie trzeba kombinować z mniej lub bardziej wirtualnymi kartami dźwiękowymi w serwerze. Do zrobienia są dwie zaledwie rzeczy:
– skonfigurować klienta RDPa tak, żeby odtwarzał dźwięki z komputera zdalnego,
– skonfigurować serwer terminali tak, żeby pozwalał na odtwarzanie dźwięku w sesjach zdalnych.

Pierwszy punkt można zrealizować w sposób prosty, intuicyjny i dobrze opisany (choćby TUTAJ). Wystarczy w zakładce „Zasoby lokalne” zaznaczyć odpowiednią opcję i po kłopocie.

Trochę gorzej jest natomiast z samym serwerem. A właściwie może nie tyle gorzej, bo też wystarczy zmiana jednej opcji, ale zdecydowanie trudniej ją znaleźć. Do magicznego miejsca możemy dotrzeć w następujący sposób:

– Logujemy się RDPem na zdalną maszynę i uruchamiamy „Remote Desktop Session Host Configuration” (zakopane to jest w „Menu Start” -> „Administratiove Tools” -> „Remote Desktop Services”),
– Klikamy dwa razy na „RDP-Tcp” (o ile nie zmieniliśmy domyślnej konfiguracji) i wybieramy zakladkę „Client Settings”,
Odznaczamy opcję „Audio and video playback”.
Teraz wystarczy zamknąć sesję RDPa, podłączyć się ponownie i możemy cieszyć się pełnowartościowym YouTube’m :-)