Kubernetes the hard way etcd setup
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<br> /ip/dns/static/add name=etcd.master.az2.k8s.cluster.home address=10.0.21.1<br> /ip/dns/static/add name=etcd.master.az3.k8s.cluster.home address=10.0.31.1<br>
Описание параметров 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 для примера),
Этот сертификат должен отвечать следующим требованиям:
- Должен быть подписан правильным СА, т.е. вся цепочка доверия должна быть проверяем. Корневой СА для этой цепочки указывается в настройке
--peer-trusted-ca-file
- Должен соответствовать домену
- Должен иметь разрешения как для клиентского так и серверного использования 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, но это пока отложено на будущее