Infrastructure as Code: jak rozwiązać problemy za pomocą XP

Cześć, Habr! Kiedyś narzekałem na życie w paradygmacie infrastruktury jako kodu i nic nie proponowałem, aby rozwiązać tę sytuację. Dziś wróciłem, aby opowiedzieć, jakie podejścia i praktyki mogą pomóc wydostać się z otchłani rozpaczy i skierować sytuację we właściwym kierunku.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

W poprzednim artykule Infrastruktura jako kod: pierwsze spotkanie Dzieliłem się moimi wrażeniami z tej dziedziny, próbowałem zastanowić się nad obecną sytuacją w tej branży i nawet zasugerowałem, że standardowe, znane wszystkim programistom praktyki mogą pomóc. Mogło się wydawać, że było tam dużo narzekań na życie, ale brakowało propozycji wyjścia z trudnej sytuacji.

Kim jesteśmy, gdzie jesteśmy i jakie mamy problemy

Obecnie jesteśmy w zespole SRE Onboarding Team, który składa się z sześciu programistów i trzech inżynierów infrastruktury. Wszyscy staramy się pisać infrastrukturę jako kod (IaC). Robimy to, ponieważ w zasadzie potrafimy pisać kod i tak naprawdę jesteśmy programistami na poziomie „powyżej średniej”.

  • Mamy zestaw zalet: pewne tło, znajomość praktyk, umiejętność pisania kodu oraz chęć uczenia się nowych rzeczy.
  • A jest też słaba strona, czyli minus: brak wiedzy na temat infrastruktury.

Stos technologii, które używamy w naszym IaC.

  • Terraform do tworzenia zasobów.
  • Packer do budowania obrazów. Są to obrazy Windows i CentOS 7.
  • Jsonnet, aby tworzyć potężne budowy w drone.io, a także do generacji packer json i naszych modułów Terraform.
  • Azure.
  • Ansible podczas przygotowywania obrazów.
  • Python do usług pomocniczych, jak również skryptów provisioningowych.
  • A wszystko to w VSCode z wtyczkami, udostępnionymi między członkami zespołu.

Wniosek z mojej poprzedniego artykułu był taki: próbowałem wpoić (przede wszystkim w siebie) optymizm, chciałem powiedzieć, że będziemy próbować znanych nam podejść i praktyk, aby walczyć z trudnościami i skomplikowaniem, które są w tej dziedzinie.

W tej chwili zmierzamy się z następującymi problemami IaC:

  • Niedoskonałość narzędzi, środków do tworzenia kodu.
  • Wolne wdrażanie. Infrastruktura to część rzeczywistego świata, a ten może być nieprędki.
  • Brak podejść i praktyk.
  • Jesteśmy nowicjuszami i niewiele wiemy.

Ekstremalne programowanie (XP) spieszy z pomocą

Wszystkim programistom dobrze znane jest ekstremalne programowanie (XP) oraz praktyki, które za nim stoją. Wielu z nas pracowało według tego podejścia, i okazało się ono skuteczne. Więc dlaczego nie skorzystać z zasad i praktyk w nim zawartych, aby poradzić sobie z trudnościami infrastruktury? Postanowiliśmy zastosować to podejście i zobaczyć, co z tego wyniknie.

Ocena zastosowania podejścia XP w Twojej dziedziniePodaję opis środowiska, dla którego XP nadaje się najlepiej, oraz jak to się odnosi do nas:

1. Dynamicznie zmieniające się wymagania oprogramowania. Wiedzieliśmy, jaki jest ostateczny cel. Jednak szczegóły mogą się różnić. Sami decydujemy, w którą stronę powinniśmy się skierować, dlatego wymagania okresowo się zmieniają (głównie przez nas samych). W przypadku zespołu SRE, który sam zajmuje się automatyzacją i ogranicza wymagania oraz zakres prac, ten punkt dobrze sprawdza się.

2. Ryzyko wynikające z projektów o stałym czasie przy użyciu nowych technologii. Mogą pojawić się ryzyka związane z użyciem rzeczy, które są nam nieznane. I to jest w 100% nasz przypadek. Cały nasz projekt opiera się na technologiach, z którymi nie byliśmy do końca zaznajomieni. To wciąż jest problem, ponieważ w dziedzinie infrastruktury nieustannie pojawia się wiele nowych technologii.

