Как использовать Etcdctl и Etcd, распределенное хранилище ключей и значений CoreOS
Введение
Одной из технологий, которая делает возможной CoreOS, является etcd
, глобально распределенное хранилище ключей и значений. Эта служба используется отдельными машинами CoreOS для формирования кластера и в качестве платформы для хранения глобально доступных данных.
В этом руководстве мы рассмотрим демон etcd
, а также утилиту etcdctl
и API HTTP/JSON, которые можно использовать для управления им.
Предпосылки
Чтобы следовать этому руководству, мы предполагаем, что у вас есть кластер компьютеров CoreOS в качестве нашего руководства по настройке кластера CoreOS на схемах DigitalOcean. Это оставит вас с тремя серверами в одном кластере:
- кореос-1
- кореос-2
- кореос-3
После того, как эти машины будут запущены и запущены, вы можете продолжить работу с этим руководством.
Модель обнаружения кластера etcd
Одной из самых фундаментальных задач, за которую отвечает etcd
, является организация отдельных машин в кластер. Это делается при загрузке CoreOS путем регистрации по адресу обнаружения, указанному в файле cloud-config
, который передается при создании.
Служба обнаружения, управляемая CoreOS, доступна по адресу https://discovery.etcd.io
. Вы можете получить новый токен, посетив страницу /new
. Там вы получите токен, который ваши машины могут использовать для обнаружения своих сопутствующих узлов. Это будет выглядеть примерно так:
https://discovery.etcd.io/dcadc5d4d42328488ecdcd7afae5f57c
Вы должны предоставить новый токен для каждого нового кластера. Это включает в себя случаи, когда вам необходимо перестроить кластер с использованием узлов, которые могут иметь один и тот же IP-адрес. Экземпляры etcd
будут сбиты с толку из-за этого и не будут правильно функционировать для построения кластера, если вы повторно используете адрес обнаружения.
Посетив адрес обнаружения в веб-браузере, вы получите объект JSON, описывающий известные машины. Когда вы только начнете, у него не будет узлов:
{"action":"get","node":{"key":"/_etcd/registry/dcadc5d4d42328488ecdcd7afae5f57c","dir":true,"modifiedIndex":102511104,"createdIndex":102511104}}
После начальной загрузки вашего кластера вы сможете увидеть больше информации здесь:
{"action":"get","node":{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda","dir":true,"nodes":[{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda/2ddbdb7c872b4bc59dd1969ac166501e","value":"http://10.132.252.38:7001","expiration":"2014-09-19T13:41:26.912303668Z","ttl":598881,"modifiedIndex":102453704,"createdIndex":102453704},{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda/921a7241c31a499a97d43f785108b17c","value":"http://10.132.248.118:7001","expiration":"2014-09-19T13:41:29.602508981Z","ttl":598884,"modifiedIndex":102453736,"createdIndex":102453736},{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda/27987f5eaac243f88ca6823b47012c5b","value":"http://10.132.248.121:7001","expiration":"2014-09-19T13:41:41.817958205Z","ttl":598896,"modifiedIndex":102453860,"createdIndex":102453860}],"modifiedIndex":101632353,"createdIndex":101632353}}
Если вам нужно найти URL-адрес обнаружения кластера, вы можете сделать это с любой из машин, являющихся его членами. Эту информацию можно получить из иерархии /run
:
cat /run/systemd/system/etcd.service.d/20-cloudinit.conf
[Service]
Environment="ETCD_ADDR=10.132.248.118:4001"
Environment="ETCD_DISCOVERY=https://discovery.etcd.io/dcadc5d4d42328488ecdcd7afae5f57c"
Environment="ETCD_NAME=921a7241c31a499a97d43f785108b17c"
Environment="ETCD_PEER_ADDR=10.132.248.118:7001"
URL хранится в записи ETCD_DISCOVERY
.
Когда машины, на которых работает etcd
, загружаются, они проверяют информацию по этому URL-адресу. Он будет представлять свою собственную информацию и запросы о других членах. Первый узел в кластере, очевидно, не найдет информацию о других узлах, поэтому назначит себя лидером кластера.
Последующие машины также свяжутся с URL-адресом обнаружения со своей информацией. Они получат информацию об уже зарегистрированных машинах. Затем они выберут одну из этих машин и подключатся напрямую, где получат полный список работоспособных членов кластера. Репликация и распространение данных осуществляется с помощью алгоритма консенсуса Raft.
Данные о каждой из машин хранятся в скрытой структуре каталогов внутри etcd
. Вы можете просмотреть информацию о машинах, о которых знает etcd
, набрав:
etcdctl ls /_etcd/machines --recursive
/_etcd/machines/2ddbdb7c872b4bc59dd1969ac166501e
/_etcd/machines/921a7241c31a499a97d43f785108b17c
/_etcd/machines/27987f5eaac243f88ca6823b47012c5b
Детали, которые etcd
передают новым членам кластера, содержатся в этих ключах. Вы можете увидеть отдельные значения, запросив их с помощью etcdctl
:
etcdctl get /_etcd/machines/2ddbdb7c872b4bc59dd1969ac166501e
etcd=http%3A%2F%2F10.132.252.38%3A4001&raft=http%3A%2F%2F10.132.252.38%3A7001
Позже мы более подробно рассмотрим команды etcdctl
.
Использование etcdctl
Существует два основных способа взаимодействия с etcd
. Через API HTTP/JSON и через клиент, например включенную утилиту etcdctl
. Сначала мы рассмотрим etcdctl
.
Просмотр ключей и каталогов
Для начала давайте посмотрим, что сейчас хранит etcdctl
. Мы можем увидеть ключи верхнего уровня, набрав:
etcdctl ls /
/coreos.com
Как видите, у нас один результат. На данный момент неясно, является ли это каталогом или ключом. Мы можем попытаться получить
узел, чтобы увидеть либо значение ключа, либо увидеть, что это каталог:
etcdctl get /coreos.com
/coreos.com: is a directory
Чтобы избежать этого ручного рекурсивного процесса, мы можем указать etcdctl
вывести всю иерархию видимой информации, набрав:
etcdctl ls / --recursive
/coreos.com
/coreos.com/updateengine
/coreos.com/updateengine/rebootlock
/coreos.com/updateengine/rebootlock/semaphore
Как видите, в начальном узле /coreos.com
было довольно много каталогов. Мы можем увидеть, как выглядит получение фактических данных из узла, запросив информацию в конечной конечной точке:
etcdctl get /coreos.com/updateengine/rebootlock/semaphore
{"semaphore":1,"max":1,"holders":null}
Это не содержит информации, которая очень полезна для нас. Мы можем получить некоторые дополнительные метаданные об этой записи, передав параметр -o extended
. Это глобальная опция, поэтому она должна стоять перед командой get
:
etcdctl -o extended get /coreos.com/updateengine/rebootlock/semaphore
Key: /coreos.com/updateengine/rebootlock/semaphore
Created-Index: 6
Modified-Index: 6
TTL: 0
Etcd-Index: 170387
Raft-Index: 444099
Raft-Term: 8
{"semaphore":1,"max":1,"holders":null}
Установка ключей и создание узлов
Чтобы создать новый каталог, вы можете использовать команду mkdir
следующим образом:
etcdctl mkdir /example
Чтобы сделать ключ, вы можете использовать команду mk
:
etcdctl mk /example/key data
data
Это будет работать только в том случае, если ключ еще не существует. Если мы запросим значение созданного нами ключа, мы сможем получить данные, которые мы установили:
etcdctl get /example/key
data
Чтобы обновить существующий ключ, используйте команду update
:
etcdctl update /example/key turtles
turtles
Сопутствующая команда updatedir
для каталогов, вероятно, полезна только в том случае, если вы установили TTL или время жизни для каталога. Это обновит время TTL на прошедшее. Вы можете установить TTL для каталогов или ключей, передав аргумент --ttl #
, где \# — количество секунд, которое нужно сохранить:
etcdctl mkdir /here/you/go --ttl 120
Затем вы можете обновить TTL с помощью updatedir
:
etcdctl updatedir /here/you/go --ttl 500
Чтобы изменить значение существующего ключа или создать ключ, если он не существует, используйте команду set
. Думайте об этом как о комбинации команд mk
и update
:
etcdctl set /example/key new
new
Это может включать несуществующие пути. Компоненты пути будут созданы динамически:
etcdctl set /a/b/c here
here
Чтобы получить ту же функцию создания, если-не-существует, для каталогов, вы можете использовать команду setdir
:
etcdctl setdir /x/y/z
Примечание. Команда setdir
в настоящее время не работает так, как указано. В текущей сборке его использование зеркально отражает команду updatedir
и завершится ошибкой, если каталог уже существует. Для решения этой проблемы в репозитории GitHub есть открытая проблема.
Удаление записей
Чтобы удалить существующие ключи, вы можете использовать команду rm
или rmdir
.
Команду rm
можно использовать для удаления ключа:
etcdctl rm /a/b/c
Его также можно использовать рекурсивно для удаления каталога и каждого подкаталога:
etcdctl rm /a --recursive
Чтобы удалить только пустой каталог или ключ, используйте команду rmdir
:
etcdctl rmdir /x/y/z
Это можно использовать, чтобы убедиться, что вы удаляете только конечные точки иерархий.
Наблюдая за изменениями
Вы можете отслеживать изменения в конкретном ключе или во всей директории. Просмотр их с помощью etcdctl
приведет к зависанию операции до тех пор, пока какое-либо событие не произойдет с тем, что просматривается.
Чтобы посмотреть ключ, используйте его без каких-либо флагов:
etcdctl watch /example/hello
Чтобы прекратить просмотр, нажмите CTRL-C
. Если во время просмотра будет обнаружено изменение, будет возвращено новое значение.
Чтобы просмотреть всю структуру каталогов, используйте флаг --recursive
:
etcdctl watch --recursive /example
Вы можете увидеть, как это было бы полезно, поместив его в простую циклическую конструкцию, чтобы постоянно отслеживать состояние значений:
while true; do etcdctl watch --recursive /example; done
Если вы хотите выполнять команду всякий раз, когда обнаруживается изменение, используйте команду exec-watch
:
etcdctl exec-watch --recursive /example -- echo "hello"
Это будет отображать «привет» на экране всякий раз, когда значение в этом каталоге изменяется.
Скрытые ценности
Одна вещь, которая не сразу бросается в глаза, это то, что внутри etcd
есть скрытые структуры каталогов. Это каталоги или ключи, начинающиеся со знака подчеркивания.
Их нет в списке обычных инструментов etcdctl
, и вы должны знать, что ищете, чтобы найти их.
Например, существует скрытый каталог с именем /_coreos.com
, в котором содержится некоторая внутренняя информация о автопарке
. Вы можете увидеть иерархию, явно запросив ее:
etcdctl ls --recursive /_coreos.com
/_coreos.com/fleet
/_coreos.com/fleet/states
/_coreos.com/fleet/states/apache@6666.service
/_coreos.com/fleet/states/apache@6666.service/2ddbdb7c872b4bc59dd1969ac166501e
/_coreos.com/fleet/states/apache@7777.service
/_coreos.com/fleet/states/apache@7777.service/921a7241c31a499a97d43f785108b17c
. . .
Другая такая структура каталогов находится внутри /_etcd
:
etcdctl ls --recursive /_etcd
/_etcd/machines
/_etcd/machines/27987f5eaac243f88ca6823b47012c5b
/_etcd/machines/2ddbdb7c872b4bc59dd1969ac166501e
/_etcd/machines/921a7241c31a499a97d43f785108b17c
/_etcd/config
Они функционируют точно так же, как и любые другие записи, с той лишь разницей, что они не отображаются в общих списках. Вы можете создать их, просто начав свой ключ или имя каталога со знака подчеркивания.
Использование HTTP/JSON API и т. д.
Другой способ взаимодействия с etcd
— простой HTTP/JSON API.
Для доступа к API вы можете использовать простую HTTP-программу, например curl
. Вы должны указать флаг -L
, чтобы следовать любым перенаправлениям, которые возвращаются. Внутри вашего кластера вы можете использовать локальный интерфейс 127.0.0.1
и порт 4001
для большинства запросов.
Примечание. Чтобы подключиться к etcd
из контейнера Docker, можно использовать адрес http://172.17.42.1:4001
. Это может быть полезно для приложений, чтобы обновлять свои конфигурации на основе зарегистрированной информации.
Доступ к обычному пространству ключей можно получить, перейдя по адресу http://127.0.0.1:4001/v2/keys/
на любом хост-компьютере. Например, чтобы получить список ключей/каталогов верхнего уровня, введите:
curl -L http://127.0.0.1:4001/v2/keys/
{"action":"get","node":{"key":"/","dir":true,"nodes":[{"key":"/coreos.com","dir":true,"modifiedIndex":6,"createdIndex":6},{"key":"/services","dir":true,"modifiedIndex":333,"createdIndex":333}]}}
Косая черта в конце запроса обязательна. Без него он не будет корректно решаться.
Вы можете устанавливать или извлекать значения, используя обычные HTTP-команды.
Чтобы изменить поведение этих операций, вы можете передать флаги в конце запроса, используя синтаксис ?flag=value
. Несколько флагов могут быть разделены символом &
.
Например, чтобы рекурсивно перечислить все ключи, мы могли бы ввести:
curl -L http://127.0.0.1:4001/v2/keys/?recursive=true
{"action":"get","node":{"key":"/","dir":true,"nodes":[{"key":"/coreos.com","dir":true,"nodes":[{"key":"/coreos.com/updateengine","dir":true,"nodes":[{"key":"/coreos.com/updateengine/rebootlock","dir":true,"nodes":[{"key":"/coreos.com/updateengine/rebootlock/semaphore","value":"{\"semaphore\":1,\"max\":1,\"holders\":null}","modifiedIndex":6,"createdIndex":6}],"modifiedIndex":6,"createdIndex":6}],"modifiedIndex":6,"createdIndex":6}],"modifiedIndex":6,"createdIndex":6}. . .
Еще одна полезная часть информации, доступная за пределами обычного пространства ключей, — это информация о версии, доступная здесь:
curl -L http://127.0.0.1:4001/version
etcd 0.4.6
Вы можете просмотреть статистику об отношениях каждого лидера кластера с каждым последователем, посетив эту конечную точку:
curl -L http://127.0.0.1:4001/v2/stats/leader
{"leader":"921a7241c31a499a97d43f785108b17c","followers":{"27987f5eaac243f88ca6823b47012c5b":{"latency":{"current":1.607038,"average":1.3762888642395448,"standardDeviation":1.4404313533578545,"minimum":0.471432,"maximum":322.728852},"counts":{"fail":0,"success":98718}},"2ddbdb7c872b4bc59dd1969ac166501e":{"latency":{"current":1.584985,"average":1.1554367141497013,"standardDeviation":0.6872303198242179,"minimum":0.427485,"maximum":31.959235},"counts":{"fail":0,"success":98723}}}}
Аналогичную операцию можно использовать для получения статистики о машине, на которой вы сейчас находитесь:
curl -L http://127.0.0.1:4001/v2/stats/self
{"name":"921a7241c31a499a97d43f785108b17c","state":"leader","startTime":"2014-09-11T16:42:03.035382298Z","leaderInfo":{"leader":"921a7241c31a499a97d43f785108b17c","uptime":"1h19m11.469872568s","startTime":"2014-09-12T19:47:25.242151859Z"},"recvAppendRequestCnt":1944480,"sendAppendRequestCnt":201817,"sendPkgRate":40.403374523779064,"sendBandwidthRate":3315.096879676072}
Чтобы просмотреть статистику о выполненных операциях, введите:
curl -L http://127.0.0.1:4001/v2/stats/store
{"getsSuccess":78823,"getsFail":14,"setsSuccess":121370,"setsFail":4,"deleteSuccess":28,"deleteFail":32,"updateSuccess":20468,"updateFail":4,"createSuccess":39,"createFail":102340,"compareAndSwapSuccess":51169,"compareAndSwapFail":0,"compareAndDeleteSuccess":0,"compareAndDeleteFail":0,"expireCount":3,"watchers":6}
Это лишь некоторые из операций, которые можно использовать для управления etcd
через API.
Конфигурация и т. д.
Службу etcd
можно настроить несколькими способами.
Первый способ — передать параметры с файлом cloud-config
, который вы используете для начальной загрузки ваших узлов. В руководстве по начальной загрузке вы немного узнали о том, как это сделать:
#cloud-config
coreos:
etcd:
discovery: https://discovery.etcd.io/<token>
addr: $private_ipv4:4001
peer-addr: $private_ipv4:7001
. . .
Чтобы просмотреть доступные параметры, используйте флаг -h
с etcd
:
etcd -h
Чтобы включить эти параметры в свой cloud-config
, просто удалите дефис в начале и отделите ключи от значений двоеточием вместо знака равенства. Таким образом, -peer-addr=
становится peer-addr:
.
После прочтения файла cloud-config
CoreOS преобразует их в переменные среды в файле-заглушке, который используется для запуска службы.
Другой способ настроить параметры etcd
— через API. Обычно это делается с использованием порта 7001
вместо стандартного 4001
, который используется для ключевых запросов.
Например, вы можете получить некоторые из текущих значений конфигурации, набрав:
curl -L http://127.0.0.1:7001/v2/admin/config
{"activeSize":9,"removeDelay":1800,"syncInterval":5}
Вы можете изменить эти значения, передав новый JSON в качестве полезных данных с операцией PUT:
curl -L http://127.0.0.1:7001/v2/admin/config -XPUT -d '{"activeSize":9,"removeDelay":1800,"syncInterval":5}'
{"activeSize":9,"removeDelay":1800,"syncInterval":5}
Чтобы получить список машин, вы можете перейти к конечной точке /v2/admin/machines
:
curl -L http://127.0.0.1:7001/v2/admin/machines
[{"name":"27987f5eaac243f88ca6823b47012c5b","state":"follower","clientURL":"http://10.132.248.121:4001","peerURL":"http://10.132.248.121:7001"},{"name":"2ddbdb7c872b4bc59dd1969ac166501e","state":"follower","clientURL":"http://10.132.252.38:4001","peerURL":"http://10.132.252.38:7001"},{"name":"921a7241c31a499a97d43f785108b17c","state":"leader","clientURL":"http://10.132.248.118:4001","peerURL":"http://10.132.248.118:7001"}]
Это можно использовать для принудительного удаления компьютеров из кластера с помощью метода DELETE.
Заключение
Как видите, etcd
можно использовать для хранения или извлечения информации с любой машины в вашем кластере. Это позволяет синхронизировать данные и предоставляет службам место для поиска данных конфигурации и сведений о соединении.
Это особенно полезно при построении распределенных систем, поскольку вы можете предоставить простую конечную точку, которая будет действительна из любого места в кластере. Воспользовавшись этим ресурсом, ваши службы могут динамически конфигурировать себя.