Kubernetes the hard way etcd setup: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
Строка 525: | Строка 525: | ||
Это часть [[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]] |
Это часть [[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 (БЕЗ пароля!) |
+ | * проверить авторизацию с сертификатом для root (БЕЗ пароля!) Все дальнейшие действия - от рута, с сертификатом |
<PRE> |
<PRE> |
||
ETCDCTL="etcdctl \ |
ETCDCTL="etcdctl \ |
||
Строка 538: | Строка 538: | ||
</PRE> |
</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> |
||
+ | =Обновление сертификатов= |
||
+ | Можно использовать скрипт или consul-template, но это пока отложено на будущее |
Версия 18:36, 13 октября 2022
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
Обновление сертификатов
Можно использовать скрипт или consul-template, но это пока отложено на будущее