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

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 590: Строка 590:
 
</PRE>
 
</PRE>
   
{{#spoiler:show=/etc/default/etcd (master1)|
+
{{#spoiler:show=/etc/default/etcd|
 
<PRE>
 
<PRE>
 
ETCD_NAME="etcd-az1"
 
ETCD_NAME="etcd-az1"

Версия 19:01, 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 для примера),

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

  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/

{{#spoiler:show=/etc/default/etcd|

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
}}

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

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