Kubernetes the hard way etcd setup: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 78 промежуточных версий этого же участника)
Строка 5: Строка 5:
 
[[Категория:TLS]]
 
[[Категория:TLS]]
 
[[Категория:Etcd]]
 
[[Категория:Etcd]]
  +
[[Категория:Kubernetes the hard way v2]]
 
=ETCD=
 
=ETCD=
  +
Вторая версия статьи, максимально подробная
  +
(первая версия тут - https://noname.com.ua/mediawiki/index.php/Etcd)
  +
  +
  +
=Требования к окружению=
  +
* 3 ноды raspberry pi установленные и настроенные, имеющие коннективити друг с другом
  +
* для работы etcd выделен отдельный VLAN с отдельным адресным пространством
  +
* установленный и настроенный PKI на основе Hashicorp Vault (в примере - по адресу http://vault.home)
  +
* Настроенный DNS и созданы записи для всех доменов в примере (в моем случае DNS поднят на MikroTik)
  +
  +
==DNS==
  +
Подчеркну что все взаимоджействие происходит исключительно по доменным именам<br>
  +
Создаем три записи DNS (для трех мастер-нод каждая из которых находится в своей "'''Availability Zone'''" (В кавычках по тому что в лабе это все очень условно)
  +
<br>
  +
<pre>
  +
/ip/dns/static/add name=etcd.master.az1.k8s.cluster.home address=10.0.11.1
  +
/ip/dns/static/add name=etcd.master.az2.k8s.cluster.home address=10.0.21.1
  +
/ip/dns/static/add name=etcd.master.az3.k8s.cluster.home address=10.0.31.1
  +
</pre>
  +
  +
=Описание параметров <code>ETCd</code>=
  +
==Общие параметры==
  +
* <B> --debug </B>
  +
* <B> --name</B>=<code>etcd-az-1</code> Имя ноды кластера - должно быть одним из содержащихся в параметре <B> --initial-cluster</B> На каждой ноде это имя отличается
  +
* <B> --data-dir</B><code>=/var/lib/etcd</code>
  +
  +
* <B> --listen-peer-urls</B> адрес для peer-to-peer коммуникации
  +
* <B> --listen-client-urls</B> адрес для клиентов (https допустим только при наличии сертификатов)
  +
* <B> --advertise-client-urls</B> адрес который будет анонсирован для клиентов, тут должно быть доменное имя и оно же должно быть в CN/AltNames что бы можно было валидировать сертификат
  +
  +
==Параметры кластера==
  +
* <B> --initial-advertise-peer-urls</B>Адрес который будет анонсирован для peer-to-peer соединений, тоже домен
  +
* <B> --initial-cluster-token</B> начальный токен, ЭТОТ ТОКЕН ОБЩИЙ ДЛЯ ВСЕХ НОД иначе вместо одного кластера из 3 нод будет создано три неполных кластера из одной ноды каждый
  +
* <B> --initial-cluster</B>список нод кластера вместе с именами, этот список общий для всех нод и должен быть одинаковый
  +
* <B> --initial-cluster-state</B> должно быть new для нового кластера
  +
  +
==Параметры SSL для peer-to-peer==
  +
* <B> --peer-client-cert-auth</B> требовать SSL (сертификаты всех нод должны быть подписаны одним СА)
  +
* <B> --peer-cert-file</B> файл сертификата
  +
* <B> --peer-key-file</B> файл ключа
  +
* <B> --peer-trusted-ca-file</B>СА которым подписаны сертификаты для peer-to-peer взаимодействия
  +
  +
==Параметры SSL для клиентских подключений==
  +
* <B> --trusted-ca-file</B>СА которым подписаны клиентские сертификаты
  +
* <B> --cert-file</B> файл сертификата
  +
* <B> --key-file</B> файл ключа
  +
* <B> --client-cert-auth </B> требовать SSL от клиентов (и не разрешать подключения без сертификата)
  +
  +
=Установка из пакетов (на всех трех нодах)=
  +
Собирать код самой последней версии под архитектуру АРМ откровенно лениво
 
<PRE>
 
<PRE>
  +
apt -y \
apt install etcd etcd-client etcd-server etcd-discovery
 
  +
install \
  +
etcd \
  +
etcd-client \
  +
etcd-server \
  +
etcd-discovery
 
</PRE>
 
</PRE>
  +
  +
<PRE>
  +
dpkg -l | grep etcd
  +
</PRE>
  +
<PRE>
  +
ii etcd 3.3.25+dfsg-7 all Transitional package for etcd-client and etcd-server
  +
ii etcd-client 3.3.25+dfsg-7 arm64 highly-available key value store -- client
  +
ii etcd-discovery 2.0.0+git2019.04.19.git.78fb45d3c9-4 arm64 etcd discovery service
  +
ii etcd-server 3.3.25+dfsg-7 arm64 highly-available key value store -- daemon
  +
</PRE>
  +
  +
Остановить сервис (запускается после установки) <br>
  +
<code>
  +
systemctl stop etcd
  +
</code>
  +
  +
  +
Переместить юнит (свой вариант юнита создается ниже)<br>
  +
<code>
  +
mv /usr/lib/systemd/system/etcd.service /root/etcd.service.original
  +
</code>
  +
  +
=Подготовка SSL сертификатов=
  +
Согласно документации (https://etcd.io/docs/v3.5/op-guide/security/) etcd сертификаты используются в двух независимых настройках:
  +
  +
* Коммуникация между нодами кластера
  +
* Коммуникация между кластером и клиентом
  +
  +
Соответственно есть ТРИ типа сертификатов
  +
* Серверные, которые используются для коммуникации по порту из настройки <code>--listen-peer-urls=https://127.0.0.1:2380 \</code> (127.0.0.1 для примера),
  +
Этот сертификат должен отвечать следующим требованиям:
  +
# Должен быть подписан правильным СА, т.е. вся цепочка доверия должна быть проверяем. Корневой СА для этой цепочки указывается в настройке <code> --peer-trusted-ca-file </code>
  +
# Должен соответствовать домену
  +
# Должен иметь разрешения как для клиентского так и серверного использования '''ext_key_usage'''="ServerAuth,ClientAuth"
  +
  +
  +
* Серверные, которые используются для коммуникации с клиентами (условно назову их "Серверные-Клиентские" )
  +
  +
* Клиентские, которые используются клиентами (например etcdctl) для подключения (условно назову их Клиентские-Клиентские)
  +
  +
=Конфигурация PKI для etcd=
  +
  +
Для получения сертификатов требуется отдельная конфигурация Vault PKI что вынесено в отдельную статью
  +
<BR>
  +
Сначала разобрать настройку PKI: [[Vault_PKI_Intermediate_ca_etcd_Kubernetes_the_hard_way_v2|Пример настройки PKI с подробными пояснениями]]
  +
<BR>
  +
А так же тестовый пользователь и домен [[Vault_PKI_Intermediate_ca_etcd_Roles_and_permissions_Kubernetes_the_hard_way_v2|Roles and Permissions]]
  +
<BR>
  +
Основываясь на примере - настроить следующую конфигурацию
  +
* 3 отдельных ендпоинта, каждый для своего домена
  +
* три отдельных пользователя с разделением прав
  +
  +
  +
=Получение сертификатов для peer-to-peer SSL=
  +
Шаги отдельно описаны в документе [[Vault_PKI_Intermediate_ca_etcd_Roles_and_permissions_for_real_cliuster_Kubernetes_the_hard_way_v2|ETCD PKI]]
  +
но без отдельно разбора каждого шага - эти шаги разобраны для тестового случая.
  +
  +
* на этом шаге можно запустить etcd с peer-to-peer SSL
  +
  +
=Peer-to-Peer SSL=
  +
==Получить на всех трех нодах корневой сертификат==
  +
<PRE>
  +
#!/bin/bash
  +
  +
  +
CERT_NAME=" /etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
echo "-----BEGIN CERTIFICATE-----" > ${CERT_NAME} && \
  +
curl "http://vault.home:8200/v1/k8s_pki_root_ca/ca" | base64 >> ${CERT_NAME} && \
  +
echo "-----END CERTIFICATE-----" >> ${CERT_NAME}
  +
</PRE>
  +
  +
==Стртовый скрипт==
  +
Тут оставлены только значимые на данный момент переменные
  +
* Сертификаты <code>ETCD_PEER_CERT_FILE</code> (разные на всех нодах) выписаны через Vault
  +
* <code>ETCD_PEER_TRUSTED_CA_FILE</code> - корневой СА (не промежуточный СА!)
  +
* Промежуточный СА содержится в сертификате (для того что бы создать цепочку доверия)
  +
  +
===master1===
  +
<PRE>
  +
#!/bin/bash
  +
  +
export ETCD_UNSUPPORTED_ARCH=arm
  +
ETCD_NAME="etcd-az1"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.11.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="http://10.0.11.1:2379,http://127.0.0.1:2379"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az1.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="http://etcd.master.az1.k8s.cluster.home:2379"
  +
ETCD_PROXY="off"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}"
  +
</PRE>
  +
  +
===master2===
  +
<PRE>
  +
#!/bin/bash
  +
  +
export ETCD_UNSUPPORTED_ARCH=arm
  +
ETCD_NAME="etcd-az2"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.21.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="http://10.0.21.1:2379,http://127.0.0.1:2379"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az2.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="http://etcd.master.az2.k8s.cluster.home:2379"
  +
ETCD_PROXY="off"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}"
  +
</PRE>
  +
  +
===master3===
  +
<PRE>
  +
#!/bin/bash
  +
  +
export ETCD_UNSUPPORTED_ARCH=arm
  +
ETCD_NAME="etcd-az3"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.31.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="http://10.0.31.1:2379,http://127.0.0.1:2379"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="http://etcd.master.az3.k8s.cluster.home:2379"
  +
ETCD_PROXY="off"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}"
  +
</PRE>
  +
  +
=Проверка подключения без SSL=
  +
<PRE>
  +
ETCDCTL_API=3 etcdctl --debug --endpoints=http://etcd.master.az1.k8s.cluster.home:2379 member list
  +
</PRE>
  +
  +
  +
Вывод разделен на 2 части - дебаг и собственно вывод команды
  +
* http - подключение ПОКА без шифрования
  +
<PRE>
  +
ETCDCTL_CACERT=
  +
ETCDCTL_CERT=
  +
ETCDCTL_COMMAND_TIMEOUT=5s
  +
ETCDCTL_DEBUG=true
  +
ETCDCTL_DIAL_TIMEOUT=2s
  +
ETCDCTL_DISCOVERY_SRV=
  +
ETCDCTL_ENDPOINTS=[http://etcd.master.az1.k8s.cluster.home:2379]
  +
ETCDCTL_HEX=false
  +
ETCDCTL_INSECURE_DISCOVERY=true
  +
ETCDCTL_INSECURE_SKIP_TLS_VERIFY=false
  +
ETCDCTL_INSECURE_TRANSPORT=true
  +
ETCDCTL_KEEPALIVE_TIME=2s
  +
ETCDCTL_KEEPALIVE_TIMEOUT=6s
  +
ETCDCTL_KEY=
  +
ETCDCTL_USER=
  +
ETCDCTL_WRITE_OUT=simple
  +
WARNING: 2022/10/12 12:51:18 Adjusting keepalive ping interval to minimum period of 10s
  +
WARNING: 2022/10/12 12:51:18 Adjusting keepalive ping interval to minimum period of 10s
  +
INFO: 2022/10/12 12:51:18 parsed scheme: "endpoint"
  +
INFO: 2022/10/12 12:51:18 ccResolverWrapper: sending new addresses to cc: [{http://etcd.master.az1.k8s.cluster.home:2379 <nil> 0 <nil>}]
  +
INFO: 2022/10/12 12:51:18 Subchannel Connectivity change to CONNECTING
  +
INFO: 2022/10/12 12:51:18 Subchannel picks a new address "http://etcd.master.az1.k8s.cluster.home:2379" to connect
  +
INFO: 2022/10/12 12:51:18 Channel Connectivity change to CONNECTING
  +
INFO: 2022/10/12 12:51:18 Subchannel Connectivity change to READY
  +
INFO: 2022/10/12 12:51:18 Channel Connectivity change to READY
  +
</PRE>
  +
<PRE>
  +
54d484c9a805fd2, started, etcd-az1, https://etcd.master.az1.k8s.cluster.home:2380, http://etcd.master.az1.k8s.cluster.home:2379
  +
c19d34eeefb6ae25, started, etcd-az2, https://etcd.master.az2.k8s.cluster.home:2380, http://etcd.master.az2.k8s.cluster.home:2379
  +
e354bb9691207bf1, started, etcd-az3, https://etcd.master.az3.k8s.cluster.home:2380, http://etcd.master.az3.k8s.cluster.home:2379
  +
</PRE>
  +
  +
=Получение сертификатов для "Клиентского" SSL=
  +
Шаги отдельно описаны в документе [[https://noname.com.ua/mediawiki/index.php/Vault_PKI_Intermediate_ca_etcd_Roles_and_permissions_for_real_cliuster_Kubernetes_the_hard_way_v2#.D0.A0.D0.BE.D0.BB.D0.B8_.D0.B8_.D0.BF.D0.BE.D0.BB.D1.8C.D0.B7.D0.BE.D0.B2.D0.B0.D1.82.D0.B5.D0.BB.D0.B8_.D0.B4.D0.BB.D1.8F_client-server_.D1.81.D0.B5.D1.80.D1.82.D0.B8.D1.84.D0.B8.D0.BA.D0.B0.D1.82.D0.BE.D0.B2|ETCD PKI]]
  +
но без отдельно разбора каждого шага - эти шаги разобраны для тестового случая.
  +
  +
* на этом шаге можно запустить etcd с client-server SSL
  +
=Настройка "клиентского" SSL=
  +
Следующий шаг - добавить шифрование клиентских соединений
  +
<BR>
  +
Тут может возникнуть некоторая путаница - есть 2 "клиентских" сертификата
  +
* "клиентский-серверный" - тот что устанавливается на сервере ETCD для того что бы обеспечить SSL клиентам
  +
* "совсем клиентский" - тот с которым авторизуются клиенты
  +
В этом разделе идет речь про установку "клиентского-серверного" сертификата
  +
==Стартовый скрипт==
  +
===master1===
  +
<PRE>
  +
#!/bin/bash
  +
  +
export ETCD_UNSUPPORTED_ARCH=arm
  +
export ETCDCTL_API=3
  +
ETCD_NAME="etcd-az1"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.11.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="https://10.0.11.1:2379"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az1.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az1.k8s.cluster.home:2379"
  +
ETCD_PROXY="off"
  +
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
  +
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
  +
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  +
--cert-file=${ETCD_CERT_FILE} \
  +
--key-file=${ETCD_KEY_FILE} \
  +
--trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  +
--client-cert-auth
  +
</PRE>
  +
  +
===master2===
  +
<PRE>
  +
#!/bin/bash
  +
  +
export ETCD_UNSUPPORTED_ARCH=arm
  +
export ETCDCTL_API=3
  +
ETCD_NAME="etcd-az2"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.21.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="https://10.0.21.1:2379"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az2.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az2.k8s.cluster.home:2379"
  +
ETCD_PROXY="off"
  +
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
  +
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
  +
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  +
--cert-file=${ETCD_CERT_FILE} \
  +
--key-file=${ETCD_KEY_FILE} \
  +
--trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  +
--client-cert-auth
  +
</PRE>
  +
  +
===master3===
  +
<PRE>
  +
#!/bin/bash
  +
  +
export ETCD_UNSUPPORTED_ARCH=arm
  +
export ETCDCTL_API=3
  +
ETCD_NAME="etcd-az3"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.31.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="https://10.0.31.1:2379"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az3.k8s.cluster.home:2379"
  +
ETCD_PROXY="off"
  +
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
  +
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
  +
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
  +
/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  +
--cert-file=${ETCD_CERT_FILE} \
  +
--key-file=${ETCD_KEY_FILE} \
  +
--trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  +
--client-cert-auth
  +
</PRE>
  +
  +
=Проверка подключения с SSL=
  +
==Без клиентского сертификата==
  +
<PRE>
  +
ETCDCTL_API=3 etcdctl --debug --endpoints=https://etcd.master.az1.k8s.cluster.home:2379 member list
  +
</PRE>
  +
Ожидаемо не работает
  +
<PRE>
  +
WARNING: 2022/10/12 17:55:21 grpc: addrConn.createTransport failed to connect to {https://etcd.master.az1.k8s.cluster.home:2379 <nil> 0 <nil>}. Err: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
  +
</PRE>
  +
==Получения сертификата для клиентов==
  +
  +
Получение сертификатов является
  +
[[Vault_PKI_Intermediate_ca_etcd_Roles_and_permissions_for_real_cliuster_Kubernetes_the_hard_way_v2#.D0.A0.D0.BE.D0.BB.D0.B8_.D0.B8_.D0.BF.D0.BE.D0.BB.D1.8C.D0.B7.D0.BE.D0.B2.D0.B0.D1.82.D0.B5.D0.BB.D0.B8_.D0.B4.D0.BB.D1.8F_.D0.BA.D0.BB.D0.B8.D0.B5.D0.BD.D1.82.D1.81.D0.BA.D0.B8.D1.85_.D1.81.D0.B5.D1.80.D1.82.D0.B8.D1.84.D0.B8.D0.BA.D0.B0.D1.82.D0.BE.D0.B2|частью настройки PKI]]
  +
и вынесено в отдельный документ
  +
  +
После получения клиентского сертификата можно проверить работу:
  +
<PRE>
  +
#!/bin/bash
  +
  +
  +
export ETCDCTL_API=3
  +
  +
P="/etc/etcd/certs/client"
  +
ENDPOINT="https://etcd.master.az1.k8s.cluster.home:2379"
  +
  +
etcdctl \
  +
--debug \
  +
--endpoints="${ENDPOINT}" \
  +
--cert=${P}/etcd-client-crt.pem \
  +
--key=${P}/etcd-client-key.pem \
  +
member list
  +
</PRE>
  +
<PRE>
  +
ETCDCTL_CACERT=
  +
ETCDCTL_CERT=/etc/etcd/certs/client/etcd-client-crt.pem
  +
ETCDCTL_COMMAND_TIMEOUT=5s
  +
ETCDCTL_DEBUG=true
  +
ETCDCTL_DIAL_TIMEOUT=2s
  +
ETCDCTL_DISCOVERY_SRV=
  +
ETCDCTL_ENDPOINTS=[https://etcd.master.az1.k8s.cluster.home:2379]
  +
ETCDCTL_HEX=false
  +
ETCDCTL_INSECURE_DISCOVERY=true
  +
ETCDCTL_INSECURE_SKIP_TLS_VERIFY=false
  +
ETCDCTL_INSECURE_TRANSPORT=true
  +
ETCDCTL_KEEPALIVE_TIME=2s
  +
ETCDCTL_KEEPALIVE_TIMEOUT=6s
  +
ETCDCTL_KEY=/etc/etcd/certs/client/etcd-client-key.pem
  +
ETCDCTL_USER=
  +
ETCDCTL_WRITE_OUT=simple
  +
WARNING: 2022/10/12 19:22:28 Adjusting keepalive ping interval to minimum period of 10s
  +
WARNING: 2022/10/12 19:22:28 Adjusting keepalive ping interval to minimum period of 10s
  +
INFO: 2022/10/12 19:22:28 parsed scheme: "endpoint"
  +
INFO: 2022/10/12 19:22:28 ccResolverWrapper: sending new addresses to cc: [{https://etcd.master.az1.k8s.cluster.home:2379 <nil> 0 <nil>}]
  +
INFO: 2022/10/12 19:22:28 Subchannel Connectivity change to CONNECTING
  +
INFO: 2022/10/12 19:22:28 Subchannel picks a new address "https://etcd.master.az1.k8s.cluster.home:2379" to connect
  +
INFO: 2022/10/12 19:22:28 Channel Connectivity change to CONNECTING
  +
INFO: 2022/10/12 19:22:29 Subchannel Connectivity change to READY
  +
INFO: 2022/10/12 19:22:29 Channel Connectivity change to READY
  +
</PRE>
  +
<PRE>
  +
54d484c9a805fd2, started, etcd-az1, https://etcd.master.az1.k8s.cluster.home:2380, https://etcd.master.az1.k8s.cluster.home:2379
  +
c19d34eeefb6ae25, started, etcd-az2, https://etcd.master.az2.k8s.cluster.home:2380, https://etcd.master.az2.k8s.cluster.home:2379
  +
e354bb9691207bf1, started, etcd-az3, https://etcd.master.az3.k8s.cluster.home:2380, https://etcd.master.az3.k8s.cluster.home:2379
  +
</PRE>
  +
  +
=Авторизация на основе сертификатов=
  +
ETCd позволяет использовать CN в качестве имени пользователя а сам сертификат - вместо пароля<br>
  +
  +
==предварительная настройка==
  +
<PRE>
  +
export ETCDCTL_API=3
  +
  +
P="/etc/etcd/certs/client"
  +
ENDPOINT="https://etcd.master.az1.k8s.cluster.home:2379"
  +
  +
ETCDCTL="etcdctl \
  +
--endpoints="${ENDPOINT}" \
  +
--cert=${P}/etcd-client-crt.pem \
  +
--key=${P}/etcd-client-key.pem \
  +
member list "
  +
</PRE>
  +
  +
==Шаги по настройке==
  +
* Создать пользователя root (c паролем, тут ввожу руками)
  +
<PRE>
  +
${ETCDCTL} user add root
  +
</PRE>
  +
* Включить авторизацию
  +
<PRE>
  +
${ETCDCTL} auth enable
  +
</PRE>
  +
* настроить PKI для возможности выписывания сертификатов с произвольным CN (по умолчанию разрешены только валидные хостнеймы)
  +
Это часть [[Vault_PKI_Intermediate_ca_etcd_Roles_and_permissions_for_real_cliuster_Kubernetes_the_hard_way_v2#.D0.A1.D0.B5.D1.80.D1.82.D0.B8.D1.84.D0.B8.D0.BA.D0.B0.D1.82.D1.8B_.D0.B4.D0.BB.D1.8F_.D0.B0.D0.B2.D1.82.D0.BE.D1.80.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D0.B8_.D1.81_.D0.B8.D0.BC.D0.B5.D0.BD.D0.B5.D0.BC_.D0.BF.D0.BE.D0.BB.D1.8C.D0.B7.D0.BE.D0.B2.D0.B0.D1.82.D0.B5.D0.BB.D1.8F_.D0.B2_ETCd|настройки ETCd]]
  +
и вынесено в отдельную секцию
  +
* проверить авторизацию с сертификатом для root (БЕЗ пароля!) Все дальнейшие действия - от рута, с сертификатом
  +
<PRE>
  +
ETCDCTL="etcdctl \
  +
--endpoints="${ENDPOINT}" \
  +
--cert=${P}/root.pem \
  +
--key=${P}/root.key "
  +
  +
  +
  +
echo "---ROLES---"
  +
${ETCDCTL} role list
  +
</PRE>
  +
(ролей еще нет)
  +
  +
* Создать 2 пользователей (для того что бы проверить разделение прав, один из них зарезервирован под аписервер)
  +
<PRE>
  +
echo testuser | ${ETCDCTL} --interactive=false user add testuser
  +
echo kubeapiserver | ${ETCDCTL} --interactive=false user add kubeapiserver
  +
</PRE>
  +
  +
* 2 роли
  +
<PRE>
  +
${ETCDCTL} role add testrole
  +
${ETCDCTL} role add k8s
  +
</PRE>
  +
  +
* дать права для ролей
  +
<PRE>
  +
${ETCDCTL} role grant-permission testrole --prefix=true readwrite /testprefix/
  +
${ETCDCTL} role grant-permission k8s --prefix=true readwrite /k8s
  +
</PRE>
  +
  +
* дать роли пользователям
  +
<PRE>
  +
${ETCDCTL} user grant-role kubeapiserver k8s
  +
${ETCDCTL} user grant-role testuser testrole
  +
</PRE>
  +
* Записать ключ-значение
  +
<PRE>
  +
{ETCDCTL} put /k8s/a c
  +
{ETCDCTL} get /k8s/a
  +
</PRE>
  +
* Дальше переключиться на пользователя kubeapiserver
  +
<PRE>
  +
ETCDCTL="etcdctl \
  +
--endpoints="${ENDPOINT}" \
  +
--cert=${P}/kubeapiserver.pem \
  +
--key=${P}/kubeapiserver.key "
  +
  +
</PRE>
  +
* Проверить запись и чтение
  +
<PRE>
  +
${ETCDCTL} get /k8s/a
  +
  +
${ETCDCTL} put /k8s/a c
  +
  +
${ETCDCTL} get /k8s/a
  +
</PRE>
  +
=Свой systemd-unit=
  +
Мне не очень нравится тот юнит что в комплекте
  +
* изменить права - почти наверняка после тестовых запусков от рута права будут неправильные
  +
<PRE>
  +
chown etcd:etcd /var/lib/etcd/
  +
</PRE>
  +
* лишний симлинк
  +
<PRE>
  +
rm /etc/systemd/system/etcd2.service
  +
</PRE>
  +
* отключить ненужный сервис
  +
<PRE>
  +
systemctl disable etcd-discovery.service
  +
systemctl stop etcd-discovery.service
  +
</PRE>
  +
{{#spoiler:show=/etc/default/etcd (master1)|
  +
<PRE>
  +
ETCD_NAME="etcd-az1"
  +
ETCD_DATA_DIR="/var/lib/etcd/"
  +
# ETCD_WAL_DIR
  +
# ETCD_SNAPSHOT_COUNT="100000"
  +
# ETCD_HEARTBEAT_INTERVAL="100"
  +
# ETCD_ELECTION_TIMEOUT="1000"
  +
ETCD_LISTEN_PEER_URLS="https://10.0.11.1:2380"
  +
ETCD_LISTEN_CLIENT_URLS="https://10.0.11.1:2379"
  +
# ETCD_MAX_SNAPSHOTS="5"
  +
# ETCD_MAX_WALS="5"
  +
# ETCD_CORS
  +
# ETCD_QUOTA_BACKEND_BYTES="0"
  +
# ETCD_BACKEND_BATCH_LIMIT="0"
  +
# ETCD_BACKEND_BATCH_INTERVAL="0"
  +
# ETCD_MAX_TXN_OPS="128"
  +
# ETCD_MAX_REQUEST_BYTES="1572864"
  +
# ETCD_GRPC_KEEPALIVE_MIN_TIME="5"
  +
# ETCD_GRPC_KEEPALIVE_INTERVAL="2h"
  +
# ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
  +
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az1.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
  +
ETCD_INITIAL_CLUSTER_STATE="new"
  +
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
  +
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az1.k8s.cluster.home:2379"
  +
# ETCD_DISCOVERY
  +
# ETCD_DISCOVERY_SRV
  +
# ETCD_DISCOVERY_FALLBACK="proxy"
  +
# ETCD_DISCOVERY_PROXY
  +
# ETCD_STRICT_RECONFIG_CHECK
  +
# ETCD_AUTO_COMPACTION_RETENTION="0"
  +
# ETCD_ENABLE_V2="true"
  +
ETCD_PROXY="off"
  +
# ETCD_PROXY_FAILURE_WAIT="5000"
  +
# ETCD_PROXY_REFRESH_INTERVAL="30000"
  +
# ETCD_PROXY_DIAL_TIMEOUT="1000"
  +
# ETCD_PROXY_WRITE_TIMEOUT="5000"
  +
# ETCD_PROXY_READ_TIMEOUT="0"
  +
# ETCD_CA_FILE
  +
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
  +
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
  +
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
# ETCD_CLIENT_CERT_AUTH
  +
# ETCD_CLIENT_CRL_FILE
  +
# ETCD_AUTO_TLS
  +
#ETCD_PEER_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
  +
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
  +
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
  +
# ETCD_PEER_CLIENT_CERT_AUTH
  +
# ETCD_PEER_CRL_FILE
  +
# ETCD_PEER_AUTO_TLS
  +
# ETCD_PEER_CERT_ALLOWED_CN
  +
# ETCD_CIPHER_SUITES
  +
#+ ETCD_EXPERIMENTAL_PEER_SKIP_CLIENT_SAN_VERIFICATION
  +
# ETCD_LOG_OUTPUTS
  +
# ETCD_DEBUG
  +
# ETCD_LOG_PACKAGE_LEVELS
  +
# ETCD_FORCE_NEW_CLUSTER
  +
</PRE>
  +
}}
  +
  +
<br>
  +
</PRE>
  +
{{#spoiler:show=/etc/default/etcd (master2)|
  +
<PRE>
  +
  +
</PRE>
  +
}}
  +
<br>
  +
</PRE>
  +
{{#spoiler:show=/etc/default/etcd (master3)|
  +
<PRE>
  +
  +
</PRE>
  +
}}
  +
  +
  +
'''/etc/systemd/system/etcd.service'''
  +
<PRE>
  +
[Unit]
  +
Description=etcd - highly-available key value store
  +
Documentation=https://etcd.io/docs
  +
Documentation=man:etcd
  +
After=network.target
  +
Wants=network-online.target
  +
  +
[Service]
  +
LimitNOFILE=65536
  +
Environment=ETCD_UNSUPPORTED_ARCH=arm
  +
Environment=ETCDCTL_API=3
  +
EnvironmentFile=-/etc/default/etcd
  +
Type=notify
  +
User=etcd
  +
PermissionsStartOnly=true
  +
  +
ExecStart=/usr/bin/etcd \
  +
--debug \
  +
--name="${ETCD_NAME}" \
  +
--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  +
--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  +
--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  +
--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  +
--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  +
--initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  +
--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  +
--data-dir="${ETCD_DATA_DIR}" \
  +
--peer-client-cert-auth \
  +
--peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  +
--peer-key-file="${ETCD_PEER_KEY_FILE}" \
  +
--peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  +
--cert-file=${ETCD_CERT_FILE} \
  +
--key-file=${ETCD_KEY_FILE} \
  +
--trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  +
--client-cert-auth
  +
  +
Restart=on-failure
  +
RestartSec=60
  +
  +
[Install]
  +
WantedBy=multi-user.target
  +
Alias=etcd-server.service
  +
</PRE>
  +
  +
<PRE>
  +
systemctl daemon-reload
  +
</PRE>
  +
  +
<PRE>
  +
systemctl restart etcd
  +
systemctl enable etcd
  +
</PRE>
  +
  +
<PRE>
  +
systemctl status etcd
  +
● etcd.service - etcd - highly-available key value store
  +
Loaded: loaded (/etc/systemd/system/etcd.service; enabled; vendor preset: enabled)
  +
Active: active (running) since Thu 2022-10-13 20:26:46 EEST; 2min 33s ago
  +
Docs: https://etcd.io/docs
  +
man:etcd
  +
Main PID: 6972 (etcd)
  +
Tasks: 10 (limit: 9237)
  +
Memory: 25.7M
  +
CPU: 10.563s
  +
CGroup: /system.slice/etcd.service
  +
└─6972 /usr/bin/etcd --debug --name=etcd-az3 --listen-peer-urls=https://10.0.31.1:2380 --listen-client-urls=https://10.0.31.1:2379 --advertise-client-urls=https://etcd.master.az3.k8s.cluster.home:2379 --initial-advertise-peer-urls=https://etcd.master.az3.k8s.cluster.home:2380 >
  +
  +
Oct 13 20:26:46 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:46 Subchannel Connectivity change to CONNECTING
  +
Oct 13 20:26:46 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:46 Subchannel picks a new address "10.0.31.1:2379" to connect
  +
Oct 13 20:26:46 master-az3 etcd[6972]: serving client requests on 10.0.31.1:2379
  +
Oct 13 20:26:46 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:46 Channel Connectivity change to CONNECTING
  +
Oct 13 20:26:47 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:47 Subchannel Connectivity change to READY
  +
Oct 13 20:26:47 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:47 Channel Connectivity change to READY
  +
Oct 13 20:26:49 master-az3 etcd[6972]: established a TCP streaming connection with peer 54d484c9a805fd2 (stream Message writer)
  +
Oct 13 20:26:49 master-az3 etcd[6972]: updated the cluster version from 3.0 to 3.3
  +
Oct 13 20:26:49 master-az3 etcd[6972]: enabled capabilities for version 3.3
  +
Oct 13 20:26:49 master-az3 etcd[6972]: established a TCP streaming connection with peer 54d484c9a805fd2 (stream MsgApp v2 writer)
  +
  +
</PRE>
  +
=Обновление сертификатов=
  +
Можно использовать скрипт или consul-template, но это пока отложено на будущее

Текущая версия на 19:57, 19 января 2023

ETCD

Вторая версия статьи, максимально подробная (первая версия тут - https://noname.com.ua/mediawiki/index.php/Etcd)


Требования к окружению

  • 3 ноды raspberry pi установленные и настроенные, имеющие коннективити друг с другом
  • для работы etcd выделен отдельный VLAN с отдельным адресным пространством
  • установленный и настроенный PKI на основе Hashicorp Vault (в примере - по адресу http://vault.home)
  • Настроенный DNS и созданы записи для всех доменов в примере (в моем случае DNS поднят на MikroTik)

DNS

Подчеркну что все взаимоджействие происходит исключительно по доменным именам
Создаем три записи DNS (для трех мастер-нод каждая из которых находится в своей "Availability Zone" (В кавычках по тому что в лабе это все очень условно)

/ip/dns/static/add name=etcd.master.az1.k8s.cluster.home address=10.0.11.1
/ip/dns/static/add name=etcd.master.az2.k8s.cluster.home address=10.0.21.1
/ip/dns/static/add name=etcd.master.az3.k8s.cluster.home address=10.0.31.1

Описание параметров ETCd

Общие параметры

  • --debug
  • --name=etcd-az-1 Имя ноды кластера - должно быть одним из содержащихся в параметре --initial-cluster На каждой ноде это имя отличается
  • --data-dir=/var/lib/etcd
  • --listen-peer-urls адрес для peer-to-peer коммуникации
  • --listen-client-urls адрес для клиентов (https допустим только при наличии сертификатов)
  • --advertise-client-urls адрес который будет анонсирован для клиентов, тут должно быть доменное имя и оно же должно быть в CN/AltNames что бы можно было валидировать сертификат

Параметры кластера

  • --initial-advertise-peer-urlsАдрес который будет анонсирован для peer-to-peer соединений, тоже домен
  • --initial-cluster-token начальный токен, ЭТОТ ТОКЕН ОБЩИЙ ДЛЯ ВСЕХ НОД иначе вместо одного кластера из 3 нод будет создано три неполных кластера из одной ноды каждый
  • --initial-clusterсписок нод кластера вместе с именами, этот список общий для всех нод и должен быть одинаковый
  • --initial-cluster-state должно быть new для нового кластера

Параметры SSL для peer-to-peer

  • --peer-client-cert-auth требовать SSL (сертификаты всех нод должны быть подписаны одним СА)
  • --peer-cert-file файл сертификата
  • --peer-key-file файл ключа
  • --peer-trusted-ca-fileСА которым подписаны сертификаты для peer-to-peer взаимодействия

Параметры SSL для клиентских подключений

  • --trusted-ca-fileСА которым подписаны клиентские сертификаты
  • --cert-file файл сертификата
  • --key-file файл ключа
  • --client-cert-auth требовать SSL от клиентов (и не разрешать подключения без сертификата)

Установка из пакетов (на всех трех нодах)

Собирать код самой последней версии под архитектуру АРМ откровенно лениво

apt -y \
  install \
    etcd \
    etcd-client \
    etcd-server \
    etcd-discovery
dpkg -l | grep etcd
ii  etcd                            3.3.25+dfsg-7                           all          Transitional package for etcd-client and etcd-server
ii  etcd-client                     3.3.25+dfsg-7                           arm64        highly-available key value store -- client
ii  etcd-discovery                  2.0.0+git2019.04.19.git.78fb45d3c9-4    arm64        etcd discovery service
ii  etcd-server                     3.3.25+dfsg-7                           arm64        highly-available key value store -- daemon

Остановить сервис (запускается после установки)
systemctl stop etcd


Переместить юнит (свой вариант юнита создается ниже)
mv /usr/lib/systemd/system/etcd.service /root/etcd.service.original

Подготовка SSL сертификатов

Согласно документации (https://etcd.io/docs/v3.5/op-guide/security/) etcd сертификаты используются в двух независимых настройках:

  • Коммуникация между нодами кластера
  • Коммуникация между кластером и клиентом

Соответственно есть ТРИ типа сертификатов

  • Серверные, которые используются для коммуникации по порту из настройки --listen-peer-urls=https://127.0.0.1:2380 \ (127.0.0.1 для примера),

Этот сертификат должен отвечать следующим требованиям:

  1. Должен быть подписан правильным СА, т.е. вся цепочка доверия должна быть проверяем. Корневой СА для этой цепочки указывается в настройке --peer-trusted-ca-file
  2. Должен соответствовать домену
  3. Должен иметь разрешения как для клиентского так и серверного использования ext_key_usage="ServerAuth,ClientAuth"


  • Серверные, которые используются для коммуникации с клиентами (условно назову их "Серверные-Клиентские" )
  • Клиентские, которые используются клиентами (например etcdctl) для подключения (условно назову их Клиентские-Клиентские)

Конфигурация PKI для etcd

Для получения сертификатов требуется отдельная конфигурация Vault PKI что вынесено в отдельную статью
Сначала разобрать настройку PKI: Пример настройки PKI с подробными пояснениями
А так же тестовый пользователь и домен Roles and Permissions
Основываясь на примере - настроить следующую конфигурацию

  • 3 отдельных ендпоинта, каждый для своего домена
  • три отдельных пользователя с разделением прав


Получение сертификатов для peer-to-peer SSL

Шаги отдельно описаны в документе ETCD PKI но без отдельно разбора каждого шага - эти шаги разобраны для тестового случая.

  • на этом шаге можно запустить etcd с peer-to-peer SSL

Peer-to-Peer SSL

Получить на всех трех нодах корневой сертификат

#!/bin/bash


CERT_NAME=" /etc/etcd/certs/k8s_root_certificate.pem"

echo "-----BEGIN CERTIFICATE-----"                            >  ${CERT_NAME} && \
curl "http://vault.home:8200/v1/k8s_pki_root_ca/ca" | base64  >> ${CERT_NAME} && \
echo "-----END CERTIFICATE-----"                              >> ${CERT_NAME}

Стртовый скрипт

Тут оставлены только значимые на данный момент переменные

  • Сертификаты ETCD_PEER_CERT_FILE (разные на всех нодах) выписаны через Vault
  • ETCD_PEER_TRUSTED_CA_FILE - корневой СА (не промежуточный СА!)
  • Промежуточный СА содержится в сертификате (для того что бы создать цепочку доверия)

master1

#!/bin/bash

export ETCD_UNSUPPORTED_ARCH=arm
ETCD_NAME="etcd-az1"
ETCD_LISTEN_PEER_URLS="https://10.0.11.1:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.0.11.1:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az1.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd.master.az1.k8s.cluster.home:2379"
ETCD_PROXY="off"
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"

/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}"

master2

#!/bin/bash

export ETCD_UNSUPPORTED_ARCH=arm
ETCD_NAME="etcd-az2"
ETCD_LISTEN_PEER_URLS="https://10.0.21.1:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.0.21.1:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az2.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd.master.az2.k8s.cluster.home:2379"
ETCD_PROXY="off"
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"

/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}"

master3

#!/bin/bash

export ETCD_UNSUPPORTED_ARCH=arm
ETCD_NAME="etcd-az3"
ETCD_LISTEN_PEER_URLS="https://10.0.31.1:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.0.31.1:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd.master.az3.k8s.cluster.home:2379"
ETCD_PROXY="off"
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"

/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}"

Проверка подключения без SSL

ETCDCTL_API=3 etcdctl --debug --endpoints=http://etcd.master.az1.k8s.cluster.home:2379 member list


Вывод разделен на 2 части - дебаг и собственно вывод команды

  • http - подключение ПОКА без шифрования
ETCDCTL_CACERT=
ETCDCTL_CERT=
ETCDCTL_COMMAND_TIMEOUT=5s
ETCDCTL_DEBUG=true
ETCDCTL_DIAL_TIMEOUT=2s
ETCDCTL_DISCOVERY_SRV=
ETCDCTL_ENDPOINTS=[http://etcd.master.az1.k8s.cluster.home:2379]
ETCDCTL_HEX=false
ETCDCTL_INSECURE_DISCOVERY=true
ETCDCTL_INSECURE_SKIP_TLS_VERIFY=false
ETCDCTL_INSECURE_TRANSPORT=true
ETCDCTL_KEEPALIVE_TIME=2s
ETCDCTL_KEEPALIVE_TIMEOUT=6s
ETCDCTL_KEY=
ETCDCTL_USER=
ETCDCTL_WRITE_OUT=simple
WARNING: 2022/10/12 12:51:18 Adjusting keepalive ping interval to minimum period of 10s
WARNING: 2022/10/12 12:51:18 Adjusting keepalive ping interval to minimum period of 10s
INFO: 2022/10/12 12:51:18 parsed scheme: "endpoint"
INFO: 2022/10/12 12:51:18 ccResolverWrapper: sending new addresses to cc: [{http://etcd.master.az1.k8s.cluster.home:2379  <nil> 0 <nil>}]
INFO: 2022/10/12 12:51:18 Subchannel Connectivity change to CONNECTING
INFO: 2022/10/12 12:51:18 Subchannel picks a new address "http://etcd.master.az1.k8s.cluster.home:2379" to connect
INFO: 2022/10/12 12:51:18 Channel Connectivity change to CONNECTING
INFO: 2022/10/12 12:51:18 Subchannel Connectivity change to READY
INFO: 2022/10/12 12:51:18 Channel Connectivity change to READY
54d484c9a805fd2, started, etcd-az1, https://etcd.master.az1.k8s.cluster.home:2380, http://etcd.master.az1.k8s.cluster.home:2379
c19d34eeefb6ae25, started, etcd-az2, https://etcd.master.az2.k8s.cluster.home:2380, http://etcd.master.az2.k8s.cluster.home:2379
e354bb9691207bf1, started, etcd-az3, https://etcd.master.az3.k8s.cluster.home:2380, http://etcd.master.az3.k8s.cluster.home:2379

Получение сертификатов для "Клиентского" SSL

Шаги отдельно описаны в документе [PKI] но без отдельно разбора каждого шага - эти шаги разобраны для тестового случая.

  • на этом шаге можно запустить etcd с client-server SSL

Настройка "клиентского" SSL

Следующий шаг - добавить шифрование клиентских соединений
Тут может возникнуть некоторая путаница - есть 2 "клиентских" сертификата

  • "клиентский-серверный" - тот что устанавливается на сервере ETCD для того что бы обеспечить SSL клиентам
  • "совсем клиентский" - тот с которым авторизуются клиенты

В этом разделе идет речь про установку "клиентского-серверного" сертификата

Стартовый скрипт

master1

#!/bin/bash

export ETCD_UNSUPPORTED_ARCH=arm
export ETCDCTL_API=3
ETCD_NAME="etcd-az1"
ETCD_LISTEN_PEER_URLS="https://10.0.11.1:2380"
ETCD_LISTEN_CLIENT_URLS="https://10.0.11.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az1.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az1.k8s.cluster.home:2379"
ETCD_PROXY="off"
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"

/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  --cert-file=${ETCD_CERT_FILE} \
  --key-file=${ETCD_KEY_FILE} \
  --trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  --client-cert-auth

master2

#!/bin/bash

export ETCD_UNSUPPORTED_ARCH=arm
export ETCDCTL_API=3
ETCD_NAME="etcd-az2"
ETCD_LISTEN_PEER_URLS="https://10.0.21.1:2380"
ETCD_LISTEN_CLIENT_URLS="https://10.0.21.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az2.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az2.k8s.cluster.home:2379"
ETCD_PROXY="off"
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"

/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  --cert-file=${ETCD_CERT_FILE} \
  --key-file=${ETCD_KEY_FILE} \
  --trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  --client-cert-auth

master3

#!/bin/bash

export ETCD_UNSUPPORTED_ARCH=arm
export ETCDCTL_API=3
ETCD_NAME="etcd-az3"
ETCD_LISTEN_PEER_URLS="https://10.0.31.1:2380"
ETCD_LISTEN_CLIENT_URLS="https://10.0.31.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="etcd-az1=https://etcd.master.az1.k8s.cluster.home:2380,etcd-az2=https://etcd.master.az2.k8s.cluster.home:2380,etcd-az3=https://etcd.master.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd.k8s.cluster.home"
ETCD_ADVERTISE_CLIENT_URLS="https://etcd.master.az3.k8s.cluster.home:2379"
ETCD_PROXY="off"
ETCD_CERT_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-crt.pem"
ETCD_KEY_FILE="/etc/etcd/certs/server-to-client/etcd-server-to-client-key.pem"
ETCD_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"
ETCD_PEER_CERT_FILE="/etc/etcd/certs/server/etcd-server-crt.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/certs/server/etcd-server-key.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/certs/k8s_root_certificate.pem"

/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  --cert-file=${ETCD_CERT_FILE} \
  --key-file=${ETCD_KEY_FILE} \
  --trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  --client-cert-auth

Проверка подключения с SSL

Без клиентского сертификата

ETCDCTL_API=3 etcdctl --debug --endpoints=https://etcd.master.az1.k8s.cluster.home:2379 member list

Ожидаемо не работает

WARNING: 2022/10/12 17:55:21 grpc: addrConn.createTransport failed to connect to {https://etcd.master.az1.k8s.cluster.home:2379  <nil> 0 <nil>}. Err: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...

Получения сертификата для клиентов

Получение сертификатов является частью настройки PKI и вынесено в отдельный документ

После получения клиентского сертификата можно проверить работу:

#!/bin/bash


export ETCDCTL_API=3

P="/etc/etcd/certs/client"
ENDPOINT="https://etcd.master.az1.k8s.cluster.home:2379"

etcdctl \
    --debug \
    --endpoints="${ENDPOINT}" \
    --cert=${P}/etcd-client-crt.pem \
    --key=${P}/etcd-client-key.pem \
    member list
ETCDCTL_CACERT=
ETCDCTL_CERT=/etc/etcd/certs/client/etcd-client-crt.pem
ETCDCTL_COMMAND_TIMEOUT=5s
ETCDCTL_DEBUG=true
ETCDCTL_DIAL_TIMEOUT=2s
ETCDCTL_DISCOVERY_SRV=
ETCDCTL_ENDPOINTS=[https://etcd.master.az1.k8s.cluster.home:2379]
ETCDCTL_HEX=false
ETCDCTL_INSECURE_DISCOVERY=true
ETCDCTL_INSECURE_SKIP_TLS_VERIFY=false
ETCDCTL_INSECURE_TRANSPORT=true
ETCDCTL_KEEPALIVE_TIME=2s
ETCDCTL_KEEPALIVE_TIMEOUT=6s
ETCDCTL_KEY=/etc/etcd/certs/client/etcd-client-key.pem
ETCDCTL_USER=
ETCDCTL_WRITE_OUT=simple
WARNING: 2022/10/12 19:22:28 Adjusting keepalive ping interval to minimum period of 10s
WARNING: 2022/10/12 19:22:28 Adjusting keepalive ping interval to minimum period of 10s
INFO: 2022/10/12 19:22:28 parsed scheme: "endpoint"
INFO: 2022/10/12 19:22:28 ccResolverWrapper: sending new addresses to cc: [{https://etcd.master.az1.k8s.cluster.home:2379  <nil> 0 <nil>}]
INFO: 2022/10/12 19:22:28 Subchannel Connectivity change to CONNECTING
INFO: 2022/10/12 19:22:28 Subchannel picks a new address "https://etcd.master.az1.k8s.cluster.home:2379" to connect
INFO: 2022/10/12 19:22:28 Channel Connectivity change to CONNECTING
INFO: 2022/10/12 19:22:29 Subchannel Connectivity change to READY
INFO: 2022/10/12 19:22:29 Channel Connectivity change to READY
54d484c9a805fd2, started, etcd-az1, https://etcd.master.az1.k8s.cluster.home:2380, https://etcd.master.az1.k8s.cluster.home:2379
c19d34eeefb6ae25, started, etcd-az2, https://etcd.master.az2.k8s.cluster.home:2380, https://etcd.master.az2.k8s.cluster.home:2379
e354bb9691207bf1, started, etcd-az3, https://etcd.master.az3.k8s.cluster.home:2380, https://etcd.master.az3.k8s.cluster.home:2379

Авторизация на основе сертификатов

ETCd позволяет использовать CN в качестве имени пользователя а сам сертификат - вместо пароля

предварительная настройка

export ETCDCTL_API=3

P="/etc/etcd/certs/client"
ENDPOINT="https://etcd.master.az1.k8s.cluster.home:2379"

ETCDCTL="etcdctl \
    --endpoints="${ENDPOINT}" \
    --cert=${P}/etcd-client-crt.pem \
    --key=${P}/etcd-client-key.pem \
    member list "

Шаги по настройке

  • Создать пользователя root (c паролем, тут ввожу руками)
${ETCDCTL} user add root
  • Включить авторизацию
${ETCDCTL}  auth enable
  • настроить PKI для возможности выписывания сертификатов с произвольным CN (по умолчанию разрешены только валидные хостнеймы)

Это часть настройки ETCd и вынесено в отдельную секцию

  • проверить авторизацию с сертификатом для root (БЕЗ пароля!) Все дальнейшие действия - от рута, с сертификатом
ETCDCTL="etcdctl \
    --endpoints="${ENDPOINT}" \
    --cert=${P}/root.pem \
    --key=${P}/root.key "



echo "---ROLES---"
${ETCDCTL} role list

(ролей еще нет)

  • Создать 2 пользователей (для того что бы проверить разделение прав, один из них зарезервирован под аписервер)
echo testuser | ${ETCDCTL} --interactive=false  user add testuser
echo kubeapiserver | ${ETCDCTL} --interactive=false  user add kubeapiserver
  • 2 роли
${ETCDCTL} role add testrole
${ETCDCTL} role add k8s
  • дать права для ролей
${ETCDCTL} role grant-permission testrole --prefix=true readwrite /testprefix/
${ETCDCTL} role grant-permission k8s --prefix=true readwrite /k8s
  • дать роли пользователям
${ETCDCTL} user grant-role kubeapiserver  k8s
${ETCDCTL} user grant-role testuser       testrole
  • Записать ключ-значение
{ETCDCTL} put /k8s/a c
{ETCDCTL} get /k8s/a
  • Дальше переключиться на пользователя kubeapiserver
ETCDCTL="etcdctl \
    --endpoints="${ENDPOINT}" \
    --cert=${P}/kubeapiserver.pem \
    --key=${P}/kubeapiserver.key "

  • Проверить запись и чтение
${ETCDCTL}  get  /k8s/a

${ETCDCTL} put /k8s/a c

${ETCDCTL}  get  /k8s/a

Свой systemd-unit

Мне не очень нравится тот юнит что в комплекте

  • изменить права - почти наверняка после тестовых запусков от рута права будут неправильные
chown etcd:etcd /var/lib/etcd/
  • лишний симлинк
rm /etc/systemd/system/etcd2.service
  • отключить ненужный сервис
systemctl disable etcd-discovery.service
systemctl stop  etcd-discovery.service




/etc/systemd/system/etcd.service

[Unit]
Description=etcd - highly-available key value store
Documentation=https://etcd.io/docs
Documentation=man:etcd
After=network.target
Wants=network-online.target

[Service]
LimitNOFILE=65536
Environment=ETCD_UNSUPPORTED_ARCH=arm
Environment=ETCDCTL_API=3
EnvironmentFile=-/etc/default/etcd
Type=notify
User=etcd
PermissionsStartOnly=true

ExecStart=/usr/bin/etcd \
  --debug \
  --name="${ETCD_NAME}" \
  --listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" \
  --listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" \
  --advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" \
  --initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" \
  --initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" \
  --initial-cluster="${ETCD_INITIAL_CLUSTER}" \
  --initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}" \
  --data-dir="${ETCD_DATA_DIR}" \
  --peer-client-cert-auth \
  --peer-cert-file="${ETCD_PEER_CERT_FILE}" \
  --peer-key-file="${ETCD_PEER_KEY_FILE}" \
  --peer-trusted-ca-file="${ETCD_PEER_TRUSTED_CA_FILE}" \
  --cert-file=${ETCD_CERT_FILE} \
  --key-file=${ETCD_KEY_FILE} \
  --trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
  --client-cert-auth

Restart=on-failure
RestartSec=60

[Install]
WantedBy=multi-user.target
Alias=etcd-server.service
systemctl daemon-reload
systemctl restart etcd
systemctl enable etcd
systemctl status etcd
● etcd.service - etcd - highly-available key value store
     Loaded: loaded (/etc/systemd/system/etcd.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-10-13 20:26:46 EEST; 2min 33s ago
       Docs: https://etcd.io/docs
             man:etcd
   Main PID: 6972 (etcd)
      Tasks: 10 (limit: 9237)
     Memory: 25.7M
        CPU: 10.563s
     CGroup: /system.slice/etcd.service
             └─6972 /usr/bin/etcd --debug --name=etcd-az3 --listen-peer-urls=https://10.0.31.1:2380 --listen-client-urls=https://10.0.31.1:2379 --advertise-client-urls=https://etcd.master.az3.k8s.cluster.home:2379 --initial-advertise-peer-urls=https://etcd.master.az3.k8s.cluster.home:2380 >

Oct 13 20:26:46 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:46 Subchannel Connectivity change to CONNECTING
Oct 13 20:26:46 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:46 Subchannel picks a new address "10.0.31.1:2379" to connect
Oct 13 20:26:46 master-az3 etcd[6972]: serving client requests on 10.0.31.1:2379
Oct 13 20:26:46 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:46 Channel Connectivity change to CONNECTING
Oct 13 20:26:47 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:47 Subchannel Connectivity change to READY
Oct 13 20:26:47 master-az3 etcd[6972]: INFO: 2022/10/13 20:26:47 Channel Connectivity change to READY
Oct 13 20:26:49 master-az3 etcd[6972]: established a TCP streaming connection with peer 54d484c9a805fd2 (stream Message writer)
Oct 13 20:26:49 master-az3 etcd[6972]: updated the cluster version from 3.0 to 3.3
Oct 13 20:26:49 master-az3 etcd[6972]: enabled capabilities for version 3.3
Oct 13 20:26:49 master-az3 etcd[6972]: established a TCP streaming connection with peer 54d484c9a805fd2 (stream MsgApp v2 writer)

Обновление сертификатов

Можно использовать скрипт или consul-template, но это пока отложено на будущее