Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 903 сообщений
Cообщения с меткой

администрирование - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

[Перевод] Это данные, тупица, и почему администраторы баз данных важны как никогда?

Пятница, 29 Июля 2016 г. 13:06 (ссылка)

«Специализированные базы данных, облачные технологии и DevOps не упраздняют роль администраторов, а наоборот – расширяют их функции. Возможно, дело уже не только в таблицах. Но роль администратора БД до сих пор важна, даже если у этой профессии нет названия». Син Галагер


В воображении тех из нас, кто слишком долго работает в сфере информационных технологий, должность «администратор БД» («АБД») порождает довольно-таки специфические образы. Мы представляем кого-то, рвущего на себе волосы из-за проблем с бэкапами (резервными копиями), глюков со снимками файловой системы (снапшотами), вышедших из-под контроля схем, сорванных планов наращивания мощностей в связи с новыми требованиями приложений, вялотекущих запросов и вечных настроек производительности.



Все эти функции админов старой закалки ещё кое-где встречаются, особенно на крупных предприятиях, где гигантские кластеры баз данных по-прежнему правят дата-центрами. Но виртуализация, облачные хранилища данных, микросервисы, DevOps-подход к разработке и запуску приложений и ряд других факторов существенно изменили то, как организации хранят свои данные и управляют ими. Многие традиционные роли администратора БД представляются спорными в том счастливом новом мире, который обещает нам новое поколение баз данных.



NoSQL базы данных не требуют предопределённой схемы данных, а многие репликации встроены по умолчанию. Подготовку новых серверов к работе можно свести к нажатию нескольких переключателей (радио-баттонов) и выставлению галочек на веб-странице. Команды разработчиков просто выбирают точку в облачном хранилище, таком как Amazon Web Services Simple Storage Service (S3), и идут отдыхать (roll). И даже разработчики реляционных БД, таких как Oracle, Microsoft и IBM, подталкивают клиентов к data-as-a-service (DaaS) моделям, кардинально упрощающим доступность и управление оборудованием.



Вы могли подумать, что от этого работа админов БД становится легче. Отнюдь.



«Я думаю, что их задачи [админов БД] стали значительно более сложными, — сказал Крис Лалонд, вице-президент и генеральный менеджер по работе с данными компании Rackspace. — Пока у нас не будет определённо большей автоматизации и технологической оснастки (инструментария), многие новые технологии будут менее зрелыми и их нужно будет холить и лелеять (они требуют больше ухода и кормления). Я хочу сказать, что многие из традиционных задач админов БД всё ещё существуют или должны существовать».



На самом деле все эти великолепные новые технологии подчёркивают профессионала в области данных, будь то администратор БД, архитектор данных, data engineer или даже, в некоторых случаях, data scientist. «Сегодня данные ещё более важны, — сказал Кенни Горман, ветеран БД и соучредитель Eventador (сервис для передачи данных в режиме реального времени). — Компании привыкли полагаться на базы данных, чтобы быть «на подъёме» (to be sound), работать гладко и давать хорошую отчётность. Но сегодня данные и вправду делают вас более конкурентоспособным, и существует больше разных профессий, связанных с данными, и больше технологий, их использующих. И профессионал по БД — в самом центре».



На шаг вперёд...



Нереляционные платформы пообещали снизить нагрузку на администраторов БД. В некотором роде они, действительно, сделали это. Рави Мэюрем, старший вице-президент Couchbase Inc. по продуктам и разработкам, сравнил сдвиг в обязанностях АБД с изменением вождения автомобиля (на протяжении многих лет): давным-давно «для того, чтобы водить машину, вы должны были по существу быть инженером; и когда что-то шло не так, вам нужно было сворачивать с дороги и лезть под капот. Теперь вещи сами заботятся о себе, но я бессилен их исправить».



Такие базы данных как MongoDB и CouchBase, хоть они и не реляционные, поддерживают SQL запросы. У них есть и другие аспекты, вызывающие благосклонность опытных админов БД. Но они также предоставляют «возможности динамического развёртывания, которых нет у реляционных систем, — утверждает Мэюрем. — А добавление новых структур данных обычно требует изменения схемы и влечёт к простою».



Данные как некая Услуга были отданы «на откуп компаний, — считает Мэюрем. — Большинство компаний не держат в облаке критически важную информацию».


В то время как большая реляционная система управления базами данных требует понимания всего аппаратного и программного обеспечения, «следующее поколение АБД будет вовлечено в это намного меньше, — объясняет Мэюрем. — К админу БД будет предъявляться, например, такое требование: всеобъемлюще разбираться в базах данных, но не только», чтобы сосредоточиться на таких задачах как планирование мощностей. АБД будущего должен будет знать, когда следует снабдить бо

https://habrahabr.ru/post/306692/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Повесть «НИИЧОСИ. Дежурная ночь»

Среда, 27 Июля 2016 г. 18:52 (ссылка)





Работа в крупной IT-компании на дежурствах в отделе центра обработки данных накладывает свои отпечатки на образ жизни. В ночных дежурствах родилась данная повесть. Представляю вашему вниманию it-параллель с братьями Стругацкими.



НИИЧОСИ. Дежурная ночь



— Где тебя носит? – голос начальника был не по-детски суров. – Ты мне это брось, почему еще не на месте?

Звонок застал меня при входе в наш НИИЧОСИ (Научно-Исследовательский Институт Частных Объектов Систем Информации) где располагался ЦОД.



— Евгений Палыч, сейчас буду, уже поднимаюсь! — в трубке мобильника укоризненно послышались гудки. М-да, ну ладно, я же не опаздываю еще. Сегодня мое первое боевое дежурство в одиночку, опоздать на него я не мог. Распахнув дверь ногой, я влетел в кабинет. Евгений Павлович, как всегда в своей клетчатой рубахе и потертых джинсах сидел за компом, неотрывно наблюдая за мониторингом, и лишь на секунду перевел взгляд на меня.



— Принимай смену. Пока все в норме, проблем нет. Порядок ты знаешь, но еще раз напомню. Сегодня ночью никаких обновлений не проводить. В двадцать три ноль-ноль просматриваешь все камеры, нет ли каких засидевшихся сотрудников. Если кто сидит — кидай им месседж чтоб в течении пяти минут сохранялись, а сам делай shutdown через три. Все в курсе, пусть не жалуются. Затем делаешь обход всех серваков. Доступ по впн для всех прикрой. Вот список кто может подключаться к нашей сети этой ночью.



Он кинул мне список в скайп. Мой телефон тренькнул и передо мной появился список из двадцати пользователей. На первом месте значился генеральный директор Борис Михайлович Воротин, на втором сам Евгений Павлович Линусов, третьим числился Константин Джобов – старший системный администратор и дальше шел список из семнадцати логинов пользователей. Я конечно не так давно здесь работаю, но эти логины видел впервые.



— ЭЭЭ… а кто это в списке начиная с четвертого и до конца?

— Это список тех, кому разрешен доступ посмертно. Хех, шучу конечно, это старые доступы, там пароли уже раз сто менялись все равно не зайдут и вообще это старый список. Оставляем первые три строчки. Ладно, продолжим. – он мельком взглянул на часы. – Через три минуты начинаешь дежурить и смотри никого не пускай за компы, даже если и проберутся. Охранник проходит по периметру каждый час, он в курсе, стучаться к тебе не будет. Уборщиц гоняй – вчера уже и так одна как-то выдрала два патч-корда из стойки, хотя провода висят на уровне лиц. А я значится, пошел. С наступающим!



Да, мое первое соло-дежурство выпало на Новогоднюю ночь.



Палыч оделся и вышел из офиса, я проследил по камерам, что он точно свалил. Заварил кофейку покрепче. Ночь обещалась быть интересной и спокойной. Не успел я сделать и глоток, в помещение ввалилась компания сисадминов.



Трое парней из соседнего кабинета. У них там видимо, что-то типа дресс-кода – все с бородой. Один в куртке на голое тело. На шее висит планка трофейной оперативы на сто двадцать восемь метров. Руки увешаны фенечками из витухи. В руках он держал бубен, и, судя по его виду, только что совершал обряд воскрешения сервака. Это Костян, он здесь дольше всех работает. Кто-то говорит, что даже дольше генерального, кто-то вообще, что ЦОД образовался вокруг него.



Двое других одеты по приличнее – сегодня даже в парадных кофтах пришли. Так как Новый год — то с оленями. Это Потап и Кирилл. Спецы по никсам и цискам (интересно или цыскам), ярые сторонники автоматизации всех возможных действий на всех устройствах.



— О, Сань привет. Ты чтоль сегодня за смотрящего? Эх, что-то Палыч зверствует. Парни может, подменим его по первости то? Что молодёжь сидеть тут будет? Пусть идет, празднует. – Потап с сожалением глядел на меня.

— И правда Александр иди домой, мы подежурим, а то что у тебя праздник не праздник, а я сейчас быром скрипт запилю чтобы Палычу смски от тебя прилетали с отчетом. – Кирилл с готовностью бросился к первому попавшемуся компу и уже начал подрубаться к какой-то железяке.



— Да ладно парни, мне еще надо закончить конфиг nginx-а править и стартануть его на тридцатом, чтобы в этом году план успеть выполнить.



У меня и правда были запланированы дела на эту ночь, хотя конечно в дежурстве вообще могло на это времени не хватить.



— Ну раз надо, так давай, удачи, я сейчас в серверную за, хм… за термопастой сбегаю и пойдем. – это Костя уже к своим обращался.



Да, конечно, за пастой. Все знают, что они под кондеями в серверной пивце охлаждают.



— Ты если что, звони. Или пиши. Хоть на мейл, хоть в ватсап, хоть в вибер, хоть в джаббер, хоть в аську, хоть куда – ты же знаешь, что мы всегда на связи! – сказал с улыбкой Костян и демонстративно вырубил свой телефон.



Вся троица весело вывалилась их офиса. Наступила тишина, только слышно было, как шумят не выключенные системники сотрудников и посвистывают лампы освещения офиса. Я врубил браузер, отписался в нашем чате: «Дежурство принял». Только запустил putty дабы проверить серваки, в офис заглянул Антон Шентер по прозвищу – Мозг. Он был моим коллегой по отделу, а по должности – ведущий специалист. Он прошел большой путь до этой должности, начиная с простого техника. Так что опыта у него хоть отбавляй! Про себя я называл его ходячей википедией — что у него не спроси из IT все знает, со всем сталкивался в работе. Сегодня он был одет в строгий серый костюм, сразу было понятно, что после работы прямиком на праздник.



— Привет Саш! Дежуришь сегодня? Заполнил доку передачи дежурства? Как у тебя с написанием скриптов? – завалил меня вопросами Антон.

— Привет. Да – дежурю. Заполнить не успел еще, пришел только. А что скрипты? – спросил я. Осваивать python я начал недавно, и любые вопросы по теме написания кода воспринимались тяжко. Не хотелось казаться неумелым в этой области.

— Ты давай, тренируйся. В нашем деле это ой как пригодится. Ну ка, давай запили мне скриптик очищающий все схемы на базе гео-систем с условием, что система трехуровневая и состоит из пяти модулей. – Антон подкатил ближайший стул и сел на него задом наперед, оседлав как коня. – Только давай пока, на тестовом, а то не хотелось бы провести новогоднюю ночь за поднятием сисадминов из-за стола и баз из бэкапов.



Дальше я в течении полу часа пытался сляпать свое произведение. Никак у меня не хотел скрипт стартовать по нормальному. То invalid syntax, то expected an indented block вылезет, а то вообще комп подвиснет без объяснения причины. Надо отдать должное Антону — держался он хорошо. Один раз только проронил устрашающим шепотом: «Ну куда ты for то пихаешь? While–ом тут нужно…» В общем, бился я с этим скриптом, а Антон не соглашался принимать работу, пока хотя бы половина задания не будет выполнена, и заставлял меня, его переписывать заново и заново. Наконец у меня поучилось что-то похожее на тот код, что может выполниться и не снести все данные без следа повсюду, а только то, что просил Антон. То-то же, — сказал он, – практики тебе не хватает Саша, практики. Ну ладно, побежал я, еще вроде на метро успеваю. А ты смотри, пока с таким умением на боевых серваках скрипты не крути. С наступающим!