3,4. Mały, współlokalizowany rozwinięty zespół. Technologia, którą używasz, umożliwia automatyczne testy jednostkowe i funkcjonalne. Te dwa punkty nie do końca do nas pasują. Po pierwsze, nie jesteśmy współlokalizowanym zespołem, po drugie, jest nas dziewięć osób, co można uznać za duży zespół. Choć według niektórych definicji „dużego” zespołu, wiele to 14+ osób.

Przyjrzyjmy się niektórym praktykom z XP i temu, jak wpływają one na szybkość i jakość informacji zwrotnej.

Zasada cyklu informacji zwrotnej w XP

Moim zdaniem informacja zwrotna to odpowiedź na pytanie, czy dobrze to robię, czy idziemy w dobrym kierunku? W XP istnieje na ten temat cudowny schemat: cykl informacji zwrotnej w czasie. Interesujące jest to, że im niżej jesteśmy, tym szybciej możemy uzyskać OS, aby odpowiedzieć na swoje pytania.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

To dość ciekawy temat do dyskusji, że w naszej branży IT można szybko uzyskać OS. Wyobraź sobie, jak trudne jest zrealizowanie jakiegoś projektu przez sześć miesięcy i dopiero wtedy dowiedzieć się, że na samym początku popełniono błąd. Takie sytuacje zdarzają się zarówno w projektowaniu, jak i w każdym budowaniu skomplikowanych systemów.

W naszym przypadku IaC pomaga nam w uzyskaniu informacji zwrotnej. Od razu wprowadzam niewielką korektę do powyższego schematu: plan wydania realizowany jest nie w miesięcznym cyklu, lecz odbywa się kilka razy dziennie. Do tego cyklu OS są przypisane pewne praktyki, które omówimy bardziej szczegółowo.

Ważne: informacja zwrotna może stać się rozwiązaniem dla wszystkich wymienionych powyżej problemów. W połączeniu z praktykami XP może wyciągnąć z otchłani rozpaczy.

Jak wyciągnąć siebie z otchłani rozpaczy: trzy praktyki

Testy

Testy są wspomniane dwukrotnie w cyklu informacji zwrotnej XP. Nie jest to przypadkowe. Są niezwykle ważne dla całej techniki programowania ekstremalnego.

Zakłada się, że masz testy jednostkowe i akceptacyjne. Jedne dają Ci informację zwrotną w ciągu kilku minut, inne w ciągu kilku dni, dlatego pisze się je dłużej, a uruchamia rzadziej.

Istnieje klasyczna piramida testowania, która pokazuje, że pewnych testów powinno być więcej.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

