Архив автора: ans

Gitlab. Mirroring repositories.

При необходимости переноса проекта из стороннего репозиторияв в Ваш локальный, Gitlab предлагает инструмент Mirroring repositories.

Зеркалирование в Gitlab поддерживает два режима:
Push: зеркалирование проекта из локального Gilbab в удаленный репозиторий.
Pull: зеркалирование проекта из удаленного репозитория в локальный Gilbab.

Рассмотрим функциональность инструмента Mirroring repositories на примере зеркалирования проекта из удаленного Atlassian Bitbucket в локальный Gitlab.

Создаем новый проект, далее переходим в настройки этого проекта и добавляем уделенный репозиторий:

Projects > Setting > Repository > Mirroring repositories

Git repository URL: адрес удаленного репозитория
Mirror direction: в нашем случае это Pull
Authentication method: в нашем случае это аутентификация по паролю, но можно и по SSH-ключу.
Password: сам пароль.
Mirror user: пользователь от которого осуществляется настройка.
Так же стоит активировать функцию Overwrite diverged branches, она позволит перезаписывать проект, если версии веток разошлись между репозиториями.

После настройки первая синхронизация займет некоторое время.

Готово, теперь репозиторий будет обновляться каждые ~30 минут. Так же можно форсировать синхронизацию кнопкой «Update now»

Как это работает согласно официальной документации:

Как только функция Mirroring repositories включена для хранилища, хранилище добавляется в очередь.

Раз в минуту задание Sidekiq cron планирует обновления зеркал репозитория на основе:
— Доступности Sidekiq.
— Количество зеркал репозитория, уже находящихся в очереди, которые должны быть обновлены. Срок выполнения зависит от того, когда зеркало хранилища последний раз обновлялось, и сколько раз оно повторялось.

Зеркала репозитория обновляются, когда Sidekiq становится доступным для их обработки. Если процесс обновления зеркала репозитория:
— Успешно, обновление будет снова поставлено в очередь, по крайней мере, через 30 минут.
— Сбой (например, ветвь отклонена от восходящего направления), попытка будет предпринята позже. Зеркала могут выходить из строя до 14 раз, прежде чем они не будут поставлены в очередь для обновления снова (об этом моменте сы поговорим чуть позже).

Возможные ошибки.

При синхронизации проектов я столкнулся с проблемой наличия недопустимых имен веток в удаленном репозитории.

Репозитории синхронизировались, данные внутри обновлялись, но я получал ошибку «Branch name is invalid».

Как быть, что делать?
Смотрим ветки в нашем локальном репозитории, смотрим ветки в удаленном репозитории в Bitbucket. Оказалось у нас не хватает одной ветки с именем «-readmemd-1572439278772», которая не прошла проверку на доступность имени и не синхронизировалась в наш Gilbab

 ~ git branch -a
...
remotes/origin/------------/-readmemd-1572439278772
...

В нашем случае мы попросили удалить эту ветку, т.к. она была не актуальна.

Первоисточник: https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html
Тикет на ошибку «Branch name is invalid: https://gitlab.com/gitlab-org/gitlab/issues/35804

0

Интеграция GitLab и Jenkins. Развертывание по событию.

Настройка непрерывной интеграции между GitLab и Jenkins. Необходимо запускать job в Jenkins всякий раз, когда в ветке master в GitLab происходят изменения.

Шаг 1. Настройка Webhooks в GitLab.

GitLab > Projects > Settings > Integrations

В нашем случае, настраиваем Webhooks на push и merge события в ветке master.

URL: указываем проект в Jenkins
Push events: указываем необходимую ветки, если пусто, то действия распространяются на все ветки.
Merge request events: активно
SSL verification: активно

Шаг 2. Настройка Build Triggers в проекте в Jenkins

Предварительно необходимо установить плагин GitLab Plugin:
Jenkins > Manage Jenkins > Plugin Manager > Available > install GitLab Plugin

Jenkins > Ваш Проект > Configure > Build Triggers

Необходимо активировать пункт Build when a change is pushed to GitLab. GitLab webhook URL: https://localhost/jenkins/project/TestJenkinsProjekt

Шаг 3. Тестирование интеграции.

Выбираем необходимый Trigger

После имитации триггера стартует job в Jenkins с припиской: Started by GitLab push by Username

Первоисточник: https://docs.gitlab.com/ee/user/project/integrations/webhooks.html

1+

Elasticsearch. Настройка ILM

Статья является вольной интерпретацией оригинальной статьи из документации Elastic.

В Elasticsearch благодаря функционалу управления жизненным циклом индекса (index lifecycle management, сокращенно ILM) стало доступным управлять состоянием индекса, замораживать, сжимать или вовсе удалять его.

В этой статье будет показан простой пример удаления индекса спустя указанный промежуток времени в Elasticsearch v. 7.3.2.

Настроить правила жизненного цикла индекса и применить их к индексу можно двумя способами:
1. По средством Dev Tools в интерфейсе Kibana или curl из консоли терминала, если Kibana не используется в кластере.
2. Либо настроить политику использую интерфейс Kibana во вкладке Management > Index Lifecycle Policies.

Сперва рассмотрим первый вариант и создадим политику с помощью запроса во вкладке Dev Tools.

Настройка через консоль Dev Tools.

Проверяем список уже имеющихся политик:

GET _ilm/policy

По умолчанию будет присутствовать стандартная политика watch-history-ilm-policy:

{
  "watch-history-ilm-policy" : {
    "version" : 1,
    "modified_date" : "2019-07-02T07:58:10.186Z",
    "policy" : {
      "phases" : {
        "delete" : {
          "min_age" : "7d",
          "actions" : {
            "delete" : { }
          }        }      }    }  }}

Создадим собственное правило:

PUT _ilm/policy/filebeat-7.3.2  
{
  "policy": {                       
    "phases": {
      "warm": {                      
        "actions": {
          "rollover": {             
            "max_size": "1GB",
            "max_age": "1h"
          }
        }
      },
      "delete": {
        "min_age": "1h",           
        "actions": {
          "delete": {}              
        }
      }
    }
  }
}

Давайте подробнее рассмотрим наше действие и разберем основные параметры запроса.
PUT _ilm/policy/filebeat-7.3.2 — создаем политику и именем filebeat-7.3.2.
«phases»: «warm» — Определяем фазу в которой окажется индекс. Подробнее про фазы ILM.
«actions»: «rollover» — Определяем действие, которое произойдет с индексом в зависимости от параметров.
«max_size»: «1GB» — Определяем первый параметр для перехода индекса в другую стадию — максимальный размер индекса.
«max_age»: «1h» — Определяем второй параметр — возраст индекса.
«delete»: «min_age»: «1h» — по достижению одного из вышеперечисленных параметров спустя указанное время (1 час) индекс удлалиться.
«actions»: «delete» — Определяем действие для удаления индекса.

Получаем положительный ответ «acknowledged» : true.
Вновь проверяем список политик:

GET _ilm/policy

Видим новое правило filebeat-7.3.2, которое мы создали:

{
  "filebeat-7.3.2" : {
    "version" : 1,   //версия правила, будет расти после каждого изменения. Немного подробнее ниже.
    "modified_date" : "2019-09-23T13:40:33.031Z", //дата изменения
    "policy" : {
      "phases" : {
        "hot" : {
          "min_age" : "0ms",
          "actions" : {
            "rollover" : {
              "max_size" : "1gb",
              "max_age" : "1h"
            }
          }
        },
        "delete" : {
          "min_age" : "1h",
          "actions" : {
            "delete" : { }          }        }      }    }  },
  "watch-history-ilm-policy" : {
    "version" : 1,
    "modified_date" : "2019-07-02T07:58:10.186Z",
    "policy" : {
      "phases" : {
        "delete" : {
          "min_age" : "7d",
          "actions" : {
            "delete" : { }          }        }      }    }  }}

После создания правила, его необходимо применить непосредственно к индексам. Можно применить правила как для одного конкретного индекса (что в целом не имеет смысла), так и для темплейта в целом.

Создание темплейта для индексов :
Внимание, если template с именем filebeat-7.3.2 уже существует, следующее действие его перезапишет

PUT _template/filebeat-7.3.2
{
  "index_patterns": ["filebeat-7.3.2-*"],                 
  "settings": {
    "index.lifecycle.name": "filebeat-7.3.2" 
  }
}

В настройка шаблона мы указали какие индексы подпадают под шаблон «index_patterns»: [«filebeat-7.3.2-*»], т.е. все индексы которые начинаются с filebeat-7.3.2-, какую политику использовать индексам «index.lifecycle.name»: «filebeat-7.3.2».

Важно помнить, что если вы используете filebeat 7 версии, то он создает темплейт в Elasticsearch уже с указанием используемой политики:
Посмотрим стандартный шаблон который создаем сам filebeat

GET _template/filebeat-7.3.2

Мы видим, что он по умолчанию использует политику с именем filebeat-7.3.2, даже если она еще не создана.

{
  "filebeat-7.3.2" : {
    "order" : 1,
    "index_patterns" : [
      "filebeat-7.3.2-*"
    ],
    "settings" : {
      "index" : {
        "lifecycle" : {
          "name" : "filebeat-7.3.2",
          "rollover_alias" : "filebeat-7.3.2"
...

В идеале создать отдельный теплейт для с паттерном индексов filebeat-7.3.2-* параллельно стандартному темплейту filebeat.

Вернемся непосредственно к ILM.
После создания политики и применения ее индексам можем проверить состояние жизненного цикла индекса:
— для всех индексов:

GET filebeat-7.3.2-*/_ilm/explain

Получаем информацию о текущих стадиях всех индексов

{
  "indices" : {
    "filebeat-7.3.2-2019.09.23-000004" : {
      "index" : "filebeat-7.3.2-2019.09.23-000004",
      "managed" : true,
      "policy" : "filebeat-7.3.2",
      "lifecycle_date_millis" : 1569248425250,
      "phase" : "warm",
      "phase_time_millis" : 1569248426531,
      "action" : "complete",
      "action_time_millis" : 1569248485680,
      "step" : "complete",
      "step_time_millis" : 1569248485680,
      "phase_execution" : {
        "policy" : "filebeat-7.3.2",
        "phase_definition" : {
          "min_age" : "0ms",
          "actions" : {
            "shrink" : {
              "number_of_shards" : 1
            }          }        },
        "version" : 2,
        "modified_date_in_millis" : 1569237244490
      }    },
    "filebeat-7.3.2-2019.09.23-000005" : {
      "index" : "filebeat-7.3.2-2019.09.23-000005",
      "managed" : true,
      "policy" : "filebeat-7.3.2",
      "lifecycle_date_millis" : 1569248424138,
      "phase" : "hot",
      "phase_time_millis" : 1569248425501,
      "action" : "rollover",
      "action_time_millis" : 1569248485824,
      "step" : "check-rollover-ready",
      "step_time_millis" : 1569248485824,
      "phase_execution" : {
        "policy" : "filebeat-7.3.2",
        "phase_definition" : {
          "min_age" : "0ms",
          "actions" : {
            "rollover" : {
              "max_size" : "50mb",
              "max_age" : "1h"
            }
          }
        },
        "version" : 2,
        "modified_date_in_millis" : 1569237244490
      }    }  }}

— для конкретного индекса (вместо * указываем полное имя индекса):

GET filebeat-7.3.2-*/_ilm/explain

GET filebeat-7.3.2-2019.09.23-000004/_ilm/explain

Получаем информацию о текущей стадии на которой находится индекс:

{
  "indices" : {
    "filebeat-7.3.2-2019.09.23-000004" : {
      "index" : "filebeat-7.3.2-2019.09.23-000004",
      "managed" : true,
      "policy" : "filebeat-7.3.2",
      "lifecycle_date_millis" : 1569248425250,
      "phase" : "warm",
      "phase_time_millis" : 1569248426531,
      "action" : "complete",
      "action_time_millis" : 1569248485680,
      "step" : "complete",
      "step_time_millis" : 1569248485680,
      "phase_execution" : {
        "policy" : "filebeat-7.3.2",
        "phase_definition" : {
          "min_age" : "0ms",
          "actions" : {
            "shrink" : {
              "number_of_shards" : 1
            }
          }
        },
        "version" : 2,
        "modified_date_in_millis" : 1569237244490
      }    }  }}

Стоит обратить внимание, на параметры:
— «phase» : «hot»\»warm» — текущая стадия индекса
— «action» : «rollover»\»complete» — ожидаемое действие
— «step» : «check-rollover-ready»\»complete» — текущий шаг
— «version» : 2 — используемая версия правила.

Остановимся подробнее на параметре version. Важно помнить, что при изменении политики меняется и ее версия. Однако индексы автоматически не меняют используемую версию политики. Говоря простым языком, после изменения настрое политики, индексы не применят эти изменения и останутся на старой версии.

Создание правила через интерфейс Kibana

Настроить политику можно использую интерфейс Kibana, переходим во вкладку Management > Index Lifecycle Policies и нажимаем кнопку «Create policy«.

Настраиваем необходимые параметры, в нашем случае необходимо включить функцию Delete phase, заполняем остальные поля по примеру:

После заполнения нужных полей можно нажать кнопку «Show JSON«, чтобы увидеть как наш конфиг будет выглядеть в json. Его же можно использовать во вкладке Dev Tools.

Далее создаем template во вкладке Dev Tools, об этом описано выше, не буду повторяться. Да, к сожалению, через интерфейс Kibana нельзя управлять настройками темплейтов.

После настройки политики и шаблонов переходим во вкладку Management > Index Management выбираем нужный нам индекс, в графе Index lifecycle management будут подробности состояния кластера:

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

Отдельно хочу обратить на имена индексов. Мы используем Rollover Action в нашей политике, которая требует, чтобы имя нашего индекса заканчивалось цифрой. В нашем случае мы использовали 000001. Это важно, чтобы Rollover мог увеличивать это число при присвоении имени новому индексу, созданному при пролонгации.
Небольшой пример в картинках, как это работает:
Скормил filebeat несколько файлов с логами превышающих объем в 50 МБ, Elasticsearch создал два индекса.

Спустя несколько часов первые индексы были удалены, а новым были присвоены порядковые номера 000003 и 000004.

Полезная информация и первоисточник:
https://www.elastic.co/guide/en/elasticsearch/reference/current/index-lifecycle-management.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-index-lifecycle-management.html

1+

Elasticsearch. Выпуск сертификата в формате PKCS#12.

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

Операции создания центра сертификации (CA) и\или сертификатов (certificates) выполняются утилитой elasticsearch-certutil:

# cd /usr/share/elasticsearch
# bin /elasticsearch-certutil

Подробнее об утилите elasticsearch-certutil

Выпуск сертификаты в формате PKCS#12

Первым шагом создадим центр сертификации:

# cd /usr/share/elasticsearch
# bin /elasticsearch-certutil ca

Называем СА как Вам удобно, например elastic-stack-ca.p12, это имя нам потребуется на следующем шаге (утилита предложит наименование по умолчанию).
Если есть необходимость создать СА без пароля то указываем параметр -pass «», команда выглядит следующим образом:

# cd /usr/share/elasticsearch
# bin /elasticsearch-certutil ca -pass ""  

Вторым шагом выпускаем сертификат (тут так же можно оставить пароль пустым использую параметр -pass «»):

# cd /usr/share/elasticsearch
# bin /elasticsearch-certutil cert --ca elastic-stack-ca.p12      //ссылаемся на созданный ранее СА

Называем СА как Вам удобно, например elastic-cert.p12

Если вы защитили сертификат узла с помощью пароля, добавьте пароль в хранилище ключей Elasticsearch:

# cd /usr/share/elasticsearch
# bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
# bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password

Теперь созданные файлы копируем в каталог настроек Elasticsearch, в моем случае это /etc/elasticsearch :

-Des.path.conf=/etc/elasticsearch

Иначе мы получим ошибку безопасности JAVA, пример ошибки:
Caused by: java.security.AccessControlException: access denied («java.io.FilePermission» «/usr/share/elasticsearch/config/cert/elastic-cert.p12» «read»)

[2019-09-04T20:32:48,044][ERROR][o.e.b.Bootstrap          ] [vsFawpk] Exception
java.lang.IllegalStateException: failed to load plugin class [org.elasticsearch.xpack.core.XPackPlugin]
        at org.elasticsearch.plugins.PluginsService.loadPlugin(PluginsService.java:614) ~[elasticsearch-6.8.2.jar:6.8.2]
...
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[?:?]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:?]
        at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:1.8.0_202]
        at org.elasticsearch.plugins.PluginsService.loadPlugin(PluginsService.java:605) ~[elasticsearch-6.8.2.jar:6.8.2]
        ... 15 more
Caused by: org.elasticsearch.ElasticsearchException: failed to initialize a TrustManagerFactory
...
Caused by: java.security.AccessControlException: access denied ("java.io.FilePermission" "/usr/share/elasticsearch/config/cert/elastic-cert.p12" "read")
...

Копируем файлы в /etc/elasticsearch/config/cert/ и выдаем права (иначе шанс словить ошибку JAVA выше)

# mkdir -p /etc/elasticsearch/config/cert/
# cp /usr/share/elasticsearch/elastic-c* /etc/elasticsearch/config/cert/
# chmod 666 /etc/elasticsearch/config/cert/elastic-c*

Файлы нужно скопировать на каждый узел кластера, для копирования на удаленный сервер воспользуйтесь утилитой scp.

Финальный шаг, теперь в конфиге elasticsearch.yml для каждого узла кластера указываем использование настроек безопасности XPack и ссылаемся на созданные СА и сертификат:

xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /etc/elasticsearch/config/cert/elastic-ca.p12
xpack.security.transport.ssl.truststore.path: /etc/elasticsearch/config/cert/elastic-cert.p12

Для применения настроек перезапустите сервис.

Полезная информация и первоисточник:
https://www.elastic.co/guide/en/elasticsearch/reference/6.8/configuring-tls.html
https://www.elastic.co/guide/en/elasticsearch/reference/6.8/certutil.html

1+

Elasticsearch. Настройка авторизации с помощью XPack

Начиная с версии 6.8.0 и 7.1.0 в Elasticsearch функция авторизации стала доступна для Basic версии.
Рассмотрим простую конфигурацию без сертификатов для кластера из одной ноды с авторизацией.

Шаг 1. Установка Elasticsearch.
https://www.elastic.co/downloads/past-releases

Скачать версию 6.8.2
Скачать версию 7.3.1

Шаг 2. Настройка XPack

В конфиге elasticsearch.yml указываем использование настроек безопасности XPack:

xpack.security.enabled: true
#xpack.security.transport.ssl.enabled: true
#xpack.security.transport.ssl.verification_mode: certificate
#xpack.security.transport.ssl.keystore.path: /etc/elasticsearch/config/cert/elastic-ca.p12
#xpack.security.transport.ssl.truststore.path: /etc/elasticsearch/config/cert/elastic-cert.p12

Параметры xpack.security.transport.ssl.*: true необходимо указать для кластерной архитектуры Elasticsearch.
Подробнее о выпуске сертификатов в статье: Elasticsearch. Выпуск сертификата в формате PKCS#12.

Шаг 3. Создание сервисных учетных записей в Elasticsearch

Переходим в директорию /usr/share/elasticsearch и запускаем утилиту elasticsearch-setup-passwords в режиме interactive:

# cd /usr/share/elasticsearch
# bin/elasticsearch-setup-passwords interactive

Интерактивный диалог предложен задать пароль для основных сервисных пользователей Elastic-стека:
— elasic
— kibana
— APM
— beats
— logstash
— remote_monitoring
Подробнее про утилиту elasticsearch-setup-passwords.

После этого этапа Elasticsearch будет доступен только для авторизированных запросов, иначе мы получим 401 ошибку:

{"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/]","header":{"WWW-Authenticate":"Basic realm=\"security\" charset=\"UTF-8\""}}],"type":"security_exception","reason":"missing authentication credentials for REST request [/]","header":{"WWW-Authenticate":"Basic realm=\"security\" charset=\"UTF-8\""}},"status":401}

Шаг 4. Настройка Kibana и Filebeat для общения.

Как видно из Шага 3, что теперь неавторизованные запросы к Elasticsearch отбиваются с ошибкой. Для этого необходимо прописать в конфиг сервисов авторизационные данные (логин\пароль) которые мы указали в Шаге 3 на этапе работы с bin/elasticsearch-setup-passwords interactive.

Для Kibana необходимо в конфиге kibana.yml указать два параметра elasticsearch.username и elasticsearch.password:

elasticsearch.username: "kibana"
elasticsearch.password: "qazqaz1"   

В случае с Filebeat мы должны отредактировать конфиг filebeat.yml добавив в графу output.elasticsearch параметры авторизации username и password:

  username: "elastic"
  password: "qazqaz1"

Подробнее про настройку Filebeat.

После изменения конфига необходимо перезагрузить сервис.

Теперь при попытки зайти в Kibana, она спрашивает логин\пароль для входа. Первый вход совершаем от учетки elasic (пароль мы задавали в Шаге 3) и создаем себе персональную учетную запись.

Шаг 4.1. Скрываем пароль в конфиге Filebeat.

Если Kibana обычно находиться рядом с Elasticsearch, то Filebeat как агент зачастую находиться на удаленном сервере, и лежащий в открытом виде пароль не очень хорошая затея.
Но пароль можно скрыть с помощью секрета в хранилище ключей и указать в конфиге в качестве переменной.

Первым делом необходимо создать хранилище и добавить туда запись:

# filebeat keystore create
# filebeat keystore add ES_PWD

После, редактируем конфиг filebeat.yml изменим значение параметра password и перезапустим сервис:

username: "elastic"
password: "${ES_PWD}"

Теперь пароль от пользователя elastic скрыт от лишних глаз.
Подробнее о хранилище ключей.

Полезная информация и первоисточник:
https://www.elastic.co/blog/getting-started-with-elasticsearch-security
https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-passwords.html
https://www.elastic.co/guide/en/beats/filebeat/6.8/filebeat-configuration.html
https://www.elastic.co/guide/en/beats/filebeat/current/keystore.html

0

Elasticsearch. Работа с curator_cli для фильтрации вывода индексов.

В прошлой статье о архивации индексов в Elasticsearch мы использовали инструмент Curator. Согласно официальной документации, Curator умеет фильтровать вывод индексов согласно заданным параметрам.

В этот рам мы рассмотрим несколько примеров фильтрации curator_cli.

Как говорилось ранее, мы использовали запрос выводящий список всех индексов старше N-дней. Рассмотрим подробнее, что делает этот запрос:

curator_cli --host localhost --port 9200 show_indices --filter_list "[{\"filtertype\":\"age\",\"source\":\"creation_date\",\"direction\":\"older\",\"unit\":\"days\",\"unit_count\":\"$DAYS\"},{\"filtertype\":\"kibana\",\"exclude\":\"True\"},{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"elastalert_status\",\"exclude\":\"True\"}]"

Мы запросили список всех индексов у Elasticsearch:

{\"filtertype\":\"age\",\"source\":\"creation_date\",\"direction\":\"older\",\"unit\":\"days\",\"unit_count\":\"$DAYS\"}

  • Параметр filtertype равный  age означает, что выборка индексов осуществляется на основе возраста(времени создания).
  • Параметр source равный creation_date — выбираем по дате создания.
  • Параметр direction равный older — этот параметр используется для определения того, являются ли индексы более старыми или младшими, чем контрольный момент времени, определяемый единицей, unit_count.
  • Параметр unit равный days — определяем параметр для unit_count. В нашем случаем мы ищем по дням (поиск возможен по другим временным единицам)
  • Параметр unit_count равный $DAYS — задаем множитель, старше какого дня ищем индексы.

Исключив из этого списка сервисный индекс .kibana в котором хранятся логи Kibana:

{\"filtertype\":\"kibana\",\"exclude\":\"True\"}

  • Параметр filtertype равный  kibana означает, что мы обращаемся к сервисному логу Kibana.
  • Параметр exclude равный True означает, что мы игнорируем данные индексы.

И исключив журнал запросов Elasticsearch:

{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"elastalert_status\",\"exclude\":\"True\"}

  • Параметр filtertype равный pattern означает, что данный тип фильтра будет перебирать список действий и сопоставлять индексы, соответствующие заданному шаблону.
  • Параметр kind равный regex — Этот параметр сообщает шаблону, что мы используем регулярное выражение.
  • Параметр value равный elastalert_status — значение kind, в нашем случаем мы обращаемся к журнал запросов Elasticsearch.
  • Параметр exclude равный True означает, что мы игнорируем данные индексы.

Немного о совмещении разных типов  filtertype

Если в Elasticsearch хранятся индексы с разным именем и назначением, то объединяя разные параметры поиска мы можем гибко фильтровать индексы.

На пример совместив filtertype pattern и age мы можем более точно выводить список индексов. Предположим в Elasticsearch два типа индексов с именами auditbeat-6.5.2-YYYY.MM.DD для хранения логов аудита и filebeat-6.2.3-YYYY.MM.DD для хранение логов сторонних сервисов.

#curator_cli --host localhost --port 9200 show_indices --filter_list "[{\"filtertype\":\"age\",\"source\":\"creation_date\",\"direction\":\"older\",\"unit\":\"days\",\"unit_count\":\"0\"},{\"filtertype\":\"kibana\",\"exclude\":\"True\"},{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"elastalert_status\",\"exclude\":\"True\"}]"

auditbeat-6.5.2-2019.02.18
auditbeat-6.5.2-2019.02.19
filebeat-6.2.3-2019.02.18
filebeat-6.2.3-2019.02.19

Объединив  filtertype pattern и age мы можем вывести отдельно список индексов auditbeat старше 1 (одного) дня:

#curator_cli --host localhost --port 9200 show_indices --filter_list "[{\"filtertype\":\"pattern\",\"kind\":\"prefix\",\"value\":\"auditbeat-\"},{\"filtertype\":\"age\",\"source\":\"creation_date\",\"direction\":\"older\",\"unit\":\"days\",\"unit_count\":\"1\"},{\"filtertype\":\"kibana\",\"exclude\":\"True\"},{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"elastalert_status\",\"exclude\":\"True\"}]"

auditbeat-6.5.2-2019.02.18

Как видим, для filtertype = pattern ми использовали регулярное выражение с шаблоном  value равному auditbeat-

Официальная документация: https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/filters.html

4+

Elasticsearch. Архивирование индексов в Elasticsearch

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

Подготовительный этап ОС.

Для начала нам необходимо установить соответствующее ПО для реализации данного сценария.

Подключим репозитирий Curator [5.5]:

для YUM Repository
https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/yum-repository.html

#vim /etc/yum.repos.d/elasticsearch-curator.repo
[curator-5]
name=CentOS/RHEL 7 repository for Elasticsearch Curator 5.x packages
baseurl=https://packages.elastic.co/curator/5/centos/7
gpgcheck=1
gpgkey=https://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

для APT repository
https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/apt-repository.html

#vim /etc/apt/sources.list.d/elasticsearch-curator.list
deb [arch=amd64] https://packages.elastic.co/curator/5/debian9 stable main

Ставим пакеты curator, NFS и jq:

для Centos 7 

#yum install -y elasticsearch-curator jq nfs

для Debian\Ubuntu

#sudo apt install -y  elasticsearch-curator jq nfs

Теперь создадим общую шару, куда будут иметь доступ наши машины с elasticsearch.
Советую создавать шару на стороннем сервере, можно поднять ее сразу на архивном, и примонтировать к elastic-машинам. 

Настройка NFS (на архивном сервере):

#mkdir -p /var/nfs_elk/snapshots/repository/
#mkdir -p /var/nfs_elk/snapshots/recovery/
#mkdir -p /var/nfs_elk/elasticsearch_backup
#chmod -R 755 /var/nfs_elk/*
#vim /etc/exports
/var/nfs_elk 192.168.1.0/24(rw,sync,no_root_squash)

Монтирование шары (на elastic-машинах):

#mkdir /var/nfs_elk/
#mount -t nfs 192.168.1.10:/var/nfs_elk/ /var/nfs_elk/

Подготовительный этап Elasticsearch.

После установки пакетов и настройки шар приступим к настройки elasticsearch.
Elasticsearch необходимо объявить общую шару и зарегистрировать ее.

В конфиг Elasticsearch.yml на всех машинах добавляем информацию об общей шаре и перезапустить сервис:

#vim /etc/elasticsearch/elasticsearch.yml
path.repo: /var/nfs-elk/snapshots

#systemctl restart elasticsearch

Объявить Elasticsearch на всех машинах о папке, куда будет бекапиться индекс:

curl -XPUT 'http://127.0.0.1:9200/_snapshot/repository' -H 'Content-Type: application/json' -d '{
"type": "fs",
"settings": {
"location": "repository",
"compress": true
}
}'

Объявить Elasticsearch на всех машинах о папке, куда будут складываться временные файлы при восстановлении индекса:

curl -XPUT 'http://127.0.0.1:9200/_snapshot/recovery' -H 'Content-Type: application/json' -d '{
"type": "fs",
"settings": {
"location": "recovery",
"compress": true
}
}'

Настройка архивирования индексов Elasticsearch

Процесс архивации протекает в несколько этапов:

  • Curator выводит список индексов из Elasticsearch согласно описанным правилам.
  • Создание снапшота индекса.
  • Переносим снапшота в ранее созданную директорию repository (/var/nfs_elk/snapshots/repository/).
  • Архивация в tar.gz и перенос архива в папку с бекапами.
  • Удаление индекса и снапшота.
  • Очистка папки repository.

Пример sh скрипта:

#vim backup.sh

#!/bin/bash

DAYS=21 #Количество дней, от текущей даты, старше которого индексы будут архивироваться
SNAPSHOT_DIRECTORY="/var/nfs_elk/snapshots" #Path to snapshot index из elasticsearch.yml
BACKUP_DIR="/var/nfs_elk/elasticsearch_backup" #Папка куда будут ложиться архивные логи
REPOSITORY="repository"
LOG="/var/log/elasticsearch/elasticsearch_backup.log" #Пишем процесс архивации в лог.
DATE=`date`

#Проверим существование папки для архивов и если нет, создадим её
if ! [ -d $BACKUP_DIR ]; then
mkdir -p $BACKUP_DIR
fi

#Получаем массив индексов, которые старше $DAYS
INDICES=`curator_cli --host localhost --port 9200 show_indices --filter_list "[{\"filtertype\":\"age\",\"source\":\"creation_date\",\"direction\":\"older\",\"unit\":\"days\",\"unit_count\":\"$DAYS\"},{\"filtertype\":\"kibana\",\"exclude\":\"True\"},{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"elastalert_status\",\"exclude\":\"True\"}]"`

#Проверим, не пустой ли список
TEST_INDICES=`echo $INDICES | grep -q -i "error" && echo 1 || echo 0`

if [ $TEST_INDICES == 1 ]
then
echo "$DATE Не найдено индексов для обработки" >> $LOG
exit
else
# Составляем цикл для каждого индекса в массиве $INDICES
for i in $INDICES
do
# Создаём снапшот для индекса $i
curator_cli --timeout 600 --host localhost --port 9200 snapshot --repository $REPOSITORY --filter_list "{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"$i\"}"

# Заносим в переменную имя снапшота для индекса $i
SNAPSHOT=`curator_cli --host localhost --port 9200 show_snapshots --repository $REPOSITORY`

# Архивируем папку репозитория и складываем архив в хранилище
cd $SNAPSHOT_DIRECTORY/$REPOSITORY && tar -zcvf $BACKUP_DIR"/"$i".tar.gz" ./*

# Удаляем snapshot
curator_cli --host localhost --port 9200 delete_snapshots --repository $REPOSITORY --filter_list "{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"$SNAPSHOT\"}"

# Удаляем индекс
curator_cli --host localhost --port 9200 delete_indices --filter_list "{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"$i\"}"

# Очищаем папку репозитория
rm -rf $SNAPSHOT_DIRECTORY/$REPOSITORY/*
done
fi

Подробнее о шаблонах фильтрации в этой статье

Ключ —host с параметром localhost возможно использовать только в том случае, если мы указали elasticsearch случать этот адрес. Если elasticsearch слушает порт 9200 только на одном адресе, то указать корректные данные.

После создания скрипта, добавим его выполнение в cron каждый день в час ночь (01:00 РМ):

#crontab -e
0 1 * * * /bin/bash /root/backup.sh >> /var/log/elasticsearch/elasticsearch_backup.log

Первоисточник: https://habr.com/ru/company/true_engineering/blog/349192/

3+

PostgreSQL. Добавление пользователей с правами на чтение.

Создание группы:

CREATE ROLE user_group;

Создание пользователя:

CREATE ROLE user_db WITH LOGIN ENCRYPTED PASSWORD 'passdb';

Добавление пользователя в группу:

GRANT user_group TO user_db;

Выдача прав на подключение к БД:

GRANT CONNECT ON DATABASE server_DB TO user_group;

Выдача права на чтение (только на выполнение SELECT):

GRANT SELECT ON all tables IN schema public TO user_group;
2+