вторник, 27 ноября 2018 г.

Установка кластера Kubernetes c помощью SaltStack

Чтобы установить и настроить кластер Kubernetes c помощью SaltStack можно использовать готовую формулу - salt-formula-kubernetes.

1) Скачиваем формулу salt-formula-kubernetes:
cd /srv/formulas
git clone https://github.com/salt-formulas/salt-formula-kubernetes.git
2) Для кластера также потребуется установить etcd. Скачиваем формулу salt-formula-etcd:
cd /srv/formulas
git clone https://github.com/salt-formulas/salt-formula-etcd.git
3) Добавляем скачанные формулы в конфиг salt-мастера - /etc/salt/master:
file_roots:
  base:
    - /srv/salt/base
    - /srv/formulas/salt-formula-etcd
    - /srv/formulas/salt-formula-kubernetes
Примечание: примеры настроек, скриптов и salt-стейтов, используемых в дальнейшем, можно взять из репозитория https://github.com/itrm/salt-for-kube:
git clone https://github.com/itrm/salt-for-kube.git
Содержимое репозитория нужно скопировать в папку /srv.

4) Kubernetes использует TLS для связи между компонентами. TLS-сертификаты создаём с помощью утилит cfssl.
Примеры настроек и скрипт для генерации сертификатов можно взять из папки https://github.com/itrm/salt-for-kube/tree/master/scripts/k8s-certs

4.1 Скачиваем утилиты cfssl и cfssljson:
wget --https-only --timestamping https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

4.2 Создаём файл ca-csr.json по образцу https://github.com/itrm/salt-for-kube/blob/master/scripts/k8s-certs/ca-csr.json

4.3 Создаём ca-сертификат:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca

4.4 Создаём ca-config.json по образцу https://github.com/itrm/salt-for-kube/blob/master/scripts/k8s-certs/ca-config.json

4.5 Создаём файл kubernetes-csr.json по образцу https://github.com/itrm/salt-for-kube/blob/master/scripts/k8s-certs/kubernetes-csr.json

4.6 Создаём остальные сертификаты:
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare kubernetes
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare kubelet-client
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare kube-controller-manager-client
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare kube-scheduler-client
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare kube-proxy-client
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare etcd-server
cfssl gencert   -ca=ca.pem   -ca-key=ca-key.pem   -config=ca-config.json   -profile=kubernetes   kubernetes-csr.json | cfssljson -bare etcd-client
4.7 Копируем сертификаты для kubernetes в папку /srv/salt/base/_certs/kubernetes:
mkdir -p /srv/salt/base/_certs/kubernetes
cp kubernetes-key.pem /srv/salt/base/_certs/kubernetes/kubernetes-server.key
cp kubernetes.pem /srv/salt/base/_certs/kubernetes/kubernetes-server.crt
cp ca.pem /srv/salt/base/_certs/kubernetes/ca-kubernetes.crt
cp ca-key.pem /srv/salt/base/_certs/kubernetes/ca-kubernetes.key
cp kubelet-client-key.pem /srv/salt/base/_certs/kubernetes/kubelet-client.key
cp kubelet-client.pem /srv/salt/base/_certs/kubernetes/kubelet-client.crt
cp kube-controller-manager-client.pem /srv/salt/base/_certs/kubernetes/kube-controller-manager-client.crt
cp kube-controller-manager-client-key.pem /srv/salt/base/_certs/kubernetes/kube-controller-manager-client.key
cp kube-scheduler-client-key.pem /srv/salt/base/_certs/kubernetes/kube-scheduler-client.key
cp kube-scheduler-client.pem /srv/salt/base/_certs/kubernetes/kube-scheduler-client.crt
cp kube-proxy-client.pem /srv/salt/base/_certs/kubernetes/kube-proxy-client.crt
cp kube-proxy-client-key.pem /srv/salt/base/_certs/kubernetes/kube-proxy-client.key
4.8 Копируем сертификаты для etcd в папку /srv/salt/base/_certs/etcd:
mkdir /srv/salt/base/_certs/etcd
cp ca.pem /srv/salt/base/_certs/etcd/ca.pem
cp etcd-server.pem /srv/salt/base/_certs/etcd/etcd-server.crt
cp etcd-server-key.pem /srv/salt/base/_certs/etcd/etcd-server.key
cp etcd-client.pem /srv/salt/base/_certs/etcd/etcd-client.crt
cp etcd-client-key.pem /srv/salt/base/_certs/etcd/etcd-client.key
Шаги 4.6 - 4.8 можно также выполнить с помощью скрипта https://github.com/itrm/salt-for-kube/blob/master/scripts/k8s-certs/generate_ssl.sh

5) Копируем сертификаты kubernetes на все ноды.
Запускаем стейт:
salt -C 'G@roles:kube-master' state.sls kube-ssl
salt -C 'G@roles:kube-node' state.sls kube-ssl
6) Копируем сертификаты etcd на мастер ноды.
Запускаем стейт:
salt -C 'G@roles:kube-master' state.sls etcd-ssl
7) Затем нужно создать pillar файлы соответствующие вашему kubernetes кластеру. Для мастер-нод и для рабочих нод создаём разные файлы.

7.1 pillar-файл для мастер-нод /srv/pillar/kube-master.sls:
https://github.com/itrm/salt-for-kube/blob/master/pillar/kube-master.sls
7.2 Создаём pillar-файл для рабочих-нод /srv/pillar/kube-node.sls по образцу https://github.com/itrm/salt-for-kube/blob/master/pillar/kube-node.sls

8) Добавляем в файл /srv/pillar/top.sls строки по образцу https://github.com/itrm/salt-for-kube/blob/master/pillar/top.sls

9) Добавляем в файл /srv/salt/base/top.sls строки по образцу https://github.com/itrm/salt-for-kube/blob/master/salt/base/top.sls

10) Устанавливаем docker на все ноды кластера.
Запускаем стейт:
salt -C 'G@roles:kube-master' state.sls docker
salt -C 'G@roles:kube-node' state.sls docker
11) Теперь всё готово для установки kubernetes-кластера
salt -C 'G@roles:kube-master' state.highstate
salt -C 'G@roles:kube-node' state.highstate

пятница, 13 июля 2018 г.

Создание бесплатного TLS сертификата для сайта

С развитием сайта и в случае, если сайт предоставляет сервисы для клиентов, появляется необходимость обеспечения безопасного соединения клиентов с сайтом. Поэтому многие сайты переходят с протокола HTTP на HTTPS.
Для работы HTTPS версии сайта требуются TLS (SSL) сертификаты. Раньше сертификаты нужно было покупать в специализированных центрах сертификации, но c появлением технологии Let’s Encrypt, сертификаты теперь можно получить бесплатно.
Расскажем как можно получить такой сертификат, а также как настроить автоматическое продление TLS сертификата, ведь срок действия letsencrypt-сертификата составляет всего 3 месяца.

Перед началом убеждаемся, что у нас установлены python и git.

Затем нужно настроить web-сервер для того, чтобы он смог обработать запрос на подтверждение подлинности сайта, т.е. что сертификат запросил именно владелец сайта, а не кто-то другой. Для этого в конфигурационный файл сайта в nginx добавляем такой location:
location /.well-known/ {
  root /var/www/html;
}
И перезагружаем nginx:
service nginx reload
А для apache такие настройки:
Alias /.well-known /var/www/html/.well-known
<Directory "/var/www/html">
 Require all granted
 RewriteEngine off
</Directory>
И перезагружаем apache:
service apache2 reload

Далее скачиваем специализированное ПО для получения сертификата, называемое certbot:
cd /root
git clone https://github.com/certbot/certbot
Теперь всё готово, сертификат получаем такой командой:
cd /root/certbot/
./certbot-auto certonly --webroot -w /var/www/html -d <ваш_домен> -d www.<ваш_домен>
Certbot сохранит сделанные сертификаты в папке /etc/letsencrypt/live/<ваш_домен>/

Теперь настраиваем web-сервер для работы сайта по HTTPS. Для nginx настройки могут быть такие:
server {
  listen 443 ssl http2;
  server_name <ваш_домен> www.<ваш_домен>;

  ssl on;
  ssl_certificate /etc/letsencrypt/live/<ваш_домен>/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/<ваш_домен>/privkey.pem;

  error_log /var/log/nginx/<ваш_домен>-errors.log;
  access_log /var/log/nginx/<ваш_домен>-access.log;

  location /.well-known/ {
    root /var/www/html;
  }

  location / {
    root /var/www/<ваш_домен>;
  }
}
Для apache:
<VirtualHost *:443>
 DocumentRoot /var/www/<ваш_домен>
 ServerName <ваш_домен>
 ServerAlias www.<ваш_домен>

 ErrorLog /var/log/apache2/<ваш_домен>-error.log
 CustomLog /var/log/apache2/<ваш_домен>-access.log common

 SSLEngine on
 SSLCertificateFile /etc/letsencrypt/live/<ваш_домен>/fullchain.pem
 SSLCertificateKeyFile /etc/letsencrypt/live/<ваш_домен>/privkey.pem

 Alias /.well-known /var/www/html/.well-known
 <Directory "/var/www/html">
   Require all granted
   RewriteEngine off
 </Directory>

 <Directory "/var/www/<ваш_домен>">
   Require all granted
 </Directory>
</VirtualHost>
Перезагружаем web-сервер для применения настроек.
Чтобы по истечении срока годности сертификата сertbot продлил его автоматически, добавляем в /etc/crontab строки:
# Update all TLS certs
22 13 * * * root /root/certbot/certbot-auto renew -q --no-self-upgrade --post-hook 'service nginx restart'
Или, в случае с apache:
# Update all TLS certs
22 13 * * * root /root/certbot/certbot-auto renew -q --no-self-upgrade --post-hook 'service apache2 restart'

Теперь все готово, можно пользоваться https версией сайта!

понедельник, 25 декабря 2017 г.

Автоматизация администрирования Linux/UNIX серверов (часть 3)

Рассмотрим автоматизацию настройки веб-сервера Nginx при помощи SaltStack.

Для начала создадим каталог mkdir /srv/salt/base/nginx в которой будут размещаться states и другие файлы для конфигурирования удаленных веб-серверов nginx через minion. После создания каталога нам нужно будет создать в нем init.sls файл (states в Salt имеют расширение .sls).

По умолчанию Salt для файлов states (.sls) использует один из самых простых и доступных форматов сериализации - YAML. Но есть поддержка также таких форматов как:
Jinja + YAML, Mako + YAML, Wempy + YAML, Jinja + json, Mako + json и Wempy + json.
Мы в наших примерах будем использовать формат YAML.

Создадим файл:
master:/srv/salt/base/nginx# vim init.sls 
И добавим в него строки:
nginx:
  pkg:
    - installed
  service:
    - running
    - watch:
      - pkg: nginx
      - file: /etc/logrotate.d/nginx
      - file: /etc/nginx/nginx.conf

/etc/nginx/nginx.conf:
  file:
    - managed
    - source: salt://nginx/nginx.conf
    - user: root
    - group: root
    - mode: 644

/etc/logrotate.d/nginx:
  file.managed:
    - source: salt://nginx/logrotate.nginx
    - mode: 644 
Итого у нас в папке такие файлы:
master:/srv/salt/base/nginx# ls
init.sls  logrotate.nginx  nginx.conf
Запустим теперь созданный state на веб-сервер web1:
master:/srv/salt/base/nginx# salt -v web1 state.sls nginx
Executing job with jid 20151226185841988594
-------------------------------------------
web1:
----------
          ID: nginx
    Function: pkg.installed
      Result: True
     Comment: The following packages were installed/updated: nginx
     Started: 18:58:42.351829
    Duration: 8520.115 ms

----------
          ID: /etc/logrotate.d/nginx
    Function: file.managed
      Result: True
     Comment: File /etc/logrotate.d/nginx updated
     Started: 18:58:50.937424
    Duration: 61.313 ms
 ----------
          ID: /etc/nginx/nginx.conf
    Function: file.managed
      Result: True
     Comment: File /etc/nginx/nginx.conf updated
     Started: 18:58:50.998879
    Duration: 5.475 ms
   ----------
          ID: nginx
    Function: service.running
      Result: True
     Comment: Service restarted
     Started: 18:58:51.050241
    Duration: 1072.89 ms
     Changes:   
              ----------
              nginx:
                  True
Summary
------------
Succeeded: 4 (changed=4)
Failed:    0
------------
Total states run:     4
Теперь создадим файл top.sls, с которого SaltStack начнет считывать состояния. Создав в корне папки /srv/salt/base/ файл top.sls:
master:/srv/salt/base # vim top.sls 
base:
  'roles:web':
     - match: grain
     - nginx
Мы сможем применить нашу конфигурацию ко всем узлам у которых grains в файле /etc/salt/minion  прописаны настройки роли web:
grains:
  roles:
    - web
Например, командой:
master:/srv/salt/base # salt -G 'roles:web' state.highstate

понедельник, 25 июля 2016 г.

Автоматизация администрирования Linux/UNIX серверов (часть 2)

Автоматизация настройки служб при помощи Salt master и minions.


Для использования основной конфигурации SaltStack необходимо установить master на центральный сервер и minion на управляемые сервера. Рассмотрим установку на Linux Debian\Ubuntu. Информацию по установке на другие системы можно найти на сайте разработчика docs.saltstack.com.

Для Debian 8 (Jessie) на серверах необходимо импортировать ключ:
# wget -O - https://repo.saltstack.com/apt/debian/8/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add -
После этого добавить в /etc/apt/sources.list строку:
deb http://repo.saltstack.com/apt/debian/8/amd64/latest jessie main
Теперь можно выполнить установку как master, так и minion:
master:/ # apt-get update
master:/ # apt-get install salt-master
либо на управляемом узле:
web1:/ # apt-get update
web1:/ # apt-get install salt-minion
После установки конфигурационные файлы master  и minion лежат в /etc/salt/
/etc/salt/master и /etc/salt/minion соответственно. В файле /etc/salt/master для начала работы достаточно только прописать ИП-адрес сервера master в строке:
interface: 10.10.10.10
А также прописать пути file_roots и pillar_roots, об это чуть поже и перезапустить Salt master:
master:/ # service salt-master restart
На сервере web1, где установлен minion в файле /etc/salt/minion нужно указать адрес хоста master и в разделе grains описать дополнительные сведения о minion, например:
web1:/ # vim /etc/salt/minion
master: salt
ipv6: True
grains:
  roles:
    - web
После перезапуска minion командой:
web1:/ # service salt-minion restart
salt-minion stop/waiting
salt-minion start/running, process 28554
Minion вышлет свой открытый ключ на master, где его необходимо будет принять для дальнейшей работы связки master-minion. Просмотреть список всех ключей на мастере можно командой:
master:/ # salt-key -L
Accepted Keys:
Denied Keys:
Unaccepted Keys:
web1
Rejected Keys:
Принять ключ можно командой:
master:~# salt-key -a web1
The following keys are going to be accepted:
Unaccepted Keys:
web1
Proceed? [n/Y] Y
Key for minion saltminion accepted.
Либо просто командой:
master:~# salt-key -A 
master:/# salt -v web1 cmd.run "hostname -s"
Executing job with jid 20151227190052206904
-------------------------------------------
web1:
    web1
По умолчанию файлы для управления и настройки удаленных узлов (Salt States или дальше просто states) располагаются на master в папке:
master:/# ls /srv/
formulas  pillar  salt
Эти пути можно переопределить в /etc/salt/master. Пример:
file_roots:
  base:
    - /srv/salt/base
    - /srv/formulas/sudoers-formula
    - /srv/formulas/timezone-formula

pillar_roots:
  base:
    - /srv/pillar
В pillar_roots в отличие от file_roots данные доступны только для конкретных узлов, указанных в файле   /srv/pillar/top.sls и недоступны другим управляемым узлам. Это позволяет использовать pillar_roots для настройки пользователей, ключей и тд, требующих повышенной безопасности.

Пример /srv/pillar/top.sls:
base:
  '*':
    - locale
  'roles:dev':
    - match: grain
    - add_dev_users
Cервер на котором в настройках  /etc/salt/minion будет прописан:
grains:
  roles:
    - dev
Сможет воспользоваться стейтами /srv/pillar/locale.sls и /srv/pillar/add_dev_users.sls, так как minion входит в группу dev. Другие узлы смогут воспользоваться только /srv/pillar/locale.sls.

В папке /srv/formulas размещаются уже готовые states которые можно загрузить из репозитария https://github.com/saltstack-formulas. Данные готовые шаблоны states можно использовать для таких задач, как установка пакетов, настройка и запуск служб, создание пользователей или прав доступа, и многое другое.

Загрузить готовые formulas можно несколькими способами:
master:/# cd /srv/formulas
master:/srv/formulas# git clone https://github.com/saltstack-formulas/docker-formula.git
Cloning into 'docker-formula'...
remote: Counting objects: 354, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 354 (delta 0), reused 0 (delta 0), pack-reused 352
Receiving objects: 100% (354/354), 56.98 KiB | 0 bytes/s, done.
Resolving deltas: 100% (172/172), done.
Checking connectivity... done.
После этого в папке docker-formula/docker/ можно увидеть готовые шаблоны для конфигурирования docker-контейнеров:
master:/srv/formulas# ls docker-formula/docker/
codenamemap.yaml  compose-ng.sls  compose.sls  containers.sls  defaults.yaml  files  init.sls  kernel.sls  map.jinja  registry.sls
Второй путь загрузить архив и распаковать:
master:/srv/formulas# wget https://github.com/saltstack-formulas/docker-formula/archive/master.zip
master:/srv/formulas# unzip master.zip
Archive:  master.zip
3e8c4ef0a8f5f7f03b156d199ad3271dc5ac63cd
   creating: docker-formula/
   …
master:/srv/formulas# ls docker-formula/docker/
codenamemap.yaml  compose-ng.sls  compose.sls  containers.sls  defaults.yaml  files  init.sls  kernel.sls  map.jinja  registry.sls
Дальше нужно путь к новой папке нужно прописать в конфигурационный файл мастера:
file_roots:
  base:
    - /srv/salt/base
    - /srv/formulas/sudoers-formula
    - /srv/formulas/timezone-formula
   - /srv/formulas/docker-formula
И перезапустить Salt Master:
master:/srv/formulas# service salt-master restart
После этого новые шаблоны states можно использовать для настройки docker-контейнеров.
В папке /srv/salt/base мы будем создавать собственные states, вы можете использовать другой путь, предварительно прописав его в конфигурации master в разделе:
file_roots:
  base:

пятница, 15 января 2016 г.

Автоматизация администрирования Linux/UNIX серверов (часть 1)

Автоматизация администрирования серверов для Веб при помощи Salt.


SaltStack или коротко Salt  - это Open Source система централизованного управления конфигурацией операционных систем и программ, установленных на серверах. Система достаточно мощная, масштабируемая и позволяет управлять десятками тысяч серверов одновременно и быстро.

Salt система аналогичная Chef и Puppet, но в отличии от них написан на языке Python, который пока является основным языком автоматизации у Linux администраторов и DevOps. Кроме этого, он относительно менее требователен к ресурсам и немного проще в использовании (на наш взгляд). Salt использует на сетевом уровне проверенную библиотеку ZeroMQ, что позволяет обновлять конфигурацию серверов очень быстро.

Две основные функции Salt: управление конфигурацией и удаленное выполнение команд. Работать с Salt можно только из командной строки. Благодаря этому систему просто установить и начать использовать даже на слабом оборудовании.  В любом случае, большинство Linux или UNIX серверов не включают в себя графический интерфейс.

Способы работы с Salt.


Использование Salt без установки Мастера.


Основная архитектура Salt состоит в установке централизованного master и Salt minions (клиентов) на удаленные машины.
Однако, вы можете использовать Salt и для настройки одного единственного сервера. Для этого достаточно установить на сервер только minion. Он содержит широкие функциональные возможности для самостоятельной работы и предназначен для:
  • Использования команды salt-call  в системе без подключения к мастеру
  • Запуска сценариев конфигурирования локально, по аналогии, как это делается с Мастера для удаленных серверов
Конфигурационные файлы при этом расположены также как на Мастере:
minion# ls /srv
formulas pillar salt
Только вместо команды:
master# salt remote-host state.highstate 
Используется команда:
minion# salt-call state.highstate

Выполнение команд Salt через SSH без установки minion.


Вы можете использовать Salt для автоматизации работы с серверами при помощи SSH без установки minion на управляемые узлы. Для этого нужно установить пакет salt-ssh на Мастер сервер Salt. Для Debian и Ubuntu это можно сделать так:
master:~$ sudo add-apt-repository ppa:saltstack/salt
master:~$ sudo apt-get install salt-ssh

master:~$ sudo dpkg -l | grep salt-ssh
ii  salt-ssh    2015.5.3+ds-1trusty1    all     remote manager to administer servers via salt
Далее включить в конфигурационный файл salt-ssh требуемые для управления узлы:
master# cat /etc/salt/roster
web1:
  host: web1 
  user: useradmin
  passwd: admin_pass
  sudo: True
При включенной опции    sudo: True  пользователь на удаленном узле websrv1 должен быть прописан в sudoers c опцией NOPASSWD.
web1:~$ cat /etc/sudoers | grep useradmin
useradmin ALL=(ALL) NOPASSWD: ALL
После этого мы можем выполнять команды на удаленном узле:
root@master:~# salt-ssh -i '*' cmd.run "service nginx status"
Executing job with jid 20151224154255487679
-------------------------------------------
web1:
    * nginx is running

Или:

root@master:~# salt-ssh -v web1 cmd.run "du -sch /var/log"
Executing job with jid 20151218192723210705
-------------------------------------------

web1:
    11G /var/log
    11G total

четверг, 31 декабря 2015 г.

Установка системы управления docker-контейнерами kubernetes


С развитием инфраструктуры docker-контейнеров появляется необходимость управления большим числом docker-контейнеров. Для этой цели служат системы: 
  • Kubernetes развиваемый компанией Google
  • Mesos развиваемый в сообществе Apache 
  • Docker Swarm от создателей Docker.
Компания Google утверждает, что уже более 9-ти лет использует в своей работе контейнеры. Поэтому разрабатываемая ими система Kubernetes является на сегодня стабильной и продвинутой.
С помощью этой статьи вы сможете легко развернуть кластер kubernetes из мастера и двух нод. И легко добавлять node-машины в дальнейшем. Мастер нода имеет API для управления кластером и дирежирует контейнерами. Ноды получают команды от мастера и запускают контейнеры.
Для начала нужно иметь 2 сервера и установить на них Docker.
Мы будем использовать 2 Docker-демона на каждом сервере:
  1. Docker начальной загрузки для запуска flanneld и etcd;
  2. Основной Docker для запуска инфраструктуры Kubernetes и запуска наших контейнеров.
Потребность в двух docker-демонах необходима по той причине, что для объединения всех контейнеров в единую сеть, будет использоваться демон flannel. Он должен запускаться не в основном Docker.

Настройка мастера
Мастер настраивается в 2 этапа:
  1. установка flanneld и etcd
  2. запуск компонент мастера
Для простоты, инициализируем переменную с IP адресом мастера:
export MASTER_IP=<IP адрес мастера, например 1.2.3.4>

Запускаем вспомогательный docker
sudo sh -c 'docker -d -H unix:///var/run/docker-bootstrap.sock \
  -p /var/run/docker-bootstrap.pid \
  --iptables=false \
  --ip-masq=false \
  --bridge=none \
  --graph=/var/lib/docker-bootstrap \
  2> /var/log/docker-bootstrap.log 1> /dev/null &'
Этот docker запускается с опцией --iptables=false, чтобы запускаемые им контейнеры работали только с опцией --net=host.

Запускаем etcd для flannel и API
sudo docker -H unix:///var/run/docker-bootstrap.sock run  \
  --restart=always \
  --net=host 
  -d gcr.io/google_containers/etcd:2.0.12 \
  /usr/local/bin/etcd --addr=127.0.0.1:4001 \
  --bind-addr=0.0.0.0:4001 \
  --data-dir=/var/etcd/data
Прописываем в etcd сеть для flannel 
Сеть не должна пересекаться с уже имеющимися сетями:
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
  --net=host \
  gcr.io/google_containers/etcd:2.0.12 \
  etcdctl set /coreos.com/network/config '{ "Network": "10.1.0.0/16" }'
Устанавливаем flannel на мастер-ноде
Flannel перенастраивает bridge, который настроил Docker. Поэтому надо остановить основной Docker, запустить Flannel и снова запустить Docker.
Останавливаем Docker
sudo service docker stop

Запускаем flannel
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
  -d \
  --restart=always \
  --net=host \
  --privileged \
  -v /dev/net:/dev/net \
  quay.io/coreos/flannel:0.5.0
Эта команда выведет длинный хеш, который будет использоваться в следующей команде. Скопируйте его.

Получаем настройки flannel-сети
sudo docker -H unix:///var/run/docker-bootstrap.sock \
  exec <длинный-хеш> cat /run/flannel/subnet.env
Пример вывода этой команды:
FLANNEL_SUBNET=10.1.10.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false

Добавляем вспомогательный Docker в автозагрузку
Создаём файл /lib/systemd/system/docker-bootstrap.socket с таким содержимым:
[Unit]
Description=Docker Socket for the API
PartOf=docker-bootstrap.service

[Socket]
ListenStream=/var/run/docker-bootstrap.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
И файл /lib/systemd/system/docker-bootstrap.service с таким содержимым:
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker-bootstrap.socket
Requires=docker-bootstrap.socket

[Service]
ExecStart=/usr/bin/docker -d -H unix:///var/run/docker-bootstrap.sock -p /var/run/docker-bootstrap.pid --iptables=false --ip-masq=false --bridge=none --graph=/var/lib/docker-bootstrap
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
В файл /lib/systemd/system/docker.service после After=network.target docker.socket
добавляем docker-bootstrap.service
После этого перечитываем конфиги systemctl
systemctl daemon-reload
systemctl enable docker-bootstrap

Настраиваем основной Docker
В конфиругационном файле или в скрипте запуска (для Ubuntu это /etc/default/docker или /etc/systemd/service/docker.service) нужно добавить:
--bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
Вместо FLANNEL_SUBNET и FLANNEL_MTU нужно прописать параметры из вывода предыдущей команды.
Команда запуска основного докера должа получится примерно такой:
/usr/bin/docker -d -H fd:// --bip="10.1.10.1/24" --mtu=1472

Удаляем существующий Docker bridge
По-умолчанию Docker создаёт bridge и именем docker0. Удалим его
sudo /sbin/ifconfig docker0 down
sudo brctl delbr docker0
Запускаем запускаем основной Docker
sudo service docker start

Запускаем kubernetes мастер
sudo docker run \
  --volume=/:/rootfs:ro \
  --volume=/sys:/sys:ro \
  --volume=/dev:/dev \
  --volume=/var/lib/docker/:/var/lib/docker:rw \
  --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
  --volume=/var/run:/var/run:rw \
  --net=host \
  --privileged=true \
  --pid=host \
  --restart=always \
  -d \
  gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube kubelet --api-servers=http://localhost:8080 --v=2 --address=0.0.0.0 --enable-server --hostname-override=127.0.0.1 --config=/etc/kubernetes/manifests-multi --cluster-dns=10.0.0.10 --cluster-domain=cluster.local
Примечание: --cluster-dns и --cluster-domain нужны для запуска внутреннего DNS сервера. Можно исключить их из команды запуска мастера.

Примечание 2: если при запуске этого контейнера появляется ошибка "System error: The minimum allowed cpu-shares is 1024", то лечится она добавлением параметра --exec-opt native.cgroupdriver=cgroupfs в команду запуска основого Docker.


Запускаем service proxy для kubernetes
Service proxy обеспечивает балансировку нагрузку между группами контейнеров объединёных в Kubernetes services
sudo docker run -d --restart=always \
  --net=host \
  --privileged \
  gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube proxy --master=http://127.0.0.1:8080 --v=2

Теперь у нас есть настроенный кластер из одной  ноды и мастера. Можем протестировать это.
Скачаем утилиту kubectl
wget -O /usr/bin/kubectl http://storage.googleapis.com/kubernetes-release/release/v1.1.3/bin/linux/amd64/kubectl
chmod +x /usr/bin/kubectl 
Запустим команду
kubectl get nodes
Пример вывода этой команды:
NAME        LABELS                             STATUS
127.0.0.1   kubernetes.io/hostname=127.0.0.1   Ready

Добавление ноды в кластер
Добавление ноды во многом повторяет настройку мастера. Процесс состоит из 3 шагов
  1. запуск flanneld
  2. запуск kubernetes
  3. добавление ноды в кластер
Инициализируем 2 переменные:
export MASTER_IP=<IP адрес мастера, например 1.2.3.4>
export NODE_IP=<IP адрес ноды, например 4.3.2.1>

Запуск flanneld
Запускаем Docker  для начальной загрузки
sudo sh -c 'docker -d -H unix:///var/run/docker-bootstrap.sock \
  -p /var/run/docker-bootstrap.pid \
  --iptables=false \
  --ip-masq=false \
  --bridge=none \
  --graph=/var/lib/docker-bootstrap \
  2> /var/log/docker-bootstrap.log 1> /dev/null &'

Останавливаем основной Docker
sudo service docker stop
Запускаем flannel
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
  -d \
  --net=host \
  --privileged \
  -v /dev/net:/dev/net \
  quay.io/coreos/flannel:0.5.0 /opt/bin/flanneld --etcd-endpoints=http://${MASTER_IP}:4001
Эта команда выведет длинный хеш, который будет использоваться в следующей команде. Скопируйте его.

Получаем настройки flannel-сети
sudo docker -H unix:///var/run/docker-bootstrap.sock \
  exec <длинный-хеш> cat /run/flannel/subnet.env
Пример вывода этой команды:
FLANNEL_SUBNET=10.1.90.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false

Настраиваем основной Docker
В конфиругационном файле или в скрипте запуска (для Ubuntu это /etc/default/docker или /etc/systemd/service/docker.service) нужно добавить:
--bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
Вместо FLANNEL_SUBNET и FLANNEL_MTU нужно прописать параметры из вывода предыдущей команды.
Команда запуска основного докера должа получится примерно такой:
/usr/bin/docker -d -H fd:// --bip="10.1.90.1/24" --mtu=1472

Удаляем существующий Docker bridge
sudo /sbin/ifconfig docker0 down
sudo brctl delbr docker0
Запускаем запускаем основной Docker
sudo service docker start
Запуск kubernetes для ноды
Запускаем kubelet
sudo docker run \
    --volume=/:/rootfs:ro \
    --volume=/sys:/sys:ro \
    --volume=/dev:/dev \
    --volume=/var/lib/docker/:/var/lib/docker:rw \
    --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
    --volume=/var/run:/var/run:rw \
    --net=host \
    --privileged=true \
    --pid=host \
    -d \
    gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube kubelet --api-servers=http://localhost:8080 --v=2 --address=0.0.0.0 --enable-server --hostname-override=127.0.0.1 --config=/etc/kubernetes/manifests-multi --cluster-dns=10.0.0.10 --cluster-domain=cluster.local
Примечание: --cluster-dns и --cluster-domain можно исключить из этой команды

Запуск service proxy

sudo docker run -d \
  --net=host \
  --privileged \
  gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube proxy --master=http://${MASTER_IP}:8080 --v=2

Теперь, выполнив на мастере команду kubectl get nodes, мы увидим, что новая нода включена в кластер.
NAME              LABELS                                   STATUS
127.0.0.1         kubernetes.io/hostname=127.0.0.1         Ready
NODE_IP           kubernetes.io/hostname=NODE_IP           Ready

Сделано на основе документации:
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/getting-started-guides/docker-multinode/master.md
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/getting-started-guides/docker-multinode/worker.md

пятница, 2 августа 2013 г.

Мониторинг веб-сервера Nginx c помощью zabbix trapper



   Рассмотрим случай, когда требуется настроить мониторинг сервера по множеству однотипных или динамических метрик, которые отсутствуют в zabbix-агенте.
   В такой ситуации в zabbix-агенте можно создавать ключи для проверки с помощью параметра конфигурации - UserParameter. Для каждого параметра в zabbix_agentd.conf создаётся строка вида:

UserParameter=<key>,<shell command>


   Однако, если значений слишком много, такой способ может оказаться не удобным.
Второй способ заключается в использовании элемента данных zabbix типа trapper (zabbix-ловушки). Принцип очень простой: в zabbix-сервере создаются элементы данных этого типа с произвольным именем ключа. Затем, с помощью утилиты zabbix_sender формируется специальный запрос, в котором указывается ключ ловушки, значение параметра и имя хоста. Если параметров много, то можно сформировать файл в формате zabbix_sender и отправить все значения из файла за одно соединение с сервером.
Строки в файле должны быть оформлены в таком виде:
- <ключ> <значение> (дефис в начале строки обязателен)
или
<имя_хоста> <ключ> <значение>


   Рассмотрим, как использовать эту возможность на примере мониторинга популярного веб-сервера Nginx.  Для этого веб-сервера есть возможнось использовать модуль stub_status, который показывает в цифрах текущую нагрузку на Nginx примерно в таком виде:
Active connections: 26
server accepts    handled     requests
1344375             1344375    3208201
Reading: 0 Writing: 2 Waiting: 24


   Из этих данных мы можем получить, например, такие метрики для мониторинга:
  • nginx_status.active   -  количество всех открытых соединений
  • nginx_status.reading -  количество запросов, у которых nginx читает заголовки запроса
  • nginx_status.writing - количество запросов, у которых в данный момент сервер читает тело запроса, обрабатывает запрос или пишет ответ клиенту
  • nginx_status.waiting  -  количество неактивных(keep-alive) соединений
  • nginx_status.accepts - количество принятых запросов в секунду
  • nginx_status.handled - количество обрабатываемых запросов в секунду
  • nginx_status.requests  - количество запросов в секунду
   Благодаря этим параметрам можно оценить нагрузку на сервер (в течении дня, недели и т.д.) , а также оценить узкие места в его работе (медленный ли канал у сервера, медленные ли каналы у клиентов, медленно ли обрабабатываются запросы и т.д.).


   Скрипт, формирующий файл для zabbix_sender-а и запускающий zabbix_sender, может запускаться zabbix-агентом.
   Для этого в конфигурационном файле агента zabbix_agentd.conf создадим ключ nginx_status:
UserParameter=nginx_status,/home/zabbix/nginx.sh 127.0.0.1


   Содержимое /home/zabbix/nginx.sh примерно такое:
#!/bin/sh

# this script tries to collect nginx data

########################################
# Active connections: 768              #
# server accepts handled requests      #
#  133844 133844 601894                #
# Reading: 63 Writing: 21 Waiting: 684 #
########################################

WGET="/usr/local/bin/wget"
ZBX_STATS_FILE="/var/log/zabbix/ZabbixStats.txt"
ZBX_SENDER="/home/zabbix/bin/zabbix_sender"
ZBX_CONFIG="/home/zabbix/conf/zabbix_agentd.conf"
ZBX_HOSTNAME=`grep "^Hostname" ${ZBX_CONFIG} | cut -f2 -d"="`

NGX_STATS_FILE="/var/log/zabbix/NginxStats.txt"
if [ -z $1 ]; then
   NGX_HOSTNAME="localhost"
else
   NGX_HOSTNAME="${1}"
fi

$WGET -q -O ${NGX_STATS_FILE} -t3 -T5 http://${NGX_HOSTNAME}/nginx-status

if [ $? == 0 ]; then
       cat ${NGX_STATS_FILE} | awk -v myhost=$ZBX_HOSTNAME '/Active connections/ {active = int($NF)}
                      /\W*([0-9]+)\W*([0-9]+)\W*([0-9]+)/ {accepts = int($1); handled = int($2); requests = int($3)}
                      /Reading:/ {reading = int($2); writing = int($4); waiting = int($NF)}
                      END {
                      print myhost, "nginx_status.active", active;
                      print myhost, "nginx_status.reading", reading;
                      print myhost, "nginx_status.writing", writing;
                      print myhost, "nginx_status.waiting", waiting;

                      print myhost, "nginx_status.accepts", accepts;
                      print myhost, "nginx_status.handled", handled;
                      print myhost, "nginx_status.requests", requests;
                      }' > ${ZBX_STATS_FILE}

       ${ZBX_SENDER} -i ${ZBX_STATS_FILE} -c ${ZBX_CONFIG} >/dev/null
       echo 1;
       exit 0
else
       echo "0"
       exit 1
fi
При запросе сервером zabbix ключа nginx_status, скрипт вышлет данные серверу.


   Создаем в zabbix-сервере шаблон - Template App Nginx.
   Создаём в шаблоне элемент данных типа zabbix agent, запускающий скрипт /home/zabbix/nginx.sh (Рис. 1).
Рисунок. 1 Элемент данных, запускающий скрипт /home/zabbix/nginx.sh


   Скрипт в случае успешного получения страницы nginx-status возвращает 1 и 0 - в противном случае. Полезно создать триггер отслеживающий эту ситуацию (Рис. 2).
Рисунок 2. Тригер, отслеживаюший возможность получения статуса с Nginx.


   Далее для каждого параметра создаем элемент данных типа zabbix trapper. На Рис.2  пример для метритки nginx active connections.
Рисунок 3. Создание элемента данных для метрики nginx active connections.


   По аналогии делаем элементы для остальных метрик. Изменяется только название элемента данных (Name) и ключ (Key).


   После объединения графиков в группы получаются графики как на Рис. 4 и Рис. 5.
Рисунок 4. Статус соединений.


Рисунок 5. Нагрузка на сервер.


   Шаблон для мониторинга nginx можно скачать отсюда: http://forum.itrm.ru/t/94/