У него в кармане звякнул телефон, и он, накинув черное пальто, вышел.



Выдохнув, я быстренько сделал rm –rf на папочке со своим созданным скриптом, чтобы кто-нибудь не нашел. Мельком глянул в мониторинг – там горели парочка красных триггеров и десяток желтых – ничего страшного, это все в рамках нормального. Видать еще разработчики-программисты резвятся, возможно уже немного приняв под вечер. Ничего скоро по плану мы их того… Все системы работали исправно, было время почитать хабр. Но сначала я заполнил документ передачи дежурства, ничего сложного, просто так надо. Быстро пробежался по консолям серваков, проверяя нагрузку. Есть конечно мониторинг, но по правилам зачем то надо было… Вот и все, теперь можно и почитать.



Я успел набрать только «hab» как в офис практически бесшумно вошел сам Борис Михайлович Воротин. Как и всегда наш генеральный был одет в идеально чистый строгий черный костюм. В руках он крутил несколько ключей, в качестве брелока служили два, пробитых по середине на сквозь кольцом, токена со старыми ЭЦП. За ним еле протиснулся в дверь, руководитель отдела разработки Роберт Михайлович Столлов. Потертые брюки и слегка запачканная рубаха с тяжестью сходились на его весьма не малом брюхе.



— Ооо, Аалександр Паавлович, дообрый вечер! – поприветствовал меня, слегка потягивая гласные, Роберт Михайлович. – Как поживаает ваш безумно краасивый аангорский крол (хз, с чего он взял, что у меня кто-то есть. Но все уже привыкли к его неожиданным вопросам, заданным не по делу)? К ваашему сведению проошу не забыть и проследить заа моим скриптом на основной бооевой базе отклонения информаации. Он должен заакончится в районе двух ночи. В процессе выпоолнения необходимо внимательно слеедите за свободным местом на раазделе. А так же может быть заадействован весь swap, если вы не успеете вовремя прибить «леевые процессы» то скрипт скушает всю паамять. Учтите, ээто не просто скрипт, это произвеедение Perl-искусства! И если нужно еему еще места не жадничайте, добаавляйте еще.

Я был обескуражен.



– Но, Роберт Михайлович! Мне запретили, что-либо запускать сегодня ночью! По плану лишь мониторинг работы и никаких обновлений.



— Ну, моой юный паадаван. Сей скрипт выполняяется уже легендарных дваадцать пять дней! Неужто быть ему остаановленным на саамом финише, дрожаащей рукой юного дежурного? Это заадание от самого… — Роберт Михайлович поднял указательный палец, тыкая, куда-то в сторону потолка. – Выполнение его прииведет к тому, что моожно будет полностью оотказаться от vacuum-ов на базах наашего ЦОДа!



Гендир, стоящий рядом, неодобрительно покосился на Столлова. Естественно не давал он никакого задания Роберту, более того откуда то «свыше» пришла в голову эта мысль руководителю ОР. Человек он был хоть и со странностями, но даже из-за своих экспериментов его не собирались увольнять, дело свое он знал.



— За скриптом следить. Категорически строго следить за мониторингом. В случае аварии действовать по плану. – Как всегда коротко и четко поставил задачи мне еще раз лично сам Гендир и так же бесшумно вышел.



— Таак то, молодой чееловек. Как только заакончится, значит, скрипт. Сраазу мне звоните. Буду лооги разгребать. Так как надо в оотчет занести всю великолепность мооей геениальной идеи.



Роберт Михайлович грузно развернулся и пошлепал к выходу. Дверь пискнула, реагируя на его пропуск, и я снова остался один.



В офисе витал легкий аромат парфюма Гендира, смешиваясь с тяжелым запахом перегара от Роберта Михайловича. Дааа, праздновать все начали еще даже утром видимо. Наконец-то меня не должен был никто тревожить. Теперь-то точно все разошлись, я глянул по камерам. Отрубать никого не пришлось. Пока все спокойно, я занялся своим любимым делом. Чтением статей на хабре. Много всего сегодня опубликовали. В середине прочтения одной из таких, зазвонил рабочий телефон. Странно уже почти Новый год это во-первых, во-вторых мы не выполняем услуг техподдержки и в-третьих — так лень что-то делать. Но по правилам я обязан взять трубку, что бы ни случилось.



— НИИЧОСИ, дежурный администратор Александр слушаю – представился я по правилам.



— Аалександр, друг мой. Забыл вас преедупредить. – я узнал голос Роберта Михайловича. — Будьте внимаательны. Скрипт троогает сеть, слеедите за нагрузкой. Иначе…



В телефоне раздались короткие гудки. Руководитель ОР спустился в метро. Он особо не задумывался о других, поэтому в его духе было так заканчивать разговор. Ну хорошо, сеть так сеть. Ну не будет же он ip-шники нигде менять, наверняка просто правила в фаерволе трогает. Я продолжил чтение. Телефон настойчиво тренькнул снова.



— НИИЧОСИ, дежурный администратор Александр слушаю.



На том конце тишина, хотя я почувствовал легкое сопение. Такой ступор порой бывает, когда кто-то ошибается номером и попадает к нам.



— Я слушаю – я терял терпение, меня ждала отличная статья…

— Здравствуйте, это ваш клиент из Норильска, с Новым годом кстати. У меня не получается подключиться к веб интерфейсу вашего облака чтобы произвести вычисления для нашего центра. – чувство было как будто он читает по бумажке, возможно ему оставили инструкцию как и что сделать. – А в вашей техподдержке не отвечают. А мне срочно надо!



Твою мать! Срочно ему! В Новый год! Нахрена?!



— Одну минуту я проверю. – я подрубился к камере расположенной в отделе техподдержки. Так и есть, единственный дежурный спал под своим столом, уткнувшись лицом в системник. На столе стояла незаконченная бутылка Jack Daniel’s. Бедненький, за последние пять часов ни одного звонка, умаялся.



— Расскажите, что именно вы делаете, и как у вас не получается.

— Когда я выходил из дома, то опаздывал на двадцать минут на автобус, поэтому мне пришлось ехать на метро. Затем, когда я добрался до нашего офиса, охранник не хотел мне давать…

— Стоп, стоп. Не так подробно. Давайте сразу к началу проблемы.

— Так вот я сел за стол. Нажал кнопку на процессоре. Он зажужал и все. Черный экран и я не могу подключиться к вашему сайту.



С клавиатуры опустились мои руки уже набиравшие в консоли tail /var/log/ngi… Я еще раз с ненавистью посмотрел в окошко с трансляцией спящего саппорта. Было видно как он, сцуко, причмокивает, и его рука нервно дергается в опасной близости от reset-а его компа.



— Нажмите кнопочку на мониторе сбоку и все заработает.



В трубке послышалось усиленное сопение и кажется даже шевеление извилин (-ы) мозга собеседника.



— А что такое монитор?

— Это тот ящик, на который вы смотрите.

— О, спасибо вам большое. Заработало. Еще раз с Наступающим.



Он положил трубку. Я еще минуту сидел немного в шоке с трубкой, прижатой к уху. Ну и клиенты у нас.

Внезапно система мониторинга окрасилась в яркий красный цвет. Около тысячи красных триггеров взревели о том, что все плохо. Мои короткие волосы на голове начали подниматься дыбом. Но я пригладил их рукой и успокоил себя. Скорее всего, это просто глючит мониторинг, бывало такое. Хватило бы рестарта одной службы, но я решил на всякий случай полностью ребутнуть сервак. Все успокоилось. Так как больше никаких проблем не наблюдалось. Я начал гулять по просторам интернета в поисках интересных it новостей. В коридоре прошел охранник. Его седая голова сквозь мутное стекло стены напоминало приведение. Поэтому среди своих, мы звали его Каспером. Кстати тормозил он, так же как и одноименный антиви… Звонок телефона оторвал меня от размышлений. Да что за ночь то такая. Более двух раз за ночь он еще у меня никогда не звонил. А если и звонил, трубку уже брал второй дежурный.



— И снова здравствуйте — опередил меня собеседник – это снова я, из Норильска. Извините, что снова тревожу, но ваша техподдержка все еще не отвечает, а у меня проблема.



Мельком взглянув на камеру из отдела ТП, я заметил, что парень уже переполз немного под соседний стол, подложил под голову чьи-то сменные туфли и во сне немного покусывает провод от сетевого фильтра.



— Что снова случилось?

— Понимаете, когда заработал ваш сайт, я пошел заварить кофе. Кофейный аппарат был выключен, но по вашему совету я нажал на кнопку сбоку и все заработало. Я положил две ложки сахара и поставил чашку на стол и когда…

— Стоп, давайте-ка сразу к проблеме!

— Так вот и когда я немного выпил кофе, начал вводить данные нашего личного кабинета. И все, дальше ничего не выходит. Я уже пробовал, как вы и советовали, нажимать на кнопку на этом… на мониторе. Но он только гаснет и его приходится включать снова, а проблема не исчезает!

— Что вы вводите и куда?

-Там где написано лодин, ввожу название нашей фирмы. Там где пасворд там наш пароль.

— Ну во-первых «логин», во вторых нужно вводить на латинице. В-третьих у вас не включен капс? Или может просто вы ошиб… Знаете, давайте я удаленно подключусь к вашему компьютеру и сам все сделаю?

— А так можно?

— Если вы не против, то конечно можно.

— Ну давайте…



К счастью на компах наших постоянных клиентов (а это был постоянный, как я посмотрел по записям в админке) была установлена, разработанная нашими программистами, система удаленного подключения. Я быстренько нашел в системе HUHA (help user the hands of assholes) его единственный доступный сейчас комп. И подключился.

— Оооо, моя мышка сама двигается. Я, кажется, вирус поймал на вашем сайте!

— Успокойтесь, это я подключился к вашему компу и все делаю.

— Круто, а так бывает?

— Ну, я же, как то это сделал.



Быстренько введя нужные данные в поля, я нажал войти. И вот открылась главная страничка их личного кабинета на нашем «облаке». Все, дальше вроде ломаться нечему и косячить негде…



— Я все сделал, дальше уж вы сами.

— Спасибо, что бы я без вас делал. – на той стороне положили трубку.

— Ты бы не прожил до такого возраста… — сказал я, в трубку обращаясь уже к гудкам в ней.



Это конечно не наша работа, и я с радостью подумал, что начал свою карьеру здесь, а не сотрудником техподдержки. Кстати. Я посмотрел на трансляцию из кабинета ТП. Окно было черным и посередине красовалась надпись: «Сигнал потерян». Это было странно. Система видеонаблюдение не давала сбоев уже больше года. Я поднялся и пошел на пятый этаж в офис ТП. Еще поднимаясь на нашем прозрачном лифте, я заметил, что весь их кабинет в полной темноте. Не светятся даже как всегда не выключенные мониторы. Я начал догадываться, в чем дело. Подходя к двери их кабинета и чувствуя легкий запах гари, я уже начал доставать телефон и набирать 112 чтобы вызвать скорую, но зайдя в темный кабинет, опустил телефон. Саппорт мирно посапывал в другой части кабинета. Подойдя ближе к его рабочему месту, я заметил слегка перегрызенный провод от сетевого фильтра, запах гари и немного жженого мяса там был сильнее всего.



