Поиск по сайту:

Как использовать 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 можно использовать для хранения или извлечения информации с любой машины в вашем кластере. Это позволяет синхронизировать данные и предоставляет службам место для поиска данных конфигурации и сведений о соединении.

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