Product SiteDocumentation Site

56.3. Настройка HA-кластера etcd с помощью kubeadm

В данном примере рассматривается процесс создания HA-кластера etcd состоящего из трех узлов, который можно использовать в качестве внешнего etcd при использовании kubeadm для настройки кластера kubernetes.
Рекомендации:
  • три хоста, которые могут общаться друг с другом через порты 2379 и 2380;
  • на каждом хосте должны быть установлены docker, kubelet и kubeadm;
  • каждый хост должен иметь доступ к реестру образов контейнера Kubernetes (k8s.gcr.io) или выводить/извлекать требуемый образ etcd с помощью kubeadm config images list/pull;
  • между хостами должна быть настроена возможность копирования файлов, например ssh и scp.
Основная идея при таком способе настройки кластера, состоит в том, чтобы генерировать все сертификаты на одном узле и распространять только необходимые файлы на другие узлы.

Примечание

kubeadm содержит все необходимое криптографические механизмы для создания сертификатов, никаких других криптографических инструментов для данного примера не требуется.
Настройка kubernetes:
  1. Настроить kubelet в качестве диспетчера служб для etcd.
    Так как etcd был создан первым, необходимо переопределить приоритет службы, создав новый файл модуля с более высоким приоритетом, чем предоставленный kubeadm файл модуля kubelet (на каждом хосте, на котором должен быть запущен etcd):
    # cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
    [Service]
    ExecStart=
    #  Replace "systemd" with the cgroup driver of your container runtime.
    #  The default value in the kubelet is "cgroupfs".
    ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd
    Restart=always
    EOF
    
    # systemctl daemon-reload
    # systemctl restart kubelet
    
    Убедиться, что kubelet запущен:
    # systemctl status kubelet
    
  2. Создать файлы конфигурации для kubeadm.
    Создать и запустить скрипт, который сгенерирует файлы конфигурации для каждого хоста. Содержимое скрипта:
    #!/bin/sh
    # HOST0, HOST1, и HOST2 - IP-адреса хостов
    export HOST0=192.168.0.201
    export HOST1=192.168.0.205
    export HOST2=192.168.0.206
    
    # Create temp directories to store files that will end up on other hosts.
    mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/
    
    ETCDHOSTS=(${HOST0} ${HOST1} ${HOST2})
    NAMES=("infra0" "infra1" "infra2")
    
    for i in "${!ETCDHOSTS[@]}"; do
    HOST=${ETCDHOSTS[$i]}
    NAME=${NAMES[$i]}
    cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
    apiVersion: "kubeadm.k8s.io/v1beta2"
    kind: ClusterConfiguration
    etcd:
    local:
        serverCertSANs:
        - "${HOST}"
        peerCertSANs:
        - "${HOST}"
        extraArgs:
            initial-cluster: ${NAMES[0]}=https://${ETCDHOSTS[0]}:2380,${NAMES[1]}=https://${ETCDHOSTS[1]}:2380,${NAMES[2]}=https://${ETCDHOSTS[2]}:2380
            initial-cluster-state: new
            name: ${NAME}
            listen-peer-urls: https://${HOST}:2380
            listen-client-urls: https://${HOST}:2379
            advertise-client-urls: https://${HOST}:2379
            initial-advertise-peer-urls: https://${HOST}:2380
    EOF
    done
    
  3. Создать центр сертификации (CA).

    Примечание

    Если у вас уже есть CA, то необходимо скопировать сертификат (crt) и ключ CA в /etc/kubernetes/pki/etcd/ca.crt и /etc/kubernetes/pki/etcd/ca.key. После этого можно перейти к следующему шагу.
    Если у вас еще нет CA, следует запустить команду на хосте $HOST0 (там, где были сгенерированы файлы конфигурации для kubeadm):
    # kubeadm init phase certs etcd-ca
    [certs] Generating "etcd/ca" certificate and key
    
    При этом будут созданы два файла: /etc/kubernetes/pki/etcd/ca.crt и /etc/kubernetes/pki/etcd/ca.key.
  4. Создать сертификаты для каждого хоста.
    Для этого создать и запустить скрипт (на хосте $HOST0):
    #!/bin/sh
    export HOST0=192.168.0.201
    export HOST1=192.168.0.205
    export HOST2=192.168.0.206
    
    kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
    kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
    cp -R /etc/kubernetes/pki /tmp/${HOST1}/
    # cleanup non-reusable certificates
    find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
    
    kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
    kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
    cp -R /etc/kubernetes/pki /tmp/${HOST2}/
    find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
    
    kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
    kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
    # No need to move the certs because they are for HOST0
    
    # clean up certs that should not be copied off this host
    find /tmp/${HOST2} -name ca.key -type f -delete
    find /tmp/${HOST1} -name ca.key -type f -delete
    
  5. Скопировать сертификаты и файлы конфигурации kubeadm на хосты.
    scp /tmp/${HOST}/kubeadmcfg.yaml user@${HOST}:
    scp -r /tmp/${HOST}/pki root@${HOST}:/etc/kubernetes/
    
    В данном примере:
    # scp /tmp/192.168.0.205/kubeadmcfg.yaml user@192.168.0.205:
    # scp -r /tmp/192.168.0.205/pki root@192.168.0.205:/etc/kubernetes/
    
  6. Должны существовать следующие файлы:
    • на хосте $HOST0 (там, где были сгенерированы файлы конфигурации для kubeadm и сертификаты):
      /tmp/${HOST0}
      └── kubeadmcfg.yaml
      ---
      /etc/kubernetes/pki
      ├── apiserver-etcd-client.crt
      ├── apiserver-etcd-client.key
      └── etcd
      ├── ca.crt
      ├── ca.key
      ├── healthcheck-client.crt
      ├── healthcheck-client.key
      ├── peer.crt
      ├── peer.key
      ├── server.crt
      └── server.key
      
    • на хосте $HOST1:
      $HOME
      └── kubeadmcfg.yaml
      ---
      /etc/kubernetes/pki
      ├── apiserver-etcd-client.crt
      ├── apiserver-etcd-client.key
      └── etcd
      ├── ca.crt
      ├── healthcheck-client.crt
      ├── healthcheck-client.key
      ├── peer.crt
      ├── peer.key
      ├── server.crt
      └── server.key
      
    • на хосте $HOST2:
      $HOME
      └── kubeadmcfg.yaml
      ---
      /etc/kubernetes/pki
      ├── apiserver-etcd-client.crt
      ├── apiserver-etcd-client.key
      └── etcd
      ├── ca.crt
      ├── healthcheck-client.crt
      ├── healthcheck-client.key
      ├── peer.crt
      ├── peer.key
      ├── server.crt
      └── server.key
      
  7. Создать статические манифесты модуля.
    На каждом хосте запустить команду kubeadm, чтобы сгенерировать статический манифест для etcd:
    root@HOST0# kubeadm init phase etcd local –config=/tmp/192.168.0.201/kubeadmcfg.yaml
    [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
    
    root@HOST1# kubeadm init phase etcd local --config=/home/user/kubeadmcfg.yaml
    [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
    
    root@HOST2# kubeadm init phase etcd local --config=/home/user/kubeadmcfg.yaml
    [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"