Подбежав к страдальцу, я понял, что помощь ему не нужна. Удар током только откинул его метров на пять (как???) и волосы на его голове стояли колом. Он пробормотал что-то типа: «…НИИЧОСИ, техподдержка – отстаньте…» после того как я его потыкал пальцем. М-да, двести двадцать не возьмут такое проспиртованное тело. Я перетащил его на диванчик стоящий в углу их кабинета. Сбегал за новым фильтром на смену испорченному. И врубил автоматы, которые отрубило после сонного покуса провода саппортом. Загорелся свет. Несколько компьютеров начали самостоятельно загружаться. Саппорт на диванчике перевернулся на другой бок, и обиженно прикрыл лицо куском ткани от обшивки дивана, которую он только что надорвал руками. Ну и ладно – дальше уже не мое дело и я пошел на свое рабочее место.



За несколько шагов до двери кабинета дежурного я уже слышал, как трезвонит рабочий телефон. Да что за хрень!



Отойти не дают. Подбежав к своему рабочему месту, я заметил на экране ip-телефона уже десять пропущенных с одного номера, и он звонит снова!



— НИИЧОСИ, дежурный администратор Александр слушаю.

— Алло, алло. Наконец то вы взяли трубку, а то я уже подумал, что с вами что-то случилось! Это клиент из Норильска. Такая ситуация. Я уже почти запустил вычисления, но тут позвонила моя жена и когда я взял…

— Давайте! Сразу! К сути! Проблемы! – я уже практически вышел из себя.

— Так вот, когда я взял трубку я случайно задел какой-то провод и все погасло. Я не знаю что делать! Вот какой-то провод, вытащенный, я держу его в руках.

— Этот провод черный? У этого провода два штырька, как например, у провода от микроволновки?

— Да, да. Все верно.

— Тогда вам нужно две скрепки. У вас там есть рядом обычные канцелярские скрепки?

— Сейчас посмотрю… Да, вот лежат!

— Сейчас слушайте внимательно. Берете две скрепки. Разгибаете их до ровного состояния. Затем берете одну скрепку в левую руку, другую в правую. И аккуратно вставляете в отверстия на сетевом фильтре – это там где розетки.

— А это не опасно?

— Стал бы я вам советовать, если бы это было опасно?

— Верно. Ну хорошо. Разогнул. Беру одну, другую. Вставля…



В трубке послышался легкий хлопок. Я повесил трубку. Я не злой человек. Интересно, я могу отсюда вызвать скорую в Норильск?



Десять минут я наслаждался тишиной в кабинете. Затем сходил к кулеру за водичкой. Залез на сервак телефонии, удалил свой последний разговор. А что? Я ничего не говорил. Клиент сам не далекого ума, решил проблему исправить. Становилось скучно. Видосы какие что ли посмо… Что это? Снова мониторинг глючит? Снова вылезло куча красных триггеров. Ничего, перезагружу. Странно зайти по ssh на сервак мониторинга не получилось. Попытка зайти хоть куда не увенчалась успехом. Почтовый клиент напряжно булькнул от пришедших ему сотен писем с уведомлениями о проблемах на серваках. Затрезвонил мой мобильник. Звонил Потап.



— Алло. Саша? Что там происходит? Почему нет доступа снаружи к нашим серверам? У меня перестали приходить ежеминутные уведомления в телеграмм о скорости вращения колеса, в котором бегают мои лабораторные хомяки! Твою жеж! Даже наш сайт не пашет!

— Я не знаю. Только что все было хорошо. Я ничего не запускал и не обновлял! – я посмотрел на часы — 02:00. Тревожная мысль пролетела в моей голове. – Я, кажется, догадываюсь что случилось. Потап, походу это скрипт Роберта Михайловича.



— Вот же толстый хрен! Не работается ему спокойно и не отдыхается. Ладно, начинай первоначальный анализ. Я всех соберу. Скоро будем.



Я лихорадочно записал время начала аварии. Система мониторинга вываливала все больше и больше триггеров, присылая мне электронные письма мегатоннами. Доступа никуда не было – сеть лежала. Через пятнадцать минут моих дерганий прибыла первая подмога. Потап с Кириллом влетели в кабинет.

— Санек ключи от серверной быстро!



Я рванул дверцу тумбочки и выдал им ключи.



— А как же расписаться в журнале… Я же не смогу потом… — крикнул я спинам уже убегавших парней.



Пару минут я пытался еще посидеть, потыркать подключение в надежде, что само пройдет. Плюнул и тоже побежал в серверную. По пути ко мне присоединились еще пара сотрудников из нашего отдела Антон и Миша. Насколько я знаю, новый год они собирались отмечать за городом и с семьей. Хм, почему мне никто не рассказал, что уже изобрели телепорт!



В серверной ковырялся Потап и Кирилл. Была вытащена старая квм, работа кипела. Потап заметил вновь прибывших:



— О, Миха, звони Мозгу пусть приезжает тут капец!



Михаил спешно достал телефон и вышел в коридор. В серверной связи не было. Через пять минут из коридора донесся крик:



— До Мозга не могу дозвониться – он бухает. Звоню Печени! Алло Костян, приезжай, тут у нас…



Голос Михи стало практически не слышно, так как Кирилл ребутнул все полки с дисками. Они взревели кулерами как стадо бизонов.



Через десять минут серверная наполнилась народом. Были тут и админы и программисты – зачем то приехавшие. Народу стало так много как будто это рабочий день и все решили охладиться в серверной разом. Костян, как выяснилось потом, приехал на снегоходе (СНЕГОХОДЕ КАРЛ!!! Вот люди празднуют) и уже ковырялся в свитчах.



— А Столлову то звонили? Что он там навоял!

— Да уже вызвали. Сказал сейчас будет и пока «ничего не троогать, а то вы испоортите всю краасоту отчета»!

— Вот же зараза. Из-за его хрени легла сеть. И похоже скрипт еще работает. Саш, где он его запускал. Я убью эту машину тупо по питанию!

— На третьем юните запускал. По всем базам отклонения информации.



Тут в серверную ворвался Роберт Михайлович.



— Стоойте! Не отключаайте ничего! Сейчаас я проверю, что все заакончилось.



Он растолкал всех своим необъятным брюхом уже попачканными салатом «Оливье» и пробрался к квм подключив ее к нужному серваку.



— Вы что же мил человек, не следили совсем за моей гордостью? – Столлов неожиданно перестал тянуть гласные и заговорил четко. Его брови нахмурились. — Что я вам говорил, следите за скриптом, смотрите, сколько он памяти выкушал! Ему же еще надо! Надо было добавить, расширить. Ему простор нужен. А из-за вашей безответственности поплохело всей системе. Надо то всего лишь вот здесь доба…



Только Роберт Михайлович начал фразу и начал выполнять какие-то действия и тут каааааак… все затихнет. В серверной повисла тишина. Народ молча пытался понять, что случилось. Потап и Кирилл синхронно почесывали затылок. Костян просто рукалицо. Миха и Антон застыли открыв рот, что-то говорив до этого. Все остальные просто стояли молча и смотрели на стойки с серваками, на которых не горели лампочки.



Роберт Михайлович, как ни в чем не бывало начал посвистывать и нажимать кнопки запуска серваков.



— Заамечательно! Просто вееликолепно! Это как раз то, что и требовалось! — он вел себя, так как будто ничего и не случилось, и был доволен собой. – Вот поосмотрите скрипт закончил своое действие. Немного все леегло, это почти так и было заадумано. В общем, я логи слиил все себе. А вы тут раазберитесь дальше. Я поошел писать отчет.



И он неожиданно легко упорхнул из серверной. По помещению пронесся легкий шепот негодования. Народ зашевелился.

Все почему то начали посматривать на меня с сожалением. Из толпы я услышал фразы: «Аааа он дежурный сегодня… ему все разгребать…». Через пять минут серверная практически опустела. Уехали Кирилл с Потапом и остальные. В общем, остались только Костя и я.



— Короче смотри. Мне тут уже делать тоже почти нечего. Запускаешь все потихоньку. Поднимаешь базы. Проверяешь сервисы. Я проверил — доступ снаружи появился. Звони, если что я подмогну. Телефон отключать не буду. – он улыбнулся, запихнул бубен за пояс и ушел.



Я остался совсем один с серверами, половина из которых была еще не запущена. Протыкивая кнопки включения я наткнулся на телефон Кости. Вот блин, интересно он специально это делает? После того как все было запущено, я двинул назад на свое рабочее место запускать все программно. Посмотрел на часы – время половина шестого. На то чтобы все поднять и оформить аварию у меня всего три с половиной часа. Страшно хотелось спать после таких нервов.



Вернувшись к себе, я занялся монотонным трудом, который меня страшно бесил. Вроде бы запуск postgresql не такая страшная штука. Но порой он где-то не хотел стартовать ни в какую. Где-то слейвы не поднимались. Все остальные сервисы работали к счастью исправно. Страшно раздражало, что тупила сеть из-за большого числа создаваемых подключений. Через полчаса такой работы я уже хотел убить всех. Зазвонил рабочий телефон. Странно, но номер мне ужасно знакомый по этой ночи.



— Алло. Это дежурный Александр? – я узнал уже надоевший голос из Норильска. – Вы знаете, мне тут что-то плохо стало и я отрубился. Когда очнулся, оказалось что все работает. Это вы удалено запустили мой компьютер? Спасибо вам большое за помощь. Знаете, иногда в вашей техподдержке отвечают такие грубияны! Но вы всегда поможете. Я вычисления запустил. Немного все тормозит. Может вы зайдете удаленно и посмотрите почему у меня медленно запускается игра на сайте. Я уже ее запустил в десяти вкладках, думаю хоть в одной то она быстрее запустится. И еще знаете, бывает, открываешь одноклассники и…



Я положил трубку. Я выключил телефон. Я убрал телефон в тумбочку. Я закрыл тумбочку на ключ. Я убрал ключ в карман. Это просто не его день.



Прошли еще два часа моих мучений с поднятием баз. Оформление отчета об аварии затянулось еще надолго, необходимо было указать все подробности и время, что, кто и когда делал. Страшно клонило в сон. Кофе уже не помогал. К утру стали собираться очереди сообщений на сервисах рассылки. Срочно пришлось переключаться на эту задачу. Неожиданно провайдер отключил основной интернет канал. Ну да кончено – сегодня же первое января!



Пришлось спешно переключать все на резервный.



Пискнула дверь в кабинет. Пришел Макс — дежурный, который меня сменит. Да уже почти девять утра.



— Как ночь прошла? Слышал, были мелкие косячки? – спросил Макс позевывая. – Вроде и обновлений небыло…

— Столлов положил все серваки своим скриптом. Как так он это сделал, я не понимаю. Я если даже захочу не смогу так.

— Даа, этот может. Ну давай, что там у тебя. Сейчас все починим.

— Принимай дежурство, умник! Вот отчет об аварии.

— И наконец, в общем чате я увидел надпись, которая освобождала меня от дежурства и я мог ехать домой спать:

«Дежурство принял».

Original source: habrahabr.ru.

https://habrahabr.ru/post/306562/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Летнее обновление на Хабре: «Администрирование», вес голоса и немногое другое

Понедельник, 25 Июля 2016 г. 13:47 (ссылка)

1. Поток «Администрирование»





Кадр из сериала «Кремниевая долина»



В середине мая мы анонсировали новый подход к категоризации материалов Хабра на тематические потоки. Первоначальная задумка введения потоков была в том, чтобы разделить технический (или инфраструктурный) контент от нетехнического – вследствие чего всё, что касалось технологий, было определено в поток «Разработка».



После получения первых отзывов и пожеланий, мы услышали мнение относительно выделения потока “Администрирования” — и исполнили, ведь данная тематика действительно заслуживает отдельного и полноценного потока.



Стоит отметить, что в связи с данной реструктуризацией вклад пользователей в потоки был пересчитан соответствующим образом.