Jak ten schemat jest zastosowany w naszym projekcie IaC? W rzeczywistości… wcale.

  • Testów jednostkowych, mimo że powinno ich być bardzo wiele, nie może być za dużo. Albo testują coś bardzo pośrednio. Można praktycznie powiedzieć, że w ogóle ich nie piszemy. Ale oto kilka zastosowań dla takich testów, które udało nam się jednak wykonać:
    1. Testowanie kodu w jsonnet. To na przykład nasz pipeline budowania w drone, który jest dość skomplikowany. Kod w jsonnet jest dobrze pokrywany testami.
      Używamy tego Unit testing framework for Jsonnet.
    2. Testy skryptów, które są wykonywane przy uruchamianiu zasobu. Skrypty w Pythonie, więc również testy na nie można pisać.
  • Potencjalnie możliwa jest weryfikacja konfiguracji w testach, ale tak nie robimy. Jest również możliwość skonfigurowania weryfikacji zasad konfigurowania zasobów za pomocą tflint. Jednak dla terraforma są tam zbyt podstawowe kontrole, ale wiele scenariuszy testowych napisano dla AWS. A my jesteśmy na Azure, więc to znowu nie pasuje.
  • Testy integracyjne komponentów: to zależy od tego, jak je klasyfikujesz i gdzie je rozkładasz. Ale zasadniczo działają.

    Tak wyglądają testy integracyjne.

    Infrastructure as Code: jak rozwiązać problemy za pomocą XP

    To przykład podczas budowania obrazów w Drone CI. Aby do nich dotrzeć, trzeba czekać 30 minut na zbudowanie obrazu Packer, a następnie jeszcze 15 minut, aż zostaną zakończone. Ale są!

    Algorytm weryfikacji obrazów

    1. Najpierw Packer musi całkowicie przygotować obraz.
    2. Obok testu znajduje się terraform z lokalnym stanem, który wykorzystujemy do uruchamiania tego obrazu.
    3. Podczas uruchamiania wykorzystywany jest mały moduł leżący obok, co ułatwia pracę z obrazem.
    4. Gdy VM jest uruchomiona z obrazu, można rozpocząć testy. W zasadzie testy prowadzone są na maszynie. Sprawdzane jest, jak działają skrypty przy starcie i jak funkcjonują demony. W tym celu przez ssh lub winrm wchodzimy na właśnie uruchomioną maszynę i sprawdzamy stan konfiguracji lub, czy uruchomiły się usługi.

  • Podobna sytuacja dotyczy testów integracyjnych i modułów dla terrraform. Oto krótka tabela wyjaśniająca szczegóły takich testów.

    Infrastructure as Code: jak rozwiązać problemy za pomocą XP

    Czas odpowiedzi na pipeline wynosi około 40 minut. Wszystko przebiega bardzo powoli. Można to wykorzystać do regresji, ale w przypadku nowego rozwoju jest to całkowicie niemożliwe. Jeśli naprawdę się do tego przygotujesz, przygotujesz running i skrypty, można skrócić to do 10 minut. Ale to i tak nie są testy jednostkowe, które wykonują 100 testów w 5 sekund.

Brak testów jednostkowych przy tworzeniu obrazów lub modułów terrraform zmusza do przerzucania pracy na osobne usługi, które można łatwo wywołać przez REST, lub na skrypty Python.

Na przykład, musieliśmy zrobić tak, aby przy uruchomieniu maszyny wirtualnej rejestrowała się ona w usłudze ScaleFT, a przy usunięciu wirtualki usuwała siebie.

Ponieważ ScaleFT jest dla nas usługą, jesteśmy zmuszeni pracować z nią przez API. Została napisana nakładka, którą można wywołać i powiedzieć: „Zdejmij to i tamto”. Przechowuje ona wszystkie niezbędne ustawienia i dostęp.

Na to możemy już pisać normalne testy, ponieważ nie różni się to od zwykłego oprogramowania: mockujesz jakieś API, wywołujesz je i obserwujesz, co się dzieje.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

Podsumowanie testów: Testowanie jednostkowe, które powinno dawać OS w minutę, tego nie robi. A wyższe rodzaje testów w piramidzie dają efekt, ale obejmują tylko część problemów.

Programowanie w parach

Testy to oczywiście coś dobrego. Można ich pisać dużo, mogą być różnych rodzajów. Będą działać na swoich poziomach i dawać nam zwrotną informację. Jednak problem z kiepskimi testami jednostkowymi, które dają najszybszy system operacyjny, nadal pozostaje. A jednak wciąż pragnie się szybkiego systemu operacyjnego, z którym łatwo i przyjemnie się pracuje. Nie wspominając już o jakości uzyskanego rozwiązania. Na szczęście istnieją techniki, które pozwalają na szybsze uzyskanie informacji zwrotnej niż testy modułowe. To programowanie w parach.

Pisząc kod, chcemy jak najszybciej uzyskać informację zwrotną na jego temat. Tak, można napisać wszystko w gałęzi funkcji (aby nikomu nic nie popsuli), zrobić pull request na GitHubie, przypisać go do kogoś, kogo zdanie ma znaczenie, i czekać na odpowiedź.

Ale czekanie może trwać długo. Ludzie są zajęci, a odpowiedź, nawet jeśli przyjdzie, może nie być najwyższej jakości. Załóżmy, że odpowiedź przyszła od razu, recenzent momentalnie zrozumiał cały zamysł, ale odpowiedź i tak przychodzi z opóźnieniem, post factum. A chcielibyśmy wcześniej. Właśnie to programowanie w parach ma na celu – by natychmiast, w momencie pisania.

