Хочу рассказать об интересном эксперименте, суть которого заключалась в развертывании и настройке Kubernetes на двух старых ноутбуках — один из них, кроме того, был с процессором на архитектуре i386. В качестве теоретической основы использовалось руководство Kubernetes The Hard Way, которое по ходу дела пришлось немного доработать, а в качестве системы на хостах — Gentoo (да, вам не показалось). Давайте погрузимся в этот увлекательный хардкор!
Наверное, многие слышали про полезный и по-своему легендарный репозиторий Келси Хайтауэра — Kubernetes The Hard Way, инструкцию по развертыванию кластера K8s без готовых скриптов и утилит. В ней объясняется, как вручную запустить Kubernetes на Google Cloud Platform (GCP). Но даже сам автор утверждает, что стоимость такого кластера будет больше, чем 300 USD, которые даются в подарок за регистрацию на сервисе.
А что, если у вас есть один или несколько старых ноутбуков, которые пылятся на полке, и вы хотите поднять-таки Kubernetes своими руками и бесплатно?
Попробуем!
Важно: эту статью стоит воспринимать лишь как дополнение к оригинальному руководству Келси Хайтауэра, так как практически всё, что им описывается, применимо не только к GCP, но и к любому другому железу или виртуальным машинам, хотя и с некоторыми оговорками.
Исходные данные
Для экспериментов у меня было два ноутбука на базе Gentoo Linux:
-
Dell G3 3590 на базе Intel Core i5-9300H (архитектура AMD64) (далее — просто dell);
-
HP Compaq 6720s на базе Intel Core2 Duo (архитектура i686) (далее — hpcom).
Они стали узлами кластера. Операционная система ставилась по официальной документации для amd64 и x32. Но ядро собиралось с несколькими дополнительными настройками для IPSet и Docker. Для kube-proxy были включены параметры ядра NETFILTER_XT_MATCH_COMMENT
и NETFILTER_XT_MATCH_STATISTIC
. Также в процессе установки я столкнулся с парой трудностей, решить которые помог форум сообщества Gentoo. На всякий случай оставлю ссылки: черный экран сразу после GRUB и ошибка с non-PAE kernel.
Что еще:
-
самый обычный роутер от провайдера;
-
основной ноутбук, с которого удаленно проводились все работы;
-
сильное желание повозиться с Kubernetes.
Как правильно пользоваться руководством
Выше я отметил, что внес лишь небольшие правки в оригинальное руководство по Kubernetes. Поэтому еще раз подчеркну, что в статье описываю только эти правки, указывая места, где нужно отступить от исходных инструкций. В остальных случаях даю ссылки на оригинальные разделы руководства.
Установка Kubernetes
Prerequisites
В этом разделе ничего не делаем, поэтому его можно со спокойной душой пропустить.
Installing the Client Tools
Здесь никаких изменений: делаем так, как написано.
Provisioning Compute Resources
Эту страницу официального руководства можно пропустить, а вместо нее для упрощения дальнейшей работы записать локальные IP-адреса будущих узлов кластера (у меня получилось так: hpcom — 192.168.1.71
, dell — 192.168.1.253
).
Для удобства запишем эти адреса в файлик node_list.txt
:
cat <<EOF | tee node_list.txt
dell 192.168.1.253 # Поменять на свои адреса и имена
hpcom 192.168.1.71
EOF
Для имитации Load Balancer’а на рабочей машине можно установить и развернуть NGINX. Затем добавить в конце конфигурационного файла nginx.conf
строку include passthrough.conf
(на Linux стандартная директория для конфигов NGINX — /etc/nginx/
, а на macOS при установке через brew — /opt/homebrew/etc/
).
Далее рядом создаем файл passthrough.conf
. Сделать это можно такой командой (не забудьте поменять путь до NGINX-директории и путь до файла с хостами на ваши):
cat <<EOF | tee /opt/homebrew/etc/nginx/passthrough.conf
stream {
upstream kube {
$(cat node_list.txt | cut -d" " -f2 | xargs -I{} echo "$(printf '%8s')server {}:6443;")
}
server {
listen 443;
proxy_pass kube;
proxy_next_upstream on;
}
}
EOF
Это поможет нам создать простейшую имитацию High-Availability-кластера (HA). Для обучения большего и не нужно.
Provisioning a CA and Generating TLS Certificates
В этом разделе выполняем все в точности до пункта The Kubelet Client Certificates. Теперь нам пригодятся записанные ранее IP-адреса узлов будущего кластера:
for instance in $(cat node_list.txt | cut -d" " -f1); do
cat > ${instance}-csr.json <<EOF
{
"CN": "system:node:${instance}",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:nodes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
INTERNAL_IP=$(cat node_list.txt | grep $instance | cut -d" " -f2)
cfssl gencert
-ca=ca.pem
-ca-key=ca-key.pem
-config=ca-config.json
-hostname=${instance},${INTERNAL_IP},127.0.0.1
-profile=kubernetes
${instance}-csr.json | cfssljson -bare ${instance}
done
Далее идем по исходной инструкции вплоть до пункта The Kubernetes API Server Certificate. Здесь меняем вводимые строки на такие:
{
KUBERNETES_HOSTNAMES=kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.svc.cluster.local
cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert
-ca=ca.pem
-ca-key=ca-key.pem
-config=ca-config.json
-hostname=$(cut -d" " -f2 node_list.txt| tr 'n' ',')127.0.0.1,${KUBERNETES_HOSTNAMES}
-profile=kubernetes
kubernetes-csr.json | cfssljson -bare kubernetes
}
В следующем разделе, The Service Account Key Pair, выполняем все по инструкции, а в Distribute the Client and Server Certificates просто разносим все нужное по узлам с помощью scp. Чтобы это заработало, на рабочей машине создаем файл ~/.ssh/config
с помощью команды:
cat node_list.txt | xargs -n2 bash -c 'echo -e "Host $0ntHostname $1ntUser <Ваш пользователь на узлах>"' | tee ~/.ssh/config
Копируем файлы на узлы:
{
for instance in $(cut -d" " -f1 node_list.txt); do
scp node_list.txt ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem service-account-key.pem service-account.pem ca.pem ${instance}-key.pem ${instance}.pem node_list.txt # Также переносим файл с IP-адресами на все узлы для дальнейшей работы.
${instance}:~/
done
}
В моем случае оба ноутбука будут выступать в качестве master’а и рабочего узла одновременно, поэтому я скопировал на них не только сертификаты для control plane, но и для рабочих узлов.
Generating Kubernetes Configuration Files for Authentication
Здесь пропускаем пункт про Kubernetes Public IP Address, а в The kubelet Kubernetes Configuration File вместо исходной команды выполняем:
for instance in $(cat node_list.txt | cut -d" " -f1); do
kubectl config set-cluster kubernetes-the-hard-way
--certificate-authority=ca.pem
--embed-certs=true
--server=https://127.0.0.1:443
--kubeconfig=${instance}.kubeconfig
kubectl config set-credentials system:node:${instance}
--client-certificate=${instance}.pem
--client-key=${instance}-key.pem
--embed-certs=true
--kubeconfig=${instance}.kubeconfig
kubectl config set-context default
--cluster=kubernetes-the-hard-way
--user=system:node:${instance}
--kubeconfig=${instance}.kubeconfig
kubectl config use-context default --kubeconfig=${instance}.kubeconfig
done
И аналогично для The kube-proxy Kubernetes Configuration File:
kubectl config set-cluster kubernetes-the-hard-way
--certificate-authority=ca.pem
--embed-certs=true
--server=https://127.0.0.1:443
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials system:kube-proxy
--client-certificate=kube-proxy.pem
--client-key=kube-proxy-key.pem
--embed-certs=true
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default
--cluster=kubernetes-the-hard-way
--user=system:kube-proxy
--kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
Далее следуем инструкции до момента копирования файлов на узлы. Вместо этого делаем так:
{
for instance in $(cat node_list.txt | cut -d" " -f1); do
scp ${instance}.kubeconfig kube-proxy.kubeconfig admin.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig ${instance}:~/
done
}
Generating the Data Encryption Config and Key
В этом разделе выполняем всё по инструкции, за исключением копирования файлов по узлам. Копируем так:
{
for instance in $(cat node_list.txt | cut -d" " -f1); do
scp encryption-config.yaml ${instance}:~/
done
}
Bootstrapping the etcd Cluster
Вместо оригинальной инструкции вначале заходим на узел (выполнять для каждого узла):
ssh hpcom
Устанавливаем следующие необходимые утилиты:
sudo emerge --sync && emerge --ask dev-vcs/git sys-devel/make net-misc/wget net-misc/curl dev-lang/go app-shells/bash-completion
Скачиваем и собираем etcd:
git clone https://github.com/etcd-io/etcd.git
cd etcd
git checkout v3.4.15
go mod vendor
./build
sudo mv bin/etcd* /usr/local/bin/
Конфигурируем собранный etcd. Устанавливаем сертификаты:
{
sudo mkdir -p /etc/etcd /var/lib/etcd
sudo chmod 700 /var/lib/etcd
sudo cp ca.pem kubernetes-key.pem kubernetes.pem /etc/etcd/
}
Получаем IP-адрес и имя узла:
INTERNAL_IP=$(grep $(hostname -s) node_list.txt | cut -d' ' -f2)
ETCD_NAME=$(hostname -s)
И формируем Unit для systemd:
cat <<EOF | sudo tee /etc/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/etcd-io/etcd
[Service]
Type=notify
Environment="ETCD_UNSUPPORTED_ARCH=386" # Только для архитектуры i386, для amd64 не нужно указывать.
ExecStart=/usr/local/bin/etcd \
--name ${ETCD_NAME} \
--cert-file=/etc/etcd/kubernetes.pem \
--key-file=/etc/etcd/kubernetes-key.pem \
--peer-cert-file=/etc/etcd/kubernetes.pem \
--peer-key-file=/etc/etcd/kubernetes-key.pem \
--trusted-ca-file=/etc/etcd/ca.pem \
--peer-trusted-ca-file=/etc/etcd/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \
--listen-peer-urls https://${INTERNAL_IP}:2380 \
--listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://${INTERNAL_IP}:2379 \
--initial-cluster-token etcd-cluster-0 \
--initial-cluster $(cat node_list.txt | sed 's# #=https://#g' | tr 'n' ',' | sed 's#,#:2380,#g' | sed 's#,$##g') \
--initial-cluster-state new \
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
Теперь возвращаемся к исходной инструкции и выполняем все, что идет после пункта Start the etcd Server включительно.
Bootstrapping the Kubernetes Control Plane
Вначале заходим на узел (выполнять для каждого узла):
ssh hpcom
Создаем каталог для конфигурации:
sudo mkdir -p /etc/kubernetes/config
Скачиваем исходники Kubernetes и собираем control plane:
git clone https://github.com/kubernetes/kubernetes.git
cd kubernetes && git checkout v1.21.0
make kube-scheduler kube-apiserver kube-controller-manager kubectl
cd _output/bin
chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl
sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/
Переносим сертификаты:
{
sudo mkdir -p /var/lib/kubernetes/
cd && sudo mv ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem
service-account-key.pem service-account.pem
encryption-config.yaml /var/lib/kubernetes/
}
Для имитирования HA ставим NGINX (перед этим создав файл для USE-флагов дополнительных модулей Gentoo):
cat <<EOF | sudo tee /etc/portage/package.use/nginx
www-servers/nginx NGINX_MODULES_HTTP: access gzip gzip_static gunzip proxy push_stream stub_status upstream_check upstream_hash upstream_ip_hash upstream_keepalive upstream_least_conn upstream_zone
www-servers/nginx NGINX_MODULES_STREAM: access geo limit_conn map return split_clients upstream_hash upstream_least_conn upstream_zone geoip realip ssl_preread geoip2 javascript
EOF
sudo emerge --ask www-servers/nginx
В nginx.conf
в блок http
добавляем проверку работы сервера:
server {
listen 127.0.0.1:80;
server_name localhost;
access_log /var/log/nginx/localhost.access_log main;
error_log /var/log/nginx/localhost.error_log info;
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
И также в конец файла дописываем строку с include
по аналогии с Provisioning Compute Resources выше:
echo include passthrough.conf; | sudo tee -a /etc/nginx/nginx.conf
Затем, как на рабочей машине, создаем рядом файл passthrough.conf
:
cat <<EOF | sudo tee /etc/nginx/passthrough.conf
stream {
upstream kube {
$(cat node_list.txt | cut -d" " -f2 | xargs -I{} echo "$(printf '%8s')server {}:6443;")
}
server {
listen 443;
proxy_pass kube;
proxy_next_upstream on;
}
}
EOF
Конфигурируем API-сервер. Получаем нужные IP-адреса:
INTERNAL_IP=$(grep $(hostname -s) node_list.txt | cut -d' ' -f2)
KUBERNETES_PUBLIC_ADDRESS=127.0.0.1
Создаем Unit для systemd:
cat <<EOF | sudo tee /etc/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
ExecStart=/usr/local/bin/kube-apiserver \
--advertise-address=${INTERNAL_IP} \
--allow-privileged=true \
--apiserver-count=$(cat node_list.txt | wc -l) \
--audit-log-maxage=30 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/var/log/audit.log \
--authorization-mode=Node,RBAC \
--bind-address=0.0.0.0 \
--client-ca-file=/var/lib/kubernetes/ca.pem \
--enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
--etcd-cafile=/var/lib/kubernetes/ca.pem \
--etcd-certfile=/var/lib/kubernetes/kubernetes.pem \
--etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \
--etcd-servers=$(cut -d' ' -f2 node_list.txt | sed 's#^#https://#g' | sed 's#$#:2379#g' | xargs | tr ' ' ',') \
--event-ttl=1h \
--encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \
--kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \
--kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \
--kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \
--runtime-config='api/all=true' \
--service-account-key-file=/var/lib/kubernetes/service-account.pem \
--service-account-signing-key-file=/var/lib/kubernetes/service-account-key.pem \
--service-account-issuer=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
--service-cluster-ip-range=10.32.0.0/24 \
--service-node-port-range=30000-32767 \
--tls-cert-file=/var/lib/kubernetes/kubernetes.pem \
--tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \
--v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
Далее выполняем всё из оригинальной инструкции до пункта The Kubernetes Frontend Load Balancer. Устанавливать и настраивать balancer не требуется, хотя при желании можно развернуть MetalLB после окончательной настройки кластера. Блок Verification также можно пропустить, так как мы уже развернули NGINX.
Проверить работоспособность API-сервера можно так:
curl --cacert /var/lib/kubernetes/ca.pem https://127.0.0.1:443/healthz
Bootstrapping the Kubernetes Worker Nodes
Заходим на каждый узел и устанавливаем необходимые пакеты:
ssh hpcom
sudo emerge --ask net-misc/socat net-firewall/conntrack-tools net-firewall/ipset sys-fs/btrfs-progs
Создаем нужные каталоги, скачиваем и собираем нужные бинарники:
sudo mkdir -p
/etc/cni/net.d
/opt/cni/bin
/var/lib/kubelet
/var/lib/kube-proxy
/var/lib/kubernetes
/var/run/kubernetes
crictl для i386:
wget -q --show-progress --https-only --timestamping https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.21.0/crictl-v1.21.0-linux-386.tar.gz
tar -xvf crictl-v1.21.0-linux-386.tar.gz && sudo mv crictl /usr/local/bin/
И для amd64:
https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.21.0/crictl-v1.21.0-linux-amd64.tar.gz
tar -xvf crictl-v1.21.0-linux-amd64.tar.gz && sudo mv crictl /usr/local/bin/
runc:
cd && git clone git@github.com:opencontainers/runc.git && cd runc && git checkout v1.0.0-rc93
make
sudo make install
CNI plugins:
cd && git clone git@github.com:containernetworking/plugins.git && cd plugins && git checkout v0.9.1
./build_linux.sh
sudo mv bin/* /opt/cni/bin/
containerd requirements для i386:
cd && wget -c https://github.com/google/protobuf/releases/download/v3.11.4/protoc-3.11.4-linux-x86_32.zip
sudo unzip protoc-3.11.4-linux-x86_32.zip -d /usr/local
И для amd64:
cd && wget -c
https://github.com/google/protobuf/releases/download/v3.11.4/protoc-3.11.4-linux-x86_64.zip
sudo unzip protoc-3.11.4-linux-x86_64.zip -d /usr/local
containerd:
cd && git clone git@github.com:containerd/containerd.git && cd containerd
git clone git@github.com:containerd/containerd.git && cd containerd/
make
sudo make install
K8s:
cd ~/kubernetes && git checkout v1.21.0
make kubelet kube-proxy
cd _output/bin
chmod +x kubelet kube-proxy
sudo mv kubelet kube-proxy /usr/local/bin/
Конфигурируем CNI-плагин:
POD_CIDR=10.200.$(grep -n $(hostname -s) node_list.txt | cut -d':' -f1).0/24
cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf
{
"cniVersion": "0.4.0",
"name": "bridge",
"type": "bridge",
"bridge": "cnio0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"ranges": [
[{"subnet": "${POD_CIDR}"}]
],
"routes": [{"dst": "0.0.0.0/0"}]
}
}
EOF
cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf
{
"cniVersion": "0.4.0",
"name": "lo",
"type": "loopback"
}
EOF
Конфигурируем containerd (используется другая версия конфига, в отличие от оригинального репозитория):
sudo mkdir -p /etc/containerd/
cat << EOF | sudo tee /etc/containerd/config.toml
version = 2
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "docker.io/alexeymakhonin/pause:i386" # k8s.gcr.io/pause:3.7 для amd64
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "overlayfs"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/sbin/runc"
runtime_root = ""
EOF
Контейнер pause
(он же sandbox_image
в конфиге containerd) от K8s не собирается для i386-архитектуры. Поэтому его можно собрать самостоятельно или воспользоваться готовым образом из моего Docker Hub’а: docker.io/alexeymakhonin/pause:i386.
Если вы решили пойти первым путем, на узле с i386-архитектурой нужно собрать бинарник:
cd ~/kubernetes/build/pause && mkdir bin
gcc -Os -Wall -Werror -static -DVERSION=v3.6-bbc2dbb9801 -o bin/pause-linux-i386 linux/pause.c
Полученный бинарник и всю директорию следует скопировать на рабочий ноутбук с Docker Buildx, на котором будет собираться образ:
scp -r hpcom:~/kubernetes/build/pause ./ && cd pause
docker buildx build --pull --output=type=docker --platform linux/i386 -t docker.io/<DockerHub username>/pause:i386 --build-arg BASE=scratch --build-arg ARCH=i386 .
docker push docker.io/<DockerHub username>/pause:i386
Затем в конфигурационном файле containerd нужно поменять sandbox_image
на собранный образ.
Теперь создаем Unit containerd для systemd:
cat <<EOF | sudo tee /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target
[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
EOF
Сконфигурировать kubelet и kube-proxy можно по оригинальной инструкции. Однако стоит помнить, что ca.pem
уже скопирован в /var/lib/kubernetes
, поэтому команда mv
упадет с ошибкой.
Проверить работоспособность узла можно так:
kubectl get node --kubeconfig ~/admin.kubeconfig
Configuring kubectl for Remote Access
Из этого раздела нас интересует только самое начало — пункт The Admin Kubernetes Configuration File. Выполняем его:
{
KUBERNETES_PUBLIC_ADDRESS=127.0.0.1
kubectl config set-cluster kubernetes-the-hard-way
--certificate-authority=ca.pem
--embed-certs=true
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:443
kubectl config set-credentials admin
--client-certificate=admin.pem
--client-key=admin-key.pem
kubectl config set-context kubernetes-the-hard-way
--cluster=kubernetes-the-hard-way
--user=admin
kubectl config use-context kubernetes-the-hard-way
}
Provisioning Pod Network Routes
Эти инструкции можно пропустить.
Deploying the DNS Cluster Add-on
Здесь инструкции придется разделить на две части. Для машины с архитектурой amd64 выполняем всё, как в оригинале, а вот для i386 придется пойти другим путем. Обусловлено это тем, что официального образа coredns для i386 не существует, поэтому его придется собирать самим (или взять уже собранный мной). Чтобы собрать образ самостоятельно, на машине с Docker Buildx выполняем команды:
git clone git@github.com:coredns/coredns.git && cd coredns && git checkout v1.8.3
make CGO_ENABLED=0 GOOS=linux GOARCH=386
docker buildx build --pull --output=type=docker --platform linux/i386 -t docker.io/<DockerHub username>/coredns:i386 .
docker push docker.io/<DockerHub username>/coredns:i386
Затем берем конфиг с заменой образа на наш и деплоим его:
curl -L https://storage.googleapis.com/kubernetes-the-hard-way/coredns-1.8.yaml --silent -o - | sed 's#image: coredns/coredns:1.8.3#image: docker.io/<DockerHub username>/coredns:i386#g' | kubectl apply -f -
Теперь остается только наложить патч на созданный ресурс, заменив значение аннотации на i386
или amd64
в зависимости от того, на какой узел вы хотите назначить coredns по архитектуре:
cat <<EOF | yq -ojson | tee patch.json
spec:
template:
spec:
nodeSelector:
kubernetes.io/arch: "386"
EOF
kubectl patch -n kube-system deployments.apps coredns --patch-file patch.json
Теперь можно проверить, что все работает, выполнив команды из оригинальной инструкции.
На этом этапе может возникнуть ошибка: Pod’ы будут зависать в состоянии ContainerCreating
с ошибкой:
cgroups: cgroup mountpoint does not exist: unknown.
Если это произошло, починить можно так:
sudo mkdir /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
Smoke Test
Делаем всё по инструкции, за исключением двух пунктов.
Команда проверки шифрования:
ssh hpcom
sudo ETCDCTL_API=3 etcdctl get
--endpoints=https://127.0.0.1:2379
--cacert=/etc/etcd/ca.pem
--cert=/etc/etcd/kubernetes.pem
--key=/etc/etcd/kubernetes-key.pem
/registry/secrets/default/kubernetes-the-hard-way | hexdump -C
Для NODE_PORT
-сервиса:
curl -I http://$(grep hpcom node_list.txt | cut -d' ' -f2):${NODE_PORT}
Cleaning up
На этом этапе можно просто снести систему :)
Заключение
Мы рассмотрели, как можно с интересом провести время и не дать пропасть старому железу, которое, например, давно отложено в кладовку, а выбросить руки не поднимаются. Также мы научились разворачивать Kubernetes на физическом оборудовании, используя готовые инструкции из Kubernetes The Hard Way с небольшими доработками.
Особенно интересным и полезным может быть опыт самостоятельной сборки недостающих образов для архитектуры i386: хотя она уже давно выходит из обращения, иногда все-таки встречается.
Надеюсь, статья поможет тем, кто хочет поглубже влезть в Kubernetes и его настройку.
P.S.
Читайте также в нашем блоге:
Автор: Махонин Алексей