33 хаба, которые вошли в поток «Администрирование»:

  • Системное администрирование

  • Сетевые технологии

  • ИТ-инфраструктура

  • Серверное администрирование

  • Беспроводные технологии

  • *nix

  • Настройка Linux

  • Виртуализация

  • Хранение данных

  • Администрирование баз данных

  • PowerShell

  • Хранилища данных

  • Антивирусная защита

  • Серверная оптимизация

  • Стандарты свящи

  • Nginx

  • Облачные вычисления

  • Cisco

  • Резервное копирование

  • DNS

  • Децентрализованные сети

  • Администрирование доменных имен

  • Хостинг

  • Восстановление данных

  • Спам и антиспам

  • DevOps

  • SAN

  • Сжатие данных

  • Fidonet

  • Apache

  • IPv6

  • IPTV

  • Оболочки



2. Вес голоса у владельцев значков





До сегодняшнего дня значки, за исключением участия в ППА, не давали их владельцам никаких ощутимых преимуществ, помимо косметических.



Тем не менее, получить их не просто, а значит, их обладатели изрядно постарались. Вполне разумно предоставить таким пользователям привилегию, ведь именно они понимают, какая тема пользуется спросом, и могут отличить хорошую публикацию от плохой.



Мы решили исправить эту ситуацию и увеличили вес голоса за публикацию пользователям со значками. Это нововведение поможет качественным заметкам быстрее набирать хороший рейтинг и попадать в топ.



Итак, сегодня суперсилой наделяются обладатели следующих 4-х значков:



– «Автор», «Звезда» и «Старожил» — вместо 1-го плюса добавляет сразу 2 (2 248 пользователей);

– «Легенда» – добавляет 3 плюса к рейтингу публикации (58 пользователей).



Увеличенный вес голоса распространяется только на голосования за публикации и не влияет на карму и комментарии. Голосование в минус остаётся без изменений, при минусовании отнимается 1 пункт рейтинга.



3. Статистика публикаций





Эта фича продиктована выбранным нами в данный момент курсом на улучшение окружения для авторов, которые вкладывают своё время и силы в написание статей для ресурса.



Полноценные и «Read & Comment» пользователи смогут найти в подменю таба «Публикации» новый пункт — «Статистика».



Всегда интересно смотреть на результативность публикации, какую отдачу получаешь взамен на вложенные силы и время – сколько публикация собрала просмотров, какой у неё рейтинг, сколько комментариев. Если раньше это можно было сделать только в ленте собственных публикаций в небольшой инфопанели под текстом до ката, то теперь эта статистика доступна на отдельной странице в таблице со списком публикаций.



Также на странице доступен график с количеством просмотров всех публикаций (в том числе неопубликованных черновиков). Для графика данные доступны за последний год.



Просмотры всех публикаций



На данный момент мы ограничились возможностями, уже доступными корпоративным блогам, но функционал полезный и интересный, поэтому в будущем будем его развивать.



4. Удаление черновиков





Ещё одна фича, которую вы давно просили. Функция доступна на странице редактирования черновика. Стоит отметить, что удалению подлежат только те черновики, которые ранее не были опубликованы. Данное ограничение не позволит удалить все ваши опубликованные посты, предварительно переведя их в черновик, в случае взлома аккаунта.






Все вышеупомянутые изменения, кроме потоков, также доступны и на Geektimes.


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306340/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Пособие по Ansible

Понедельник, 11 Июля 2016 г. 13:14 (ссылка)

управление конфигурацией оркестра



Это практическое пособие познакомит вас c Ansible. Вам понадобится виртуальная или реальная машина, которая будет выступать в роли узла для Ansible. Окружение для Vagrant идет в комплекте с этим пособием.



Ansible — это программное решение для удаленного управления конфигурациями. Оно позволяет настраивать удаленные машины. Главное его отличие от других подобных систем в том, что Ansible использует существующую инфраструктуру SSH, в то время как другие (chef, puppet, и пр.) требуют установки специального PKI-окружения.



Пособие покрывает такие темы:




  1. Установка Ansible и Vagrant

  2. Файл инвенторизации

  3. Модули shell, copy, сбор фактов, переменные

  4. Запуск на группу хостов

  5. Плейбуки

  6. Пример: поднимаем кластер, устанавливаем и настраиваем Apache и балансировщик нагрузок HAproxy

  7. Обработка ошибок, откат

  8. Шаблоны конфигурации

  9. Роли



Ansible использует так называемый push mode: конфигурация «проталкивается» (push) с главной машины. Другие CM-системы обычно поступают наоборот – узлы «тянут» (pull) конфигурацию с главной машины.



Этот режим интересен потому что вам не нужно иметь публично доступную главную машину для удаленной настройки узлов; это узлы должны быть доступны (позже мы увидим, что скрытые узлы также могут получать конфигурацию).



Что нужно для Ansible



Необходимы следующие Python-модули




  • python-yaml

  • python-jinja2



На Debian/Ubuntu запустите:



sudo apt-get install python-yaml python-jinja2 python-paramiko python-crypto


У вас также должна быть пара ключей в ~/.ssh.



Установка Ansible



Из исходников



Ветка devel всегда стабильна, так что используем ее. Возможно, вам нужно будет установить git (sudo apt-get install git на Debian/Ubuntu).



git clone git://github.com/ansible/ansible.git
cd ./ansible


Теперь можно загрузить окружение Ansible.



source ./hacking/env-setup


Из deb пакета



sudo apt-get install make fakeroot cdbs python-support
git clone git://github.com/ansible/ansible.git
cd ./ansible
make deb
sudo dpkg -i ../ansible_1.1_all.deb (version may vary)


В этом пособии предполагается, что вы использовали именно этот способ.



Установка Vagrant



Vagrant позволяет с легкостью создавать виртуальные машины и запускать их на VirtualBox. Vagrantfile идет в комплекте с пособием.



Чтобы запустить Vagrant вам нужно установить:





Теперь инициализируйте виртуальную машину с помощью следующей команды. Имейте ввиду, что вам не нужно скачивать какой-либо "box" вручную. Это пособие уже содержит готовый Vagrantfile, он содержит все, что нужно для работы.



vagrant up


и налейте себе кофе (если вы используете vagrant-hostmaster, то вам нужно будет ввести root-пароль). Если что-то пошло не так, загляните в туториал по Vagrant'у.



Добавление SSH-ключей на виртуальной машине



Чтобы продолжить, вам нужно добавить свои ключи в authorized_keys root'а на виртуальной машине. Это не обязательно (Ansible может использовать sudo и авторизацию по паролю), но так будет намного проще.



Ansible идеально подходит для этой задачи, поэтому используем его. Однако, я не буду пока ничего объяснять. Просто доверьтесь мне.



ansible-playbook -c paramiko -i step-00/hosts step-00/setup.yml --ask-pass --sudo


В качестве пароля введите vagrant. Если возникнут ошибки "Connections refused", то проверьте настройки фаервола.



Теперь добавьте свои ключи в ssh-agent (ssh-add).



Inventory



Теперь нам нужно подготовить файл inventory. Место по умолчанию это /etc/ansible/hosts.

Но вы можете настроить Ansible так, чтобы использовался другой путь. Для этого используется переменная окружения (ANSIBLE_HOSTS) или флаг -i.



Мы создали такой файл inventory:



host0.example.org ansible_ssh_host=192.168.33.10 ansible_ssh_user=root
host1.example.org ansible_ssh_host=192.168.33.11 ansible_ssh_user=root
host2.example.org ansible_ssh_host=192.168.33.12 ansible_ssh_user=root


ansible_ssh_host это специальная переменная, которая содержит IP-адрес узла, к которому будет создаваться соединение. В данном случае она не обязательна, если вы используете gem vagrant-hostmaster. Также, вам нужно будет менять IP-адреса если вы устанавливали и настраивали свою виртуальную машину с другими адресами.



ansible_ssh_user это еще одна специальная переменная которая говорит Ansible'у подключаться под указанным аккаунтом (юзером). По умолчанию Ansible использует ваш текущий аккаунт, или другое значение по умолчанию, указанное в ~/.ansible.cfg (remote_user).



Проверка



Теперь когда Ansible установлен, давайте проверим, что все работает:



ansible -m ping all -i step-01/hosts


Здесь Ansible попытается запустить модуль ping (подробнее о модулях позже) на каждом хосте. Вывод должен быть примерно таким:



host0.example.org | success >> {
"changed": false,
"ping": "pong"
}

host1.example.org | success >> {
"changed": false,
"ping": "pong"
}

host2.example.org | success >> {
"changed": false,
"ping": "pong"
}


Отлично! Все три хоста живы и здоровы, и Ansible может общаться с ними.



Общение с узлами



Теперь мы готовы. Давайте поиграем с уже знакомой нам командой из прошлого раздела: ansible. Эта команда – одна из трех команд, которую Ansible использует для взаимодействия с узлами.



Сделаем что-нибудь полезное



В прошлой команде -m ping означал «используй модуль ping». Это один из множества модулей, доступных в Ansible. Модуль ping очень прост, он не требует никаких аргументов. Модули, требующие аргументов, могут получить их через -a. Давайте взглянем на несколько модулей.



Модуль shell



Этот модуль позволяет запускать shell-команды на удаленном узле:



ansible -i step-02/hosts -m shell -a 'uname -a' host0.example.org


Вывод должен быть вроде:



host0.example.org | success | rc=0 >>
Linux host0.example.org 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686 i686 i386 GNU/Linux


Легко!



Модуль copy



Модуль copy позволяет копировать файл из управляющей машины на удаленный узел. Представим, что нам нужно скопировать наш /etc/motd в /tmp узла:



ansible -i step-02/hosts -m copy -a 'src=/etc/motd dest=/tmp/' host0.example.org


Вывод:



host0.example.org | success >> {
"changed": true,
"dest": "/tmp/motd",
"group": "root",
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
"mode": "0644",
"owner": "root",
"size": 0,
"src": "/root/.ansible/tmp/ansible-1362910475.9-246937081757218/motd",
"state": "file"
}


Ansible (точнее, модуль copy, запущенный на узле) ответил кучей полезной информации в формате JSON. Позже мы увидим, как это можно использовать.



У Ansible есть огромный

список модулей, который покрывает практически все, что можно делать в системе. Если вы не нашли подходящего модуля, то написание своего модуля – довольно простая задача (и не обязательно писать его на Python, главное, чтобы он понимал JSON).



Много хостов, одна команда



Все что было выше – замечательно, но нам нужно управлять множеством хостов. Давайте попробуем. Допустим, мы хотим собрать факты про узел и, например, хотим узнать какая версия Ubuntu установлена на узлах. Это довольно легко:



ansible -i step-02/hosts -m shell -a 'grep DISTRIB_RELEASE /etc/lsb-release' all


all означает «все хосты в файле inventory». Вывод будет примерно таким:



host1.example.org | success | rc=0 >>
DISTRIB_RELEASE=12.04

host2.example.org | success | rc=0 >>
DISTRIB_RELEASE=12.04

host0.example.org | success | rc=0 >>
DISTRIB_RELEASE=12.04


Больше фактов



Легко и просто. Однако, если нам нужно больше информации (IP-адреса, размеры ОЗУ, и пр.), такой подход может быстро оказаться неудобным. Решение – использовать модуль setup. Он специализируется на сборе фактов с узлов.



Попробуйте:



ansible -i step-02/hosts -m setup host0.example.org


ответ:



"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.0.60"
],
"ansible_all_ipv6_addresses": [],
"ansible_architecture": "x86_64",
"ansible_bios_date": "01/01/2007",
"ansible_bios_version": "Bochs"
},
---snip---
"ansible_virtualization_role": "guest",
"ansible_virtualization_type": "kvm"
},
"changed": false,
"verbose_override": true


Вывод был сокращен для простоты, но вы можете узнать много интересного из этой информации. Вы также можете фильтровать ключи, если вас интересует что-то конкретное.



Например, вам нужно узнать, сколько памяти доступно на всех хостах. Это легко: запустите ansible -i step-02/hosts -m setup -a 'filter=ansible_memtotal_mb' all:



host2.example.org | success >> {
"ansible_facts": {
"ansible_memtotal_mb": 187
},
"changed": false,
"verbose_override": true
}

host1.example.org | success >> {
"ansible_facts": {
"ansible_memtotal_mb": 187
},
"changed": false,
"verbose_override": true
}

host0.example.org | success >> {
"ansible_facts": {
"ansible_memtotal_mb": 187
},
"changed": false,
"verbose_override": true
}


Заметьте, что узлы ответили не в том порядке, в котором они отвечали выше. Ansible общается с хостами параллельно!



Кстати, при использовании модуля setup можно указывать * в выражении filter=. Как в shell.



Выбор хостов



Мы видели, что all означает «все хосты», но в Ansible есть

куча иных способов выбирать хосты:




  • host0.example.org:host1.example.org будет запущен на host0.example.org и на

    host1.example.org

  • host*.example.org будет запущен на всех хостах, названия которых начинается с 'host' и заканчивается на '.example.org' (тоже как в shell)



Группировка хостов



Хосты в inventory можно группировать. Например, можно создать группу debian, группу web-servers, группу production и так далее.



[debian]
host0.example.org
host1.example.org
host2.example.org


Можно даже сократить:



[debian]
host[0-2].example.org


Если хотите задавать дочерние группы, используйте [groupname:children] и добавьте дочерние группы в него. Например, у нас есть разные дистрибутивы Линукса, их можно организовать следующим образом:



[ubuntu]
host0.example.org

[debian]
host[1-2].example.org

[linux:children]
ubuntu
debian


Установка переменных



Вы можете добавлять переменные для хостов в нескольких местах: в файле inventory, файлах переменных хостов, файлах переменных групп и др.



Обычно я задаю все переменные в файлах переменных групп/хостов (подробнее об этом позже). Однако, зачастую я использую переменные напрямую в файле inventory, например, ansible_ssh_host, которая задает IP-адрес хоста. По умолчанию Ansible резолвит имена хостов при соединении по SSH. Но когда вы инициализируете хост, он, возможно, еще не имеет IP-адреса. ansible_ssh_host будет полезен в таком случае.



При использовании команды ansible-playbook (а не обычной команды ansible), переменные можно задавать с помощью флага --extra-vars (или -e). О команде ansible-playbook мы поговорим в следующем шаге.



ansible_ssh_port, как вы могли догадаться, используется, чтобы задать порт соединения по SSH.



[ubuntu]
host0.example.org ansible_ssh_host=192.168.0.12 ansible_ssh_port=2222


Ansible ищет дополнительные переменные в файлах переменных групп и хостов. Он будет искать эти файлы в директориях group_vars и host_vars, внутри директории, где расположен главный файл inventory.



Ansible будет искать файлы по имени. Например, при использовании упомянутого ранее файле inventory, Ansible будет искать переменные host0.example.org в файлах:




  • group_vars/linux

  • group_vars/ubuntu

  • host_vars/host0.example.org



Если этих файлов не существует – ничего не произойдет, но если они существуют – они будут использованы.



Теперь, когда мы познакомились с модулями, инвентаризацией и переменными, давайте, наконец, узнаем о настоящей мощи Ansible с плейбуками.



Плейбуки Ansible



Концепция плейбуков очень проста: это просто набор команд Ansible (задач, tasks), похожих на те, что мы выполняли с утилитой ansible. Эти задачи направлены на конкретные наборы узлов/групп.



Пример с Apache (a.k.a. "Hello World!" в Ansible)



Продолжаем с допущением, что ваш файл inventory выглядит так (назовем его hosts):



[web]
host1.example.org


и все хосты — это системы на основе Debian.



Заметка: помните, что вы можете (и в нашем упражнении мы делаем это) использовать ansible_ssh_host чтобы задать реальный IP-адрес хоста. Вы также можете изменять inventory и использовать реальный hostname. В любом случае, используйте машину, с которой безопасно экспериментировать. На реальных хостах мы также добавляем ansible_ssh_user=root чтобы избежать потенциальных проблем с разными конфигурациями по умолчанию.



Давайте соберем плейбук, который установит Apache на машины группы web.



- hosts: web
tasks:
- name: Installs apache web server
apt: pkg=apache2 state=installed update_cache=true


Нам всего лишь нужно сказать, что мы хотим сделать, используя правильные модули Ansible. Здесь мы используем модуль apt, который может устанавливать пакеты Debian. Мы также просим этот модуль обновить кэш.



Нам нужно имя для этой задачи. Это не обязательно, но желательно для вашего же удобства.



Ну, в целом было довольно легко! Теперь можно запустить плейбук (назовем его apache.yml):



ansible-playbook -i step-04/hosts -l host1.example.org step-04/apache.yml


Здесь step-04/hosts это файл inventory, -l ограничивает запуск хостом host1.example.org,

а apache.yml это наш плейбук.



При запуске команды будет вывод подобный этому:



PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Installs apache web server] *********************
changed: [host1.example.org]

PLAY RECAP *********************
host1.example.org : ok=2 changed=1 unreachable=0 failed=0


Примечание: возможно, вы заметите проходящую мимо корову, если у вас установлен cowsay :-) Если она вам не нравится, можно отключить ее так: export ANSIBLE_NOCOWS="1".



Давайте проанализируем вывод строчка за строчкой.



PLAY [web] *********************


Ansible говорит нам, что play выполняется в группе web. Play — это набор инструкций Ansible, связанных с хостом. Если бы у нас был другой -host: blah в плейбуке, он бы тоже вывелся (но после того, как первый play завершен).



GATHERING FACTS *********************
ok: [host1.example.org]


Помните, когда мы использовали модуль setup? Перед каждым воспроизведением Ansible запускает его на каждом хосте и собирает факты. Если это не требуется (скажем, потому что вам не нужна никакая информация о хосте) можно добавить gather_facts: no под строкой хоста (на том же уровне, где находится tasks:).



TASK: [Installs apache web server] *********************
changed: [host1.example.org]


Теперь самое главное: наша первая и единственная задача запущена, и, так как там сказано changed, мы знаем, что она изменила что-то на хосте host1.example.org.



PLAY RECAP *********************
host1.example.org : ok=2 changed=1 unreachable=0 failed=0


Наконец, Ansible выводит выжимку того, что произошло: две задачи были выполнены, и одна из них изменила что-то на хосте (это была наша задача apache; модуль setup ничего не меняяет).



Давайте запустим это еще раз и посмотрим, что произойдет:



$ ansible-playbook -i step-04/hosts -l host1.example.org step-04/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Installs apache web server] *********************
ok: [host1.example.org]

PLAY RECAP *********************
host1.example.org : ok=2 changed=0 unreachable=0 failed=0


Теперь changed равен '0'. Это совершенно нормально и является одной из главных особенностей Ansible: плейбук будет делать что-то, только если есть что делать. Это называется идемпотентностью. Это значит что можно запускать плейбук сколько угодно раз, но в итоге мы будем иметь машину в одном и том же состоянии (ну, только если вы не будете безумствовать с модулем shell, но тут Ansible уже не сможет ничего поделать).



Улучшаем набор apache



Мы установили apache, давайте теперь настроим virtualhost.



Улучшение плейбука



Нам нужен лишь один виртуальный хост на сервере, но мы хотим сменить дефолтный на что-то более конкретное. Поэтому нам придется удалить текущий virtualhost, отправить наш virtualhost, активировать его и перезапустить apache.



Давайте создадим директиорию под названием files и добавим нашу конфигурацию для host1.example.org, назовем ее awesome-app:




DocumentRoot /var/www/awesome-app

Options -Indexes

ErrorLog /var/log/apache2/error.log
TransferLog /var/log/apache2/access.log


Теперь небольшое обнуление плейбука и все готово:



- hosts: web
tasks:
- name: Installs apache web server
apt: pkg=apache2 state=installed update_cache=true

- name: Push default virtual host configuration
copy: src=files/awesome-app dest=/etc/apache2/sites-available/ mode=0640

- name: Deactivates the default virtualhost
command: a2dissite default

- name: Deactivates the default ssl virtualhost
command: a2dissite default-ssl

- name: Activates our virtualhost
command: a2ensite awesome-app
notify:
- restart apache

handlers:
- name: restart apache
service: name=apache2 state=restarted


Поехали:



$ ansible-playbook -i step-05/hosts -l host1.example.org step-05/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Installs apache web server] *********************
ok: [host1.example.org]

TASK: [Push default virtual host configuration] *********************
changed: [host1.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host1.example.org]

PLAY RECAP *********************
host1.example.org : ok=7 changed=5 unreachable=0 failed=0


Круто! Ну, если задуматься, мы немного опережаем события. Не нужно ли проверить корректность конфигурации перед тем, как перезапускать apache? Чтобы не нарушать работоспособность сервиса в случае если конфигурация содержит ошибку.



Перезапуск в случае ошибки конфигурации



Мы установили apache, изменили virtualhost и перезапустили сервер. Но что, если мы хотим перезапускать сервер только когда конфигурация корректна?



Откатываемся, если есть проблемы



Ansible содержит классную особенность: он остановит всю обработку, если что-то пошло не так. Мы используем эту особенность чтобы остановить плейбук, когда конфигурация не валидна.



Давайте изменим файл конфигурации виртуального хоста awesome-app и сломаем его:



  
RocumentDoot /var/www/awesome-app

Options -Indexes

ErrorLog /var/log/apache2/error.log
TransferLog /var/log/apache2/access.log


Как я сказал, если задача не может исполниться, обработка останавливается. Так что нужно удостовериться в валидности конфигурации перед перезапуском сервера. Мы также начнем с добавления виртуального хоста до удаления дефолтного виртуального хоста, так что последующий перезапуск (возможно, сделанный напрямую на сервере) не сломает apache.



Нужно было сделать это в самом начале. Так как мы уже запускали этот плейбук, дефолтный виртуальный хост уже деактивирован. Не проблема: этот плейбук можно использовать на других невинных хостах, так что давайте защитим их.



- hosts: web
tasks:
- name: Installs apache web server
apt: pkg=apache2 state=installed update_cache=true

- name: Push future default virtual host configuration
copy: src=files/awesome-app dest=/etc/apache2/sites-available/ mode=0640

- name: Activates our virtualhost
command: a2ensite awesome-app

- name: Check that our config is valid
command: apache2ctl configtest

- name: Deactivates the default virtualhost
command: a2dissite default

- name: Deactivates the default ssl virtualhost
command: a2dissite default-ssl

notify:
- restart apache

handlers:
- name: restart apache
service: name=apache2 state=restarted


Поехали:



$ ansible-playbook -i step-06/hosts -l host1.example.org step-06/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Installs apache web server] *********************
ok: [host1.example.org]

TASK: [Push future default virtual host configuration] *********************
changed: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]

TASK: [Check that our config is valid] *********************
failed: [host1.example.org] => {"changed": true, "cmd": ["apache2ctl", "configtest"], "delta": "0:00:00.045046", "end": "2013-03-08 16:09:32.002063", "rc": 1, "start": "2013-03-08 16:09:31.957017"}
stderr: Syntax error on line 2 of /etc/apache2/sites-enabled/awesome-app:
Invalid command 'RocumentDoot', perhaps misspelled or defined by a module not included in the server configuration
stdout: Action 'configtest' failed.
The Apache error log may have more information.

FATAL: all hosts have already failed -- aborting

PLAY RECAP *********************
host1.example.org : ok=4 changed=2 unreachable=0 failed=1


Как вы заметили, apache2ctl возвращает код ошибки 1. Ansible видит это и останавливает работу. Отлично!



Ммм, хотя нет, не отлично… Наш виртуальный хост все равно был добавлен. При любой последующей попытке перезапуска Apache будет ругаться на конфигурацию и выключаться. Так что нам нужен способ отлавливать ошибки и возвращаться к рабочему состоянию.



Использование условий



Мы установили Apache, добавили виртуальный хост и перезапустили сервер. Но мы хотим вернуться к рабочему состоянию, если что-то пошло не так.



Возврат при проблемах



Здесь нет никакой магии. Прошлая ошибка – не вина Ansible. Это не система резервного копирования, и она не умеет отказывать все к прошлым состояниям. Безопасность плейбуков – ваша ответственность. Ansible просто не знает, как отменить эффект a2ensite awesome-app.



Как было сказано ранее, если задача не может исполниться – обработка останавливается… но мы можем принять ошибку (и нам нужно это делать). Так мы и поступим: продолжим обработку в случае ошибки, но только чтобы вернуть все к рабочему состоянию.



- hosts: web
tasks:
- name: Installs apache web server
apt: pkg=apache2 state=installed update_cache=true

- name: Push future default virtual host configuration
copy: src=files/awesome-app dest=/etc/apache2/sites-available/ mode=0640

- name: Activates our virtualhost
command: a2ensite awesome-app

- name: Check that our config is valid
command: apache2ctl configtest
register: result
ignore_errors: True

- name: Rolling back - Restoring old default virtualhost
command: a2ensite default
when: result|failed

- name: Rolling back - Removing our virtualhost
command: a2dissite awesome-app
when: result|failed

- name: Rolling back - Ending playbook
fail: msg="Configuration file is not valid. Please check that before re-running the playbook."
when: result|failed

- name: Deactivates the default virtualhost
command: a2dissite default

- name: Deactivates the default ssl virtualhost
command: a2dissite default-ssl

notify:
- restart apache

handlers:
- name: restart apache
service: name=apache2 state=restarted


Ключевое слово register записывает вывод команды apache2ctl configtest (exit

status, stdout, stderr, ...), и when: result|failed проверяет, содержит ли переменная

(result) статус failed.



Поехали:



$ ansible-playbook -i step-07/hosts -l host1.example.org step-07/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Installs apache web server] *********************
ok: [host1.example.org]

TASK: [Push future default virtual host configuration] *********************
ok: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]

TASK: [Check that our config is valid] *********************
failed: [host1.example.org] => {"changed": true, "cmd": ["apache2ctl", "configtest"], "delta": "0:00:00.051874", "end": "2013-03-10 10:50:17.714105", "rc": 1, "start": "2013-03-10 10:50:17.662231"}
stderr: Syntax error on line 2 of /etc/apache2/sites-enabled/awesome-app:
Invalid command 'RocumentDoot', perhaps misspelled or defined by a module not included in the server configuration
stdout: Action 'configtest' failed.
The Apache error log may have more information.
...ignoring

TASK: [Rolling back - Restoring old default virtualhost] *********************
changed: [host1.example.org]

TASK: [Rolling back - Removing our virtualhost] *********************
changed: [host1.example.org]

TASK: [Rolling back - Ending playbook] *********************
failed: [host1.example.org] => {"failed": true}
msg: Configuration file is not valid. Please check that before re-running the playbook.

FATAL: all hosts have already failed -- aborting

PLAY RECAP *********************
host1.example.org : ok=7 changed=4 unreachable=0 failed=1


Кажется, все работает как нужно. Давайте попробуем перезапустить apache:



$ ansible -i step-07/hosts -m service -a 'name=apache2 state=restarted' host1.example.org
host1.example.org | success >> {
"changed": true,
"name": "apache2",
"state": "started"
}


Теперь наш Apache защищен от ошибок конфигурации. Помните, переменными можно пользоваться практически везде, так что этот плейбук можно использовать для apache и в других случаях. Напишите один раз и пользуйтесь везде.



Деплоим сайт с помощью Git



Мы установили Apache, добавили виртуальный хост и безопасно перезапустили сервер. Теперь давайте используем модуль git чтобы сделать деплой приложения.



Модуль git



Ну, честно говоря, тут все будет просто, ничего нового. Модуль git это просто еще один модуль. Но давайте попробуем что-нибудь интересное. А позже это пригодится, когда мы будем работать с ansible-pull.



Виртуальный хост задан, но нам нужно внести пару изменений чтобы закончить деплой. Мы деплоим приложение на PHP, так что нужно установить пакет libapache2-mod-php5. Также нужно установить сам git, так как, очевидно, модуль git требует его наличия.



Можно сделать так:



    ...
- name: Installs apache web server
apt: pkg=apache2 state=installed update_cache=true

- name: Installs php5 module
apt: pkg=libapache2-mod-php5 state=installed

- name: Installs git
apt: pkg=git state=installed
...


но в Ansible есть способ лучше. Он может проходить по набору элементов и использовать каждый в определенном действии, вот так:



- hosts: web
tasks:
- name: Updates apt cache
apt: update_cache=true

- name: Installs necessary packages
apt: pkg={{ item }} state=latest
with_items:
- apache2
- libapache2-mod-php5
- git

- name: Push future default virtual host configuration
copy: src=files/awesome-app dest=/etc/apache2/sites-available/ mode=0640

- name: Activates our virtualhost
command: a2ensite awesome-app

- name: Check that our config is valid
command: apache2ctl configtest
register: result
ignore_errors: True

- name: Rolling back - Restoring old default virtualhost
command: a2ensite default
when: result|failed

- name: Rolling back - Removing out virtualhost
command: a2dissite awesome-app
when: result|failed

- name: Rolling back - Ending playbook
fail: msg="Configuration file is not valid. Please check that before re-running the playbook."
when: result|failed

- name: Deploy our awesome application
git: repo=https://github.com/leucos/ansible-tuto-demosite.git dest=/var/www/awesome-app
tags: deploy

- name: Deactivates the default virtualhost
command: a2dissite default

- name: Deactivates the default ssl virtualhost
command: a2dissite default-ssl
notify:
- restart apache

handlers:
- name: restart apache
service: name=apache2 state=restarted


Поехали:



$ ansible-playbook -i step-08/hosts -l host1.example.org step-08/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Updates apt cache] *********************
ok: [host1.example.org]

TASK: [Installs necessary packages] *********************
changed: [host1.example.org] => (item=apache2,libapache2-mod-php5,git)

TASK: [Push future default virtual host configuration] *********************
changed: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]

TASK: [Check that our config is valid] *********************
changed: [host1.example.org]

TASK: [Rolling back - Restoring old default virtualhost] *********************
skipping: [host1.example.org]

TASK: [Rolling back - Removing out virtualhost] *********************
skipping: [host1.example.org]

TASK: [Rolling back - Ending playbook] *********************
skipping: [host1.example.org]

TASK: [Deploy our awesome application] *********************
changed: [host1.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host1.example.org]

PLAY RECAP *********************
host1.example.org : ok=10 changed=8 unreachable=0 failed=0


Теперь можно перейти на http://192.168.33.11 и увидеть котенка и имя сервера.



Строка tags: deploy позволяет запустить определнную порцию плейбука. Допустим, вы запушили новую версию сайта. Вы хотите ускорить процесс и запустить только ту часть, которая ответственна за деплой. Это можно сделать с помощью тегов. Естественно, "deploy" — это просто строка, можно задавать любую. Давайте посмотрим, как это можно использовать:



$ ansible-playbook -i step-08/hosts -l host1.example.org step-08/apache.yml -t deploy

X11 forwarding request failed on channel 0



PLAY [web] *****



GATHERING FACTS *****

ok: [host1.example.org]



TASK: [Deploy our awesome application] *****

changed: [host1.example.org]



PLAY RECAP *****

host1.example.org: ok=2 changed=1 unreachable=0 failed=0



Добавляем еще один веб-сервер



У нас есть один веб-сервер. Мы хотим два.



Обновление inventory



Мы ожидаем наплыва трафика, так что давайте добавим еще один веб-сервер и балансировщик, который мы настроим в следующем шаге. Давайте закончим с inventory:



[web]
host1.example.org ansible_ssh_host=192.168.33.11 ansible_ssh_user=root
host2.example.org ansible_ssh_host=192.168.33.12 ansible_ssh_user=root

[haproxy]
host0.example.org ansible_ssh_host=192.168.33.10 ansible_ssh_user=root


Помните, здесь мы указываем ansible_ssh_host потому что хост имеет не тот IP, что ожидается. Можно добавить эти хосты к себе в /etc/hosts или использовать реальные имена (что вы и будете делать в обычной ситуации).



Сборка второго веб-сервера



Мы не зря напрягались перед этим. Деплой второго сервера очень прост:



$ ansible-playbook -i step-09/hosts step-09/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host2.example.org]
ok: [host1.example.org]

TASK: [Updates apt cache] *********************
ok: [host1.example.org]
ok: [host2.example.org]

TASK: [Installs necessary packages] *********************
ok: [host1.example.org] => (item=apache2,libapache2-mod-php5,git)
changed: [host2.example.org] => (item=apache2,libapache2-mod-php5,git)

TASK: [Push future default virtual host configuration] *********************
ok: [host1.example.org]
changed: [host2.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host2.example.org]
changed: [host1.example.org]

TASK: [Check that our config is valid] *********************
changed: [host2.example.org]
changed: [host1.example.org]

TASK: [Rolling back - Restoring old default virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Removing out virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Ending playbook] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Deploy our awesome application] *********************
ok: [host1.example.org]
changed: [host2.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host2.example.org]
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host1.example.org]
changed: [host2.example.org]

PLAY RECAP *********************
host1.example.org : ok=10 changed=5 unreachable=0 failed=0
host2.example.org : ok=10 changed=8 unreachable=0 failed=0


Все, что нужно, это удалить -l host1.example.org из командной строки. Помните, -l позволяет ограничить хосты для запуска. Теперь ограничения не требуется, и запуск произойдет на всех машинах группы web.



Если бы в группе web были другие машины, и нам нужно было бы запустить плейбук только на некоторых из них, можно было бы использовать, например, такое: -l firsthost:secondhost:....



Теперь у нас есть чудесная ферма веб-серверов, давайте превратим ее в кластер с помощью балансировщика нагрузок.



Шаблоны



Мы будем использовать haproxy в качестве балансировщика. Установка такая же, как с apache. Но конфигурация немного сложнее, потому что нам нужно указать список всех веб-серверов в конфигурации haproxy. Как это сделать?



Шаблон конфигурации HAProxy



Ansible использует Jinja2, систему шаблонов для Python. Внутри Jinja2-шаблона можно использовать любую переменную, которая определена Ansible'ом.



Например, если нужно вывести на экран inventory_name хоста, для которого собран шаблон, то можно просто написать {{ inventory_hostname }} в Jinja2-шаблоне. Или, если нужно вывести IP-адрес первого ethernet-интерфейса (о котором Ansible знает благодаря модулю setup), то можно написать {{ ansible_eth1['ipv4']['address'] }}.



Jinja2 также поддерживает условия, циклы и прочее.



Давайте создадим директорию templates/ с Jinja-шаблоном внутри. Назовем его haproxy.cfg.j2. Расширение .j2 даем прото для удобства, оно не обязательно.



global
daemon
maxconn 256

defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms

listen cluster
bind {{ ansible_eth1['ipv4']['address'] }}:80
mode http
stats enable
balance roundrobin
{% for backend in groups['web'] %}
server {{ hostvars[backend]['ansible_hostname'] }} {{ hostvars[backend]['ansible_eth1']['ipv4']['address'] }} check port 80
{% endfor %}
option httpchk HEAD /index.php HTTP/1.0


Тут есть несколько новых для нас деталей.



Во-первых, {{ ansible_eth1['ipv4']['address'] }} заменится на IP балансировщика нагрузки на eth1.



Дальше у нас есть цикл. Он используется для генерации списка бэкенд-серверов. Каждый шаг цикла соответствует одному хосту из группы [web], и каждый такой хост будет записан в переменную backend. С помощью фактов хоста для каждого из хостов будет сгенерирована строка. Факты всех хостов доступны через переменную hostvars, поэтому достать переменные (например, имя хоста или IP, как в нашем случае) из других хостов очень легко.



Можно было написать список хостов вручную, у нас их всего два. Но мы надеемся, что популярность заставит нас заводить сотни серверов. Так что, при добавлении или изменении серверов нам нужно лишь обновить группу [web].



HAProxy playbook



Самое сложное позади. Написать плейбук для устновки и конфигурации HAproxy очень легко:



- hosts: haproxy
tasks:
- name: Installs haproxy load balancer
apt: pkg=haproxy state=installed update_cache=yes

- name: Pushes configuration
template: src=templates/haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg mode=0640 owner=root group=root
notify:
- restart haproxy

- name: Sets default starting flag to 1
lineinfile: dest=/etc/default/haproxy regexp="^ENABLED" line="ENABLED=1"
notify:
- restart haproxy

handlers:
- name: restart haproxy
service: name=haproxy state=restarted


Выглядит знакомо, правда? Новый модуль тут только один: template. У него такие же аргументы, как у copy. А еще мы ограничили этот плейбук группой haproxy.



А теперь… попробуем. В нашем inventory содержатся только необходимые для кластера хосты, поэтому нам не нужно делать дополнительных ограничений и можно даже запустить оба плейбука. Ну, на самом деле, нам нужно запускать их одновременно, так как haproxy-плейбуку нужны факты из двух веб-серверов. Чуть позже мы узнаем, как избежать этого.



$ ansible-playbook -i step-10/hosts step-10/apache.yml step-10/haproxy.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]
ok: [host2.example.org]

TASK: [Updates apt cache] *********************
ok: [host1.example.org]
ok: [host2.example.org]

TASK: [Installs necessary packages] *********************
ok: [host1.example.org] => (item=apache2,libapache2-mod-php5,git)
ok: [host2.example.org] => (item=apache2,libapache2-mod-php5,git)

TASK: [Push future default virtual host configuration] *********************
ok: [host2.example.org]
ok: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Check that our config is valid] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Rolling back - Restoring old default virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Removing out virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Ending playbook] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Deploy our awesome application] *********************
ok: [host2.example.org]
ok: [host1.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host2.example.org]
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host2.example.org]
changed: [host1.example.org]

PLAY RECAP *********************
host1.example.org : ok=10 changed=5 unreachable=0 failed=0
host2.example.org : ok=10 changed=5 unreachable=0 failed=0

PLAY [haproxy] *********************

GATHERING FACTS *********************
ok: [host0.example.org]

TASK: [Installs haproxy load balancer] *********************
changed: [host0.example.org]

TASK: [Pushes configuration] *********************
changed: [host0.example.org]

TASK: [Sets default starting flag to 1] *********************
changed: [host0.example.org]

NOTIFIED: [restart haproxy] *********************
changed: [host0.example.org]

PLAY RECAP *********************
host0.example.org : ok=5 changed=4 unreachable=0 failed=0


Вроде все хорошо. Зайдите на http://192.168.33.10/ и оцените результат. Кластер задеплоен! Можно даже посмотреть на статистику HAproxy: http://192.168.33.10/haproxy?stats.



Снова переменные



Итак, мы установили балансировщик нагрузки, и он работает нормально. Мы берем переменные из фактов и используем их для генерации конфигурации.



Ansible также поддерживает другие виды переменных. Мы уже видели ansible_ssh_host в файле inventory, но теперь используем переменные, которые заданы в файлах host_vars и group_vars.



Тонкая настройка конфигурации HAProxy



Обычно HAProxy проверяет, живы ли бэкенды. Если бэкенд не откликается, то он удаляется из пула, и HAProxy больше не шлет ему запросы.



У бэкэндов может быть указан вес (от 0 до 256). Чем выше вес, тем больше запросов сервер получит по сравнению с другими серверами. Это полезно, когда узлы отличаются по мощности и нужно направить трафик в соответствии с этим.



Мы используем переменные для настройки этих параметров.



Group-переменные



Интервал проверки haproxy будет задан в файле group_vars. Таким образом, все экземпляры haproxy унаследуют это.



Нужно создать файл group_vars/haproxy внутри директории inventory. Название файла должно совпадать с названием группы, для которой задаются переменные. Если бы мы задавали переменные для группы web, то назвали бы файл group_vars/web.



haproxy_check_interval: 3000
haproxy_stats_socket: /tmp/sock


Название переменной может быть любым. Естественно, рекомендуется давать осмысленные названия, но каких-то специальных правил нет. Можно делать даже комплексные переменные (то есть Python dict) вот так:



haproxy:
check_interval: 3000
stats_socket: /tmp/sock


Это дело вкуса. Такой подход позволяет делать логическую группировку. Мы пока будем использовать простые переменные.



Переменные хоста



С переменными хоста такая же история, но файлы живут в директори host_vars. Давайте зададим вес бэкенда в host_vars/host1.example.com:



haproxy_backend_weight: 100


и для host_vars/host2.example.com:



haproxy_backend_weight: 150


Если бы мы задали haproxy_backend_weight в group_vars/web, то он бы использовался по-умолчанию:

переменные из файла host_vars имеют приоритет перед переменными из group_vars.



Обновляем шаблон



Теперь необходимо обновить шаблон, чтобы он использовал эти переменные.



global
daemon
maxconn 256
{% if haproxy_stats_socket %}
stats socket {{ haproxy_stats_socket }}
{% endif %}

defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms

listen cluster
bind {{ ansible_eth1['ipv4']['address'] }}:80
mode http
stats enable
balance roundrobin
{% for backend in groups['web'] %}
server {{ hostvars[backend]['ansible_hostname'] }} {{ hostvars[backend]['ansible_eth1']['ipv4']['address'] }} check inter {{ haproxy_check_interval }} weight {{ hostvars[backend]['haproxy_backend_weight'] }} port 80
{% endfor %}
option httpchk HEAD /index.php HTTP/1.0


Заметили блок {% if ...? Этот блок будет отработан, если условие верно. Так что, если мы где-нибудь зададим haproxy_stats_socket для балансировщика нагрузки (можно даже добавить --extra-vars="haproxy_stats_sockets=/tmp/sock" при вызове из командной строки), то блок будет добавлен в сгенерированный конфигурационный файл.



Имейте ввиду, что такой метод очень плох с точки зрения безопасности!



Поехали:



ansible-playbook -i step-11/hosts step-11/haproxy.yml


Мы можем, но не обязаны запускать плейбук apache, потому что ничего не изменилось. Но пришлось добавить небольшой трюк. Вот обновленный плейбук haproxy:



- hosts: web
- hosts: haproxy
tasks:
- name: Installs haproxy load balancer
apt: pkg=haproxy state=installed update_cache=yes

- name: Pushes configuration
template: src=templates/haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg mode=0640 owner=root group=root
notify:
- restart haproxy

- name: Sets default starting flag to 1
lineinfile: dest=/etc/default/haproxy regexp="^ENABLED" line="ENABLED=1"
notify:
- restart haproxy

handlers:
- name: restart haproxy
service: name=haproxy state=restarted


Видите? Мы добавили пустой блок для веб-хостов в самом начале. В нем ничего не происходит. Но факт его наличия заставит Ansible собрать факты для группы web. Это необходимо, потому что плейбук haproxy использует факты из этой группы. Если не сделать этого, то Ansible будет ругаться, что ключа ansible_eth1 не существует.



Мигрируем к ролям!



Теперь, когда все плейбуки готовы, давайте все отрефакторим! Мы переделаем все через роли. Роли — это просто еще один способ организации файлов, но у них есть несколько интересных возможностей. Не будем вдаваться в детали, все они описаны в

документации Ansible. Моя любимая фича — это зависимости ролей: роль B может зависеть от другой роли A. Поэтому при применении роли B, автоматически будет применена роль A.



Структура ролей



Роли добавляют немного «магии» в Ansible: они предполагают особую организацию файлов. Роли полагается структурировать определенным образом, хотя вы можете делать это как угодно вам. Тем не менее, если придерживаться соглашений, вам будет гораздо легче создавать модульные плейбуки. Содержать код в порядке будет гораздо легче. Рубисты называют это "convention over configuration".



Структура файлов для ролей такая:



roles
|
|_some_role
|
|_files
| |
| |_file1
| |_...
|
|_templates
| |
| |_template1.j2
| |_...
|
|_tasks
| |
| |_main.yml
| |_some_other_file.yml
| |_ ...
|
|_handlers
| |
| |_main.yml
| |_some_other_file.yml
| |_ ...
|
|_vars
| |
| |_main.yml
| |_some_other_file.yml
| |_ ...
|
|_meta
|
|_main.yml
|_some_other_file.yml
|_ ...


Довольно просто.



Файлы main.yml не обязательны. Но если они присутствуют, то роли добавят их к отработке автоматически. Эти файлы можно использовать для добавления других тасков и хэндлеров.



Обратите внимание на директории vars и meta. vars нужна для случаев, когда есть куча переменных, связанных с ролью. Но мне лично не нравится задавать переменные в ролях и сценариях напрямую. Я считаю, что переменные должны быть частью конфигурации, а сценарии — это структура. Иными словами, я считаю сценарии фабриками, а данные — параметрами для фабрик. Поэтому я предпочитаю видеть «данные» (например, переменные) вне ролей и сценариев. Тогда мне легче шарить роли и не раскрывать слишком много информации о внутренностях серверов. Но это дело личных предпочтений. Ansible предоставляет вам выбор.



В директории meta находятся зависимости, но об этом поговорим в следующий раз. Сценарии лежат в директории roles.



Создаем роль Apache



Теперь у нас достаточно знаний, чтобы создать роль для apache на основе нашего плейбука.



Несколько простых шагов:




  • создать директорию ролей и структуру роли apache

  • вынести хэндлер apache в файл roles/apache/handlers/main.yml

  • перенести конфигурационный файл apache awesome-app в roles/apache/files/

  • создать плейбук для роли



Задаем структуру



Все просто:



mkdir -p step-12/roles/apache/{tasks,handlers,files}


Теперь копируем таски из apache.yml в main.yml. Файл выглядит так:



- name: Updates apt cache
apt: update_cache=true

- name: Installs necessary packages
apt: pkg={{ item }} state=latest
with_items:
- apache2
- libapache2-mod-php5
- git

...

- name: Deactivates the default ssl virtualhost
command: a2dissite default-ssl
notify:
- restart apache


Это не полный текст файла, а просто иллюстрация. Файл в точности повторяет содержание

apache.yml между tasks: и handlers:.



Мы также убрали обращения к директориям files/ и templates/ в тасках. Так как используется стандартная структура ролей, Ansible сам знает, в какие директории смотреть.



Выносим хэндлер



Нужно создать файл step-12/roles/apache/handlers/main.yml:



- name: restart apache
service: name=apache2 state=restarted


Переносим файл конфигурации



Еще проще:



cp step-11/files/awesome-app step-12/roles/apache/files/


Роль apache работает. Но нам нужен способ запустить ее.



Создаем плейбук роли



Давайте создадим плейбук верхнего уровня для связывания хостов и групп хостов с ролями. Назовем файл site.yml, так как нам нужна общая конфигурация сайта. Заодно добавим туда haproxy:



- hosts: web
roles:
- { role: apache }

- hosts: haproxy
roles:
- { role: haproxy }


Совсем не сложно. Теперь давайте создадим роль haproxy:



mkdir -p step-12/roles/haproxy/{tasks,handlers,templates}
cp step-11/templates/haproxy.cfg.j2 step-12/roles/haproxy/templates/


потом извлечем хэндлер и удалим упоминание templates/.



Попробуем?:



ansible-playbook -i step-12/hosts step-12/site.yml


Если все хорошо, то мы увидим "PLAY RECAP":



host0.example.org          : ok=5    changed=2    unreachable=0 failed=0
host1.example.org : ok=10 changed=5 unreachable=0 failed=0
host2.example.org : ok=10 changed=5 unreachable=0 failed=0


Вы наверное заметили, что запуск всех ролей в site.yml занимает много времени. Что если нужно сделать изменения только для веб-серверов? Легко! Используем limit-флаг:



ansible-playbook -i step-12/hosts -l web step-12/site.yml


На этом миграция на роли закончена.



(От переводчика: в оригинальном пособии в будущем появится еще как минимум одна глава. Я добавлю ее в эту публикацию или создам новую).


Original source: habrahabr.ru.

https://habrahabr.ru/post/305400/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Windocks — SQL Server и .NET контейнеры на Windows Server 2012 R2 с поддержкой docker api

Четверг, 30 Июня 2016 г. 18:42 (ссылка)





Здравствуйте, уважаемые читатели хабра. Сегодня мы поговорим о Windocks–продукте компании с одноименным названием, позиционирующем себя как первый движок докер для Windows. Пока клиенты майкрософт ожидают новую версию Windows Server, а именно Windows Server 2016 (на момент написания статьи доступна версия Technical Preview 5) с нативной поддержкой докер-контейнеров, создатели windocks попытались предоставить докер-контейнеры для текущего поколения серверных систем windows.



Итак, что же такое Windocks? Если коротко — это смесь портированной версии существующего демона докер и open source container project от Uhuru Software. Об особенностях Windocks и вызовах, которые стояли перед разработчиками, можно почитать тут.



В рамках данного материала мы попробуем разобраться, чем работа с windocks принципиально отличается от работы с оригинальным демоном для linux, какие у текущей версии windocks ограничения и стоит ли внедрять инструмент в свои процессы разработки и тестирования.



Что доступно сейчас



На момент написания статьи windocks поддерживает следующие ОС:


  • Windows 8/8.1

  • Windows 10

  • Windows Server 2012 / Windows Server 2012 R2

  • Windows Server 2016





В этих ОС можно создавать контейнеры из образов:


  • SQL Server 2016/2014/2012/2008 R2/2008

  • Net 4.5/3.5/2.0

  • Jenkins (агенты, демо по запросу)

  • Office conversion (для конвертации презентаций powerpoint в видео, демо по запросу)

  • Microsoft Dynamics (линейка ERP и CRM решений, демо по запросу)





Развертываем windocks на VPS с Windows Server 2012



Совсем недавно Windocks объявили о релизе community edition, для того чтобы можно было бесплатно ознакомиться с возможностями продукта. Эту версию мы и будем разворачивать. Отправляем запрос через форму на сайте. Ответ приходит мгновенно, и через минуту ссылка уже у нас.



В качестве окружения для развертывания windocks будем использовать VPS с конфигурацией 2x2.6ГГц, 2Гб RAM, 20Гб HDD / Windows Server 2012 R2. Для того, чтобы использовать SQL Server контейнеры на VPS необходимо установить SQL Server. Устанавливаем, а затем ставим и сам windocks. Никаких дополнительных настроек в процессе установки не требуется.



Сгенерируем сертификаты и ключи для хоста и для клиента, чтобы настроить двустороннюю аутентификацию и предоставим их windocks:

server-key.pem -> C:\Users\Administrator\.docker\key.pem
server-cert.pem -> C:\Users\Administrator\.docker\cert.pem
ca.pem -> C:\Users\Administrator\.docker\ca.pem




Теперь запустим windocks (команда запуска выглядит немного иначе, чем для демона докер на линукс):

docker -H tcp://WINDOCKS_IP:2376 -dD --tlsverify=true




В логах запуска видим:

time="2016-06-30T14:32:06.901345300+03:00" level=info msg="Daemon has completed initialization"


Не забываем разрешить входящие подключения на tcp порт 2376 в файрволе для нужных ip-адресов.



Подключаемся с помощью стандартного клиента докер



Как вы наверное догадались по заголовку, Windocks поддерживает docker RESTful api. Это означает, что для работы с ним можно использовать стандартного консольного клиента докер. Однако, windocks на данный момент поддерживает не все команды, а только их часть. В DockerFile также поддерживается ограниченный набор комманд (FROM, ADD, COPY, ADDDB, MOUNTDB). Полный список комманд для сравнения вы можете найти тут.



Подключаемся к windocks абсолютно также, как и к обычному докер хосту (для работы с клиентом рекомендуем создать алиасы команд, в windows это можно сделать, например, с помощью DOSKEY):

docker.exe --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=WINDOCKS_IP:2376 version




В результате получаем что-то вроде:


Client version: 1.7.0
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 0baf609
OS/Arch (client): windows/amd64
Server version: $VERSION
Server API version: 1.19
Go version (server): go1.5.1
Git commit (server): $GITCOMMIT
OS/Arch (server): windows/amd64




Запускаем .NET приложение в windocks



У windocks свой локальный реестр образов, который в community addition по умолчанию содержит 2 образа: dotnet и mssql. Его содержимое можно получить, выполнив (считаем, что мы уже сделали алиас с параметрами для аутентификации с помощью сертификатов):

docker images




Результат:





Итак, нам доступны 2 базовых образа: dotnet-4.5 и mssql-2014. Вместе с Windocks идёт набор сэмплов, демонстрирующих его возможности.



В рамках статьи мы рассмотрим сэмплы testMountDb и testDotnet. Первый монтирует в контейнер, созданный на основе образа mssql-2014, базу для тестового приложения. Второй — использует эту базу в работе в другом контейнере. Скопируем их на клиентскую ОС, чтобы осуществлять работу непосредственно с помощью стандартного клиента.



Соберем контейнер из сэмпла testMountDb и запустим его.

docker build testMountDb




Получаем следующее:


Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM mssql-2014
Step 1 : MOUNTDB customers C:\dcr\mountDbExample\customerdata.mdf
ContainerId = c4d6e4f7bdc9cfc4c8b62b09572b255f43b56716d862b28e291e7af86e08bc3f & ContainerPort = 10001 & ContainerUserName = prison_oo_aqRdapH & ContainerPassword = Pr!5n5A39SvNRo & MSSQLPort = 10001 & MSSQLServerUserName = sa & MSSQLServer
SaPassword = Pr!54q0flmqoM1 & DockerFile output: & Line 2- Mounted DB: customers, C:\ dcr \mountDbExample\customerdata.mdf




Отсюда нам понадобятся MSSQLServerUserName и SaPassword, которые мы будем использовать в web.cfg в строке подключения.

Запустим созданный контейнер:

docker start c4d




Теперь соберем контейнер из сэмпла testDotnet и запустим (всё аналогично):

docker build testDotnet




Результат:


SECURITY WARNING: You are building a Docker image from Windows against a Linux Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
Sending build context to Docker daemon 20.99 kB
Sending build context to Docker daemon
Step 0 : FROM dotnet-4.5
Step 1 : COPY web.config app-root\\runtime\\repo
Step 2 : COPY default.aspx app-root\\runtime\\repo
Step 3 : COPY default.aspx.cs app-root\\runtime\\repo
Step 4 : COPY main.css app-root\\runtime\\repo
Step 5 : COPY windockslogo.png app-root\\runtime\\repo
Step 6 : COPY testrun.bat .
Step 7 : RUN cmd.exe /C .\testrun.bat
ContainerId = 3b8cefeef04d3ac5010fa8e37b04ce42aa207359e4848581222d521839ea7a04 & ContainerPort = 10003 & ContainerUserName = prison_oo_P4yo5gA & ContainerPassword = Pr!5c6g8mVfQq7 & DOTNETPort = 10003 & DockerFile output: PS

docker start 3b8





Открываем в браузере
http://WINDOCKS_IP:10003 
и, если все сделано правильно, видим следующее:





Теперь сохраним образ приложения в реестре windocks, выполнив следующее:

docker commit a29 windocks_dotnet_demo_v1




И выведем обновлённый список образов:

docker images








Теперь образ windocks_dotnet_demo_v1 могут использовать и другие пользователи



Выводы



На наш взгляд, несмотря на то, что windocks достаточно ограниченный (в чем его ограничения мы указали в самом начале статьи) инструмент в сравнении с демоном докер для линукс, он неплохо справляется со своими стандартными задачами по предоставлению SQL Server и .NET контейнеров. Также его можно вполне комфортно использовать для разработки и тестирования приложений на ASP.NET 4.5 / MSSQL в небольших командах, однако для использования в продакшене инструмент ещё слишком молод и ещё может стать неактуальным после релиза Windows Server 2016. А вы как считаете, уважаемые читатели?
Original source: habrahabr.ru.

https://habrahabr.ru/post/304508/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Каждый слепой сам себе админ

Суббота, 25 Июня 2016 г. 19:04 (ссылка)

У меня сложился один интересный, не популярный и деликатный вопрос к сообществу системных администраторов. Насколько я понимаю часть работы системного администратора в коммерческой или государственной организации заключается в подготовке и обслуживании рабочих мест для сотрудников этой организации. А если один или несколько сотрудников незрячие?



К сожалению, опыт показывает, что большинство системных администраторов не имеют не малейшего представления о вспомогательных технологиях доступности. А те, кто хоть что-то знают, как правило, просто не хотят связываться с этой специфичной сферой. В нашей школе администратор просто не пожелал вникать и что-либо делать на машине, где требовалась настройка таких технологий, но свою часть работы он выполнял, поставил ось, дрова и софт. А дальше на ваше усмотрение. В апреле ухитрился упороть именно нашу систему каким-то левым антивирусником, который мирно отправил в карантин весь вспомогательный софт, за что мы его сердечно «поблагодарили».



По закону с этого года учащиеся с ОВЗ (Ограниченные Возможности Здоровья), а именно — слепые, имеют возможность сдавать экзамены по русскому языку, как выпускные, так и вступительные в ВУЗ, с помощью компьютера. Но во всех ВУЗах мне отказали в этом праве, сославшись, после консультации со своими техническими специалистами, на невозможность создать соответствующие условия. Мне предложили принести свой ноутбук и написать на нём. Ещё более грустно выглядит ситуация, когда настроены сильно ограниченные учётные записи, а системный администратор отказывается давать доступ к полноценной учётной записи входящей в группу администраторы, мотивируя это некомпетентностью самих пользователей.



В связи со всем выше изложенным, хочется обратиться с вопросом к соответствующим специалистам, который находится в вопроснике под статьёй.




Готовы ли вы помочь незрячим людям с настройкой рабочего места в организации, которую вы обслуживаете?


























































Проголосовало 17 человек. Воздержалось 20 человек.





Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.


Original source: habrahabr.ru.

https://habrahabr.ru/post/304104/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Конструктивная админская лень или как я конфиг автоматизировал

Воскресенье, 12 Июня 2016 г. 22:34 (ссылка)

Здравствуйте!

Окрылён Вашим вниманием к первой моей статье: Исследование коммутатора Dlink после грозы, подумал написать цикл статей под общим названием (см. заголовок), если Вам дорогие коллеги, это интересно буду крайне признателен за комментарии.



Входные данные:

Имеются несколько мультисервисных сетей передачи данных размером в 1 город каждая (далее буду рассматривать один город и возможность масштабирования решения на все существующие и перспективу появления новых). итак структура примерно такая: MC-IC-mIC-HC, где

MC — узел города(магистральная подсистема города);

IC — узел агрегации (магистральная подсистема комплекса зданий);

mIC — ведомый узел агрегации;

HC — горизонтальная подсистема, узел доступа;



Задачи требующие решения:

Создание единой системы маркировки;

Генерация конфигурации на основе единого регламента конфигурация оборудования и данных об узле куда предполагается установка конфигурируемого оборудования;

Мониторинг пула IP адресов с целью выявления оборудования с нарушением регламента конфигурации, оповещение локального админа(системный администратор города в котором обнаружено оборудование с не регламентированными настройками).



Инструментарий:

ФИАС;

PostgreSQL;

Python;



В виду объемности работы хотелось бы узнать нужно ли Вам об этом рассказать.

В случае Вашего интереса буду выкладывать одну статью каждую пятницу. Первая статья цикла «ФИАС для администратора сети» почти готова.



Жду ваших комментариев.




Интересен ли Вам цикл статей на означенную тему?




























Проголосовало 7 человек. Воздержалось 6 человек.





Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.


Original source: habrahabr.ru.

https://habrahabr.ru/post/303128/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<администрирование - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda