Kubernetes the hard way etcd setup

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску

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>

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

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

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}

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

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

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

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

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

Проверка подключения без 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

Systemd unit

/etc/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/coreos

[Service]
Type=notify
LimitNOFILE=65536
Environment=ETCD_UNSUPPORTED_ARCH=arm64
EnvironmentFile=/etc/etcd/env
ExecStart=/usr/bin/etcd \
                --debug \
                --name=etcd-az-1 \
                --listen-peer-urls=https://10.240.1.2:2380 \
                --listen-client-urls=https://10.240.1.2:2379,https://127.0.0.1:2379 \
                --advertise-client-urls=https://etcd.az1.k8s.home:2379 \
                --initial-advertise-peer-urls=https://etcd.az1.k8s.home:2380 \
                --initial-cluster-token=etcd.az1.k8s.home \
                --initial-cluster etcd-az-1=https://etcd.az1.k8s.home:2380,etcd-az-2=https://etcd.az2.k8s.home:2380,etcd-az-3=https://etcd.az3.k8s.home:2380 \
                --initial-cluster-state=new \
                --data-dir=/var/lib/etcd \
                --peer-client-cert-auth \
                --peer-cert-file=/etc/etcd/certs/server/etcd.az1.k8s.home.pem \
                --peer-key-file=/etc/etcd/certs/server/etcd.az1.k8s.home.key \
                --peer-trusted-ca-file=/etc/etcd/certs/rootCA.pem \
                --trusted-ca-file=/etc/etcd/certs/rootCA.pem \
                --cert-file=/etc/etcd/certs/client/etcd.az1.k8s.home.pem \
                --key-file=/etc/etcd/certs/client/etcd.az1.k8s.home.key \
                --client-cert-auth

Restart=on-failure
RestartSec=60

[Install]
WantedBy=multi-user.target
Alias=etcd-server.service


ETCD_NAME="etcd.master.az3.k8s.cluster.home"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_SNAPSHOT_COUNT="100000"
ETCD_HEARTBEAT_INTERVAL="100"
ETCD_ELECTION_TIMEOUT="1000"
ETCD_LISTEN_PEER_URLS="http://localhost:2380"
ETCD_LISTEN_CLIENT_URLS="https://10.0.31.1/2379,http://localhost:2379"
ETCD_MAX_SNAPSHOTS="5"
ETCD_MAX_WALS="5"
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.az3.k8s.cluster.home:2380"
ETCD_INITIAL_CLUSTER="default=http://localhost:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
ETCD_STRICT_RECONFIG_CHECK
ETCD_AUTO_COMPACTION_RETENTION="0"
ETCD_CERT_FILE
ETCD_KEY_FILE
ETCD_CLIENT_CERT_AUTH
ETCD_TRUSTED_CA_FILE
ETCD_PEER_CERT_FILE
ETCD_PEER_KEY_FILE
ETCD_PEER_CLIENT_CERT_AUTH
ETCD_PEER_TRUSTED_CA_FILE
ETCD_PEER_CERT_ALLOWED_CN=
ETCD_DEBUG
ETCD_LOG_PACKAGE_LEVELS=etcdserver=WARNING,security=DEBUG