Następnie przedstawiam style programowania w parach oraz ich zastosowanie w pracy nad IaC:

1. Klasyczny, Doświadczony+doświadczony, zmiana co określony czas. Dwie role – kierowca i nawigator. Dwie osoby. Pracują nad jednym kodem i zmieniają się rolami co określony z góry czas.

Zobaczmy, jak nasze problemy łączą się ze stylem:

  • Problem: niedoskonałość narzędzi i środków do tworzenia kodu.
    Negatywny wpływ: dłużej się rozwija, spowalniamy się, rytm pracy się zaburza.
    Jak z tym walczymy: stosujemy inne narzędzia, wspólne IDE i dodatkowo uczymy się skrótów.
  • Problem: wolne wdrażanie.
    Negatywny wpływ: wydłuża czas tworzenia działającego kawałka kodu. Nudzimy się podczas czekania, ręce ciągną, by zająć się czymś innym, podczas oczekiwania.
    Jak z tym walczymy: nie pokonaliśmy tego.
  • Problem: brak podejść i praktyk.
    Negatywny wpływ: brak wiedzy, jak robić dobrze, a jak źle. Wydłuża uzyskiwanie informacji zwrotnej.
    Jak z tym walczymy: wzajemna wymiana opinii i praktyk w pracy w parach prawie rozwiązuje problem.

Głównym problemem związanym z zastosowaniem tego stylu w IaC jest nierównomierne tempo pracy. W tradycyjnym programowaniu masz bardzo równomierny postęp. Możesz spędzić pięć minut i napisać N. Spędzić 10 minut i napisać 2N, 15 minut – 3N. Tutaj można spędzić pięć minut i napisać N, a potem spędzić kolejne 30 minut i napisać jedną dziesiątą N. Tutaj nic nie wiesz, masz zator. Rozwiązywanie problemu zajmuje czas i odciąga od samego programowania.

Wniosek: w czystej postaci nam to nie odpowiada.

2. Ping-pong. To podejście zakłada, że jeden uczestnik pisze test, a drugi tworzy jego implementację. Biorąc pod uwagę, że z testami jednostkowymi wszystko jest skomplikowane i trzeba pisać długie testy integracyjne, wszelka lekkość ping-ponga znika.

Mogę powiedzieć, że próbowaliśmy podziału obowiązków w projektowaniu scenariusza testu i implementacji kodu do niego. Jeden uczestnik wymyślał scenariusz, w tej części pracy był odpowiedzialny, miał ostatnie słowo. A drugi był odpowiedzialny za implementację. To wychodziło dobrze. Jakość scenariusza wzrastała przy takim podejściu.

Wniosek: niestety, tempo pracy nie pozwala na użycie ping-ponga jako praktyki programowania w parach w IaC.

3. Strong Style. Skomplikowana praktyka. Idea polega na tym, że jeden uczestnik staje się dyrektywnym nawigatorem, a drugi przyjmuje rolę wykonawczego kierowcy. Przy tym prawo decyzji należy wyłącznie do nawigatora. Kierowca jedynie pisze i słowem może wpłynąć na to, co się dzieje. Role nie zmieniają się przez długi czas.

Dobrze sprawdza się w nauce, ale wymaga silnych umiejętności interpersonalnych. Na tym się potknęliśmy. Technika szła trudno. I nie chodzi tutaj nawet o infrastrukturę.

Wniosek: potencjalnie może być stosowane, nie rezygnujemy z prób.

4. Mobbing, swarming i wszystkie znane, ale tu nie wymienione style nie rozważamy, ponieważ nie próbowaliśmy i nie możemy o tym mówić w kontekście naszej pracy.

Ogólne wnioski dotyczące stosowania programowania w parach:

  • Mamy nierównomierne tempo pracy, które dezorientuje.
  • Zderzyliśmy się z niewystarczająco dobrymi umiejętnościami interpersonalnymi. A przedmiot pracy nie sprzyja pokonywaniu tych naszych braków.
  • Długie testy, problemy z narzędziami sprawiają, że wspólne programowanie staje się mozołem.

5. Mimo to, odnotowaliśmy również sukcesy. Opracowaliśmy naszą własną metodę „Zbieżność - rozbieżność”. Krótko opiszę, jak to działa.

Mamy stałych partnerów na kilka dni (mniej niż tydzień). Wspólnie realizujemy jedno zadanie. Przez jakiś czas pracujemy razem: jedna osoba pisze, druga obserwuje, jak zespół wsparcia. Potem rozdzielamy się na jakiś czas, każda osoba wykonuje niezależne zadania, po czym znowu się spotykamy, szybko synchronizujemy, robiąc coś razem i znów się rozdzielamy.

Planowanie i komunikacja

Ostatni blok praktyk, poprzez które rozwiązujemy problemy OS, to organizacja prac związanych z samymi zadaniami. Wchodzi w to również wymiana doświadczeń, które wychodzą poza pracę w parze. Rozważmy trzy praktyki:

1. Zadania przez drzewo celów. Ogólne prowadzenie projektu organizujemy poprzez drzewo, które nieprzerwanie sięga w przyszłość. Technicznie prowadzenie jest realizowane w Miro. Jest jedno zadanie - to cel pośredni. Z niego wynikają mniejsze cele lub grupy zadań. Z nich powstają same zadania. Wszystkie zadania są tworzone i prowadzone na tej tablicy.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

Ten schemat również daje informacje zwrotne, które odbywają się raz dziennie, gdy synchronizujemy się na spotkaniach. Posiadanie wspólnego planu, który jest jednocześnie usystematyzowany i całkowicie otwarty, pozwala każdemu być na bieżąco z postępami i tym, jak daleko zaszliśmy.

Zalety wizualnego przedstawiania zadań:

  • Kausalność. Każde zadanie prowadzi do jakiegoś ogólnego celu. Zadania grupowane są według mniejszych celów. Obszar infrastruktury sam w sobie jest dość techniczny. Nie zawsze od razu wiadomo, jakie konkretnie ma wpływ na biznes, na przykład pisanie podręcznika migracji na innego nginx. Obecność celu obok karty czynności czyni to bardziej zrozumiałym.
    Infrastructure as Code: jak rozwiązać problemy za pomocą XP
    Kausalność to ważna cecha zadań. Bezpośrednio odpowiada na pytanie: „Czy to, co robię, jest właściwe?”
  • Równoległość. Jest nas dziewięcioro i fizycznie niemożliwe jest, aby wszyscy skupiali się na jednym zadaniu. Zadania z jednej dziedziny nie zawsze wystarczą. Zmuszeni jesteśmy dzielić pracę między małe grupy robocze. Grupy pracują przez pewien czas nad swoim zadaniem, mogą być dodatkowo wzmocnione przez kogoś innego. Czasami z tej grupy roboczej odchodzą ludzie. Ktoś idzie na urlop, ktoś przygotowuje prezentację na konferencję DevOps conf, ktoś inny pisze artykuł na Habr. Ważne staje się zrozumienie, jakie cele i zadania mogą być realizowane równolegle.

2. Zmienni prowadzący poranne spotkania. Na stand-upach pojawił się problem – wiele zadań ludzie wykonują równolegle. Czasami zadania są słabo powiązane i nie ma zrozumienia, kto co robi. A zdanie jeszcze jednego członka zespołu jest bardzo ważne. To dodatkowa informacja, która może zmienić przebieg rozwiązania zadania. Oczywiście zazwyczaj jest z tobą ktoś w parze, ale konsultacje i wskazówki zawsze są pomocne.

Aby poprawić tę sytuację, wprowadziliśmy technikę „Zmiana prowadzącego stand-up”. Teraz rotujemy według określonej listy i to ma swój efekt. Kiedy nadchodzi twoja kolej, zmuszasz się do zanurzenia i zrozumienia, co się dzieje, aby dobrze przeprowadzić spotkanie scrumowe.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

3. Wewnętrzne demo. Pomoc w rozwiązywaniu zadań przez programowanie w parach, wizualizacja w drzewie zadań i wsparcie w porannych scrumach – to dobre, ale nie idealne. W parze ograniczasz się tylko do swojej wiedzy. Drzewo zadań pomaga globalnie zrozumieć, kto co robi. A prowadzący i koledzy na porannym spotkaniu nie zanurzą się głęboko w twoje problemy. Na pewno mogą coś przeoczyć.

Rozwiązaniem okazało się prezentowanie zrealizowanych prac sobie nawzajem i ich późniejsze omawianie. Spotykamy się raz w tygodniu na godzinę i pokazujemy szczegóły rozwiązań związanych z zadaniami, które realizowaliśmy w ostatnim tygodniu.

W trakcie prezentacji należy ujawnić szczegóły zadania i koniecznie pokazać jego działanie.

Prezentację można prowadzić według listy kontrolnej.1. Wprowadź w kontekst. Skąd wziął się problem, po co to w ogóle było potrzebne?

2. Jak problem był rozwiązywany do tej pory? Na przykład, potrzebne było masowe klikanie myszką, lub w ogóle nie dało się czegoś zrobić.

3. Jak to poprawiamy. Na przykład: „Zobaczcie, teraz mamy skrypt, oto readme.”

4. Pokaż, jak to działa. Najlepiej zrealizować jakiś scenariusz użytkownika. Chcę X, robię Y, widzę Z. Na przykład, wdrażam NGINX, sprawdzam URL, otrzymuję 200 OK. Jeśli działanie jest długie, przygotuj to wcześniej, aby później pokazać. Najlepiej, aby godzinę przed demo nie było już poważnych awarii, jeśli coś jest delikatne.

5. Wyjaśnij, jak skutecznie rozwiązano problem, jakie trudności pozostały, co jest do zrobienia, jakie ulepszenia są możliwe w przyszłości. Na przykład, obecnie cli, a później będzie pełna automatyzacja w CI.

Każdy prelegent powinien zmieścić się w 5-10 minut. Jeśli Twoje wystąpienie jest z założenia ważne i zajmie więcej czasu, skonsultuj to wcześniej w kanale sre-takeover.

Po części na żywo zawsze odbywa się dyskusja w wątku. To tutaj pojawia się ta potrzebna nam informacja zwrotna na temat naszych zadań.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP
Na koniec przeprowadza się ankietę w celu ustalenia użyteczności odbywających się prezentacji. To już jest informacja zwrotna na temat samego wystąpienia i znaczenia zadania.

Infrastructure as Code: jak rozwiązać problemy za pomocą XP

Długie wnioski i co dalej

Może się wydawać, że ton artykułu jest nieco pesymistyczny. Nic bardziej mylnego. Dwa podstawowe poziomy uzyskiwania informacji zwrotnej, a mianowicie testy i programowanie w parach, działają. Nieco inaczej niż w tradycyjnym programowaniu, ale pozytywny efekt z tego jest.

Testy, w ich obecnym stanie, zapewniają tylko częściowe pokrycie kodu. Wiele funkcji konfiguracji pozostaje nieprzetestowanych. Ich wpływ na codzienną pracę przy pisaniu kodu jest niewielki. Jednak efekt testów integracyjnych jest odczuwalny, to właśnie one pozwalają na bezpieczne przeprowadzanie refaktoryzacji. To duży sukces. Ponadto z przeniesieniem nacisku na rozwój w językach wysokiego poziomu (u nas python, go), problem znika. A do »klejenia« potrzebnych jest niewiele sprawdzeń, wystarcza ogólny test integracyjny.

Praca w parze bardziej zależy od konkretnych ludzi. Istnieje czynnik zadania i nasze umiejętności interpersonalne. Z niektórymi współpraca układa się bardzo dobrze, z innymi gorzej. Korzyści z tego na pewno są. Jasne jest, że nawet przy niewystarczającym przestrzeganiu zasad pracy w parach, sam fakt wspólnego wykonywania zadań pozytywnie wpływa na jakość wyniku. Osobiście w parze pracuje mi się łatwiej i przyjemniej.

Bardziej zaawansowane sposoby wpływania na system operacyjny – planowanie i praca z zadaniami na pewno przynoszą efekty: jakościowa wymiana wiedzy i poprawa jakości procesu tworzenia oprogramowania.

Krótka konkluzja w jednej linii

  • Praktyki XP funkcjonują w IaC, ale z mniejszą efektywnością.
  • Wzmacniaj to, co działa.
  • Twórz własne mechanizmy kompensacyjne i praktyki.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster