- PVSM.RU - https://www.pvsm.ru -
Аннотация. Статья про очень простой скрипт, формирующий из списка серверов когфиг для ssh Linux. Проверено на Ubunta 18, используется Goodle Cloud SDK, Python 2.7, Bash.
После резкого увеличения количества серверов, с которыми приходится работать, понял, хранилище паролей и CMDB уже не дают такого оперативного доступа, как в те времена, когда просто помнил все ip и реквизиты наизусть. Может быть и потому, что CMDB мы до конца еще так и не осилили. Но тем не менее решать проблему быстрого доступа по SSH к большому количеству серверов как-то надо.
Дальше — с точки зрения терминала Linux (выполнялось на Ubunta 18). Возможно, работает и в других дистрибутивах и, вероятно, даже есть аналог на Windows — не смотрел.
Главные требования:
Для этого решил использовать alias хостов в настройках ssh, список серверов получать через gcloud cli клиент GCP, а автоматизировать все это с помощью Python 2.7 (потому что он в Ubuntu был по умолчанию и я решил его изучить для работы с данными). Сам скрипт с описанием под катом.
Идея была такая: вести список связи "алиасов" серверов и их актуальных адресов таким образом, чтобы при установке подключения можно было использовать только имя. При этом сам список периодически актуализировать из GCP по API.
В итоге задач стояло несколько:
Тут все довольно просто и решено не мной. Утилита ssh в Linux поддерживает настройку алиасов в конфиг файле.
Расположение файла: ~.ssh/config
Формат файла мы использовали очень банальный, но на самом деле возможности там намного шире:
HOST алиас_сервера
HostName ip_или_имя-сервера
Подробнее о возможностях конфигурации можно прочитать тут [1], тут [2] или в официальной документации [3].
Тут решение принадлежит совершенно не мне, а Ben Lobaugh [4] и описано в его статье [5].
Коротко говорят, использовал sed, который для простоты запуска (уж очень длинное правило в параметрах) сокращено через alias:
alias sshhosts="sed -rn ‘s/^s*Hosts+(.*)s*/1/ip’ ~/.ssh/config"
Если надо найти хост по части названия, то этот скрипт отлично дополняется утилитой grep и в итоге получается так:
sshhost | grep 'Искомая-часть-названия-хоста'
Есть и другие варианты, например, как описано тут [6].
Спасибо за решение onix74 [7] !
Добавить в ~/.bash_completion строку:
complete -W "$(grep "^Host " ~/.ssh/config | grep -v "*" | sed 's/[^ ]* *(.*)/1/')" ssh
Для команды ssh будет работать автозаполнение по списку алиасов серверов. Т.е. можно использовать ssh для подстановки имени ssh-сервера. Работает в bash.
Планирую поделить хосты на группы, чтобы можно было выбирать все сервера определенного клиента или с определенным приложением. Думается, такая возможность будет интересна для массового выполнения скриптов и подключения Ansible; а также для создания разных реквизитов подключения для разных групп. Но насколько это действительно имеет смысл еще предстоит выяснить.
В этом шаге все довольно просто, если не считать настройки параметров (хотя и тут дело опыта). Решил использовать GCloud SDK для получения данных, т.к. пока пользуюсь им редко, но предполагаю, что когда-то это позволит мне все меньше использовать графический интерфейс и значительно упростить рутину администрирования. Поэтому основной аргумент — получение опыта.
Вероятно, то же самое можно было бы сделать используя curl и REST API GCP, и тогда решение было бы более универсальным (т.к. GCloud SDK требуют отдельной установки и инициализации, которые не так уж сложны, но все равно требуются).
Для получения нужной информации пришлось использовать формат json. Хотя это существенно упростило дальнейшую обработку полученного ответа, но заставило немного поломать голову с настройкой параметров форматирования в SDK.
В итоге получил такую команду:
gcloud compute instances list --filter="status:running" --format="json(name, status, networkInterfaces[].accessConfigs[])"
Возвращает только активные на текущий момент сервера (к остальным нет смысла подключаться) с информацией об их имени и сетевом интерфейсе. Пока что используется только один внешний интерфейс для каждого сервера.
Итоговый результат прилетает в json:
[
---...----
{
"name": "название-сервера",
"networkInterfaces": [
{
"accessConfigs": [
{
"kind": "compute#accessConfig",
"name": "External NAT",
"natIP": "ip-адрес",
"networkTier": "PREMIUM",
"type": "ONE_TO_ONE_NAT"
}
]
}
],
"status": "RUNNING"
},
----...---
]
Найти формат, вывод которого позволит минимизировать или вообще устранить последующую обработку.
Скрипт написал на python 2.7 по двум причинам:
Алгоритм следующий:
#!/usr/bin/python
import commands
import json
sComputeListOutput = commands.getoutput('gcloud compute instances list --filter="status:running" --format="json(name, status, networkInterfaces[].accessConfigs[])" ')
s = json.loads(sComputeListOutput)
for server in s:
print 'HOST ',server['name']
print ' HostName ',server['networkInterfaces'][0]['accessConfigs'][0]['natIP']
Эта задача пока в работе. Планирую читать файл ssh/config в рамках того же скрипта, сравнивать с полученными значениями и потом записывать весь результат обратно. Или генерировать новый файл отдельно и проводить сравнение, используя какой-нибудь diff — это позволит вручную подтверждать все изменения.
Автор: Александр
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ssh/343776
Ссылки в тексте:
[1] тут: https://linuxize.com/post/using-the-ssh-config-file/
[2] тут: https://www.cyberciti.biz/faq/create-ssh-config-file-on-linux-unix/
[3] официальной документации: https://www.ssh.com/ssh/config
[4] Ben Lobaugh: https://ben.lobaugh.net/
[5] в его статье: https://ben.lobaugh.net/blog/203195/quickly-list-all-hosts-in-your-ssh-config
[6] тут: https://www.jamesridgway.co.uk/blog/list-ssh-hosts-from-your-ssh-config
[7] onix74: https://habr.com/ru/users/onix74/
[8] Источник: https://habr.com/ru/post/484500/?utm_source=habrahabr&utm_medium=rss&utm_campaign=484500
Нажмите здесь для печати.