Перейти к основному содержимому

5.3.2. Аутентификация

Ниже два рабочих сценария подключения worker-ноды к кластеру. Первый дает полный контроль над bootstrap-процессом, второй повторяет привычный путь через kubeadm join.

Это ручной сценарий: создаем bootstrap-kubelet.conf, запускаем kubelet и при необходимости сами проводим CSR через Kubernetes API. Подходит, если хотите видеть весь путь TLS Bootstrap без автоматики kubeadm.

Внимание

В примере ниже используется статичный bootstrap-токен для всех worker-узлов. Для production-среды лучше выпускать отдельный токен на каждую ноду и задавать ему ограниченный срок жизни.

Создание bootstrap-токена

Bootstrap-токен хранится в Secret в namespace kube-system и дает новой ноде право начать bootstrap-процесс. Ниже два способа его создать.

🖥️ Мастер-нода

Команды ниже выполняются на мастер-ноде или на хосте с kubeconfig, имеющим права на создание Secret в namespace kube-system.

Переменные окружения

export AUTH_EXTRA_GROUPS="system:bootstrappers:kubeadm:default-node-token"
export DESCRIPTION="kubeadm bootstrap token"
export EXPIRATION=$(date -d '24 hours' "+%Y-%m-%dT%H:%M:%SZ")
export TOKEN_ID="fjt9ex"
export TOKEN_SECRET="lwzqgdlvoxtqk4yw"
export USAGE_BOOTSTRAP_AUTHENTIFICATION="true"
export USAGE_BOOTSTRAP_SIGNING="true"

Создание Secret

kubectl \
--kubeconfig=/etc/kubernetes/super-admin.conf \
apply -f - <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: bootstrap-token-${TOKEN_ID}
namespace: kube-system
data:
auth-extra-groups: $(echo -n "$AUTH_EXTRA_GROUPS" | base64)
description: $(echo -n "$DESCRIPTION" | base64)
expiration: $(echo -n "$EXPIRATION" | base64)
token-id: $(echo -n "$TOKEN_ID" | base64)
token-secret: $(echo -n "$TOKEN_SECRET" | base64)
usage-bootstrap-authentication: $(echo -n "$USAGE_BOOTSTRAP_AUTHENTIFICATION" | base64)
usage-bootstrap-signing: $(echo -n "$USAGE_BOOTSTRAP_SIGNING" | base64)
type: bootstrap.kubernetes.io/token
EOF

Создание bootstrap-kubelet.conf

🖥️ Worker-нода

Все команды данного этапа выполняются на worker-ноде. На worker-ноде файл ca.crt еще отсутствует. CA-данные получаем из публичного ConfigMap cluster-info в namespace kube-public, доступного анонимно через kube-apiserver.

Переменные окружения

export BOOTSTRAP_TOKEN=fjt9ex.lwzqgdlvoxtqk4yw
export API_SERVER="https://api.my-first-cluster.example.com:6443"

Рабочая директория

mkdir -p /etc/kubernetes

Получение CA из cluster-info

export CA_DATA=$(curl -sk "${API_SERVER}/api/v1/namespaces/kube-public/configmaps/cluster-info" | \
jq -r '.data.kubeconfig' | \
grep 'certificate-authority-data' | \
awk '{print $2}')

Сохранение CA-сертификата

mkdir -p /etc/kubernetes/pki
echo "${CA_DATA}" | base64 -d > /etc/kubernetes/pki/ca.crt

Генерация kubeconfig

cat <<EOF > /etc/kubernetes/bootstrap-kubelet.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${CA_DATA}
server: ${API_SERVER}
name: my-first-cluster
contexts:
- context:
cluster: my-first-cluster
user: tls-bootstrap-token-user
name: tls-bootstrap-token-user@kubernetes
current-context: tls-bootstrap-token-user@kubernetes
kind: Config
preferences: {}
users:
- name: tls-bootstrap-token-user
user:
token: ${BOOTSTRAP_TOKEN}
EOF

Kubernetes CSR (имитация TLS Bootstrap)

Ниже показан тот же поток, который kubelet обычно проходит сам во время TLS Bootstrap: ключи генерируются на worker-ноде, CSR отправляются через Kubernetes API, а подпись подтверждает администратор на мастер-ноде. Приватный ключ CA на worker-ноде для этого не нужен.

Kubelet Client Certificate (CSR)

● Обязателен к применению

Назначение: Клиентский сертификат kubelet для подключения к kube-apiserver.

1. Генерация ключа и CSR

🖥️ Worker-нода

Все команды данного этапа выполняются на worker-ноде.

export HOST_NAME=worker-1
export CLUSTER_NAME="my-first-cluster"
export BASE_DOMAIN="example.com"
export FULL_HOST_NAME="${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}"
mkdir -p /var/lib/kubelet/pki
mkdir -p /etc/kubernetes/openssl/csr
cat <<EOF > /etc/kubernetes/openssl/kubelet-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[ dn ]
CN = system:node:${FULL_HOST_NAME}
O = system:nodes

[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
openssl genrsa \
-out /var/lib/kubelet/pki/kubelet-client-key.pem 2048
openssl req -new \
-key /var/lib/kubelet/pki/kubelet-client-key.pem \
-out /etc/kubernetes/openssl/csr/kubelet-client.csr \
-config /etc/kubernetes/openssl/kubelet-client.conf

2. Отправка CSR в Kubernetes API

🖥️ Worker-нода

Worker-нода аутентифицируется bootstrap-токеном через bootstrap-kubelet.conf.

export HOST_NAME=worker-1
export CSR_NAME="${HOST_NAME}-kubelet-client"
export CSR_CONTENT=$(cat /etc/kubernetes/openssl/csr/kubelet-client.csr | base64 | tr -d '\n')
kubectl \
--kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
apply -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${CSR_NAME}
spec:
request: ${CSR_CONTENT}
signerName: kubernetes.io/kube-apiserver-client-kubelet
usages:
- digital signature
- key encipherment
- client auth
EOF

3. Утверждение CSR

🖥️ Мастер-нода

Утверждение CSR выполняется на мастер-ноде. Укажите имя worker-ноды, для которой утверждается CSR.

export HOST_NAME=worker-1
export CSR_NAME="${HOST_NAME}-kubelet-client"
kubectl \
--kubeconfig=/etc/kubernetes/super-admin.conf \
certificate approve ${CSR_NAME}

4. Получение подписанного сертификата

🖥️ Worker-нода

Сертификат получаем на worker-ноде с использованием bootstrap-kubelet.conf.

export HOST_NAME=worker-1
export CSR_NAME="${HOST_NAME}-kubelet-client"
kubectl \
--kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
get csr ${CSR_NAME} \
-o jsonpath='{.status.certificate}' | base64 -d > /var/lib/kubelet/pki/kubelet-client.pem
cat /var/lib/kubelet/pki/kubelet-client.pem /var/lib/kubelet/pki/kubelet-client-key.pem > /var/lib/kubelet/pki/kubelet-client-$(date '+%Y-%m-%d-%H-%M-%S').pem
ln -sf /var/lib/kubelet/pki/kubelet-client-$(date '+%Y-%m-%d-%H-%M-%S').pem /var/lib/kubelet/pki/kubelet-client-current.pem

Kubelet Server Certificate (CSR)

● Обязателен к применению

Назначение: Серверный сертификат kubelet для TLS на порту 10250.

1. Генерация ключа и CSR

🖥️ Worker-нода

Все команды данного этапа выполняются на worker-ноде.

export HOST_NAME=worker-1
export CLUSTER_NAME="my-first-cluster"
export BASE_DOMAIN="example.com"
export FULL_HOST_NAME="${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}"
export MACHINE_LOCAL_ADDRESS="$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)"
mkdir -p /var/lib/kubelet/pki
mkdir -p /etc/kubernetes/openssl/csr
cat <<EOF > /etc/kubernetes/openssl/kubelet-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}

[ dn ]
CN = system:node:${FULL_HOST_NAME}
O = system:nodes

[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
openssl genrsa \
-out /var/lib/kubelet/pki/kubelet-server-key.pem 2048
openssl req -new \
-key /var/lib/kubelet/pki/kubelet-server-key.pem \
-out /etc/kubernetes/openssl/csr/kubelet-server.csr \
-config /etc/kubernetes/openssl/kubelet-server.conf

2. Отправка CSR в Kubernetes API

🖥️ Worker-нода

Worker-нода аутентифицируется bootstrap-токеном через bootstrap-kubelet.conf.

export HOST_NAME=worker-1
export CSR_NAME="${HOST_NAME}-kubelet-server"
export CSR_CONTENT=$(cat /etc/kubernetes/openssl/csr/kubelet-server.csr | base64 | tr -d '\n')
kubectl \
--kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
apply -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${CSR_NAME}
spec:
request: ${CSR_CONTENT}
signerName: kubernetes.io/kubelet-serving
usages:
- digital signature
- key encipherment
- server auth
EOF

3. Утверждение CSR

🖥️ Мастер-нода

Утверждение CSR выполняется на мастер-ноде. Укажите имя worker-ноды, для которой утверждается CSR.

export HOST_NAME=worker-1
export CSR_NAME="${HOST_NAME}-kubelet-server"
kubectl \
--kubeconfig=/etc/kubernetes/super-admin.conf \
certificate approve ${CSR_NAME}

4. Получение подписанного сертификата

🖥️ Worker-нода

Сертификат получаем на worker-ноде с использованием bootstrap-kubelet.conf.

export HOST_NAME=worker-1
export CSR_NAME="${HOST_NAME}-kubelet-server"
kubectl \
--kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
get csr ${CSR_NAME} \
-o jsonpath='{.status.certificate}' | base64 -d > /var/lib/kubelet/pki/kubelet-server.pem
cat /var/lib/kubelet/pki/kubelet-server.pem /var/lib/kubelet/pki/kubelet-server-key.pem > /var/lib/kubelet/pki/kubelet-server-$(date '+%Y-%m-%d-%H-%M-%S').pem
ln -sf /var/lib/kubelet/pki/kubelet-server-$(date '+%Y-%m-%d-%H-%M-%S').pem /var/lib/kubelet/pki/kubelet-server-current.pem