Главная » Хабрахабр » [Из песочницы] Запускаем полноценный кластер на Kubernetes с нуля на Ubuntu 16.04

[Из песочницы] Запускаем полноценный кластер на Kubernetes с нуля на Ubuntu 16.04

Уже довольно много написано статей, по установке и запуску Kubernetes, однако, не всё так гладко (я потратил несколько суток на запуск своего кластера).

Данная статья призвана дать исчерпывающую информацию не только по установке k8s, но и объяснить каждый шаг: зачем и почему мы делаем именно так, как написано (это очень важно для успешного запуска).

Что нужно знать

Серверы:
Кластер подразумевает, что у Вас более одного физического сервера, между которыми и будут распределятся ресурсы. Серверы называются нодами (nodes).

Диски:
k8s требует распределенного файлового хранилища. Это необходимо для того, чтобы k8s мог «перемещать» контейнеры docker на другие ноды в случае необходимости, без потери данных (файлов).

Начинать создание кластера нужно именно с создания своего распределенного файлового хранилища. Я выбрал Ceph. А еще рекомендую почитать эту замечательную статью.

Минимальное разумное количество серверов для Ceph — 3 (можно построить и на одном, но в этом мало смысла из-за высокой вероятности потерять данные).

Сеть:
Нам понадобится Flannel — он позволяет организовать программно определяемую сеть (Software Defined Network, SDN). Именно SDN позволяет всем нашим контейнерам общаться с друг другом внутри кластера (установка Flannel производится вместе с k8s и описана ниже).

Подготовка серверов

В нашем примере мы используем 3 физических сервера. Установите Ubuntu 16.04 на все сервера. Не создавайте swap партиции (требование k8s).

Предусмотрите в каждом сервере как минимум один диск (или партицию) для Ceph.

Не включайте поддержку SELinux (в Ubuntu 16.04 он выключен по-умолчанию).

Мы назвали сервера так: kub01 kub02 kub03. Партиция sda2 на каждом сервере создана для Ceph (форматировать не обязательно).

Установка и настройка Ceph

Установку Ceph я опишу довольно кратко. В сети много примеров и на самом сайте Ceph довольно хорошая документация.

Все операции производим из под привелигированого пользователя root.

Создадим временную директорию:

mkdir ~/ceph-admin
cd ~/ceph-admin

Установим Ceph:

apt install ceph-deploy ceph-common

Необходимо создать ключ и разложить его по всем серверам. Это нужно для утилиты ceph-deploy:

ssh-keygen
ssh-copy-id kub01
ssh-copy-id kub02
ssh-copy-id kub03

Создаем дисковый кластер и инициализируем его:

ceph-deploy new kub01 kub02 kub03
ceph-deploy install kub01 kub02 kub03
ceph-deploy mon create-initial
ceph-deploy osd prepare kub01:sda2 kub02:sda2 kub03:sda2
ceph-deploy osd activate kub01:sda2 kub02:sda2 kub03:sda2

Проверяем наш дисковый кластер:

ceph -s cluster 363a4cd8-4cb3-4955-96b2-73da72b63cf5 health HEALTH_OK

Можно взять на вооружение следующие полезные команды:

ceph -s
ceph df
ceph osd tree

Теперь, когда мы убедились, что Ceph работает, мы создадим отдельный пул (pool) для k8s:

ceph osd pool create kube 100 100

(можно посмотреть все существующие пулы командой: ceph df)

Теперь создадим отдельного пользователя для нашего пула kube и сохраним ключи:

ceph auth get-or-create client.kube mon 'allow r' osd 'allow rwx pool=kube'
ceph auth get-key client.admin > /etc/ceph/client.admin
ceph auth get-key client.kube > /etc/ceph/client.kube

(ключи понадобятся для доступа k8s к хранилищу)

Устанавливаем Kubernetes

Добавим репозиторий k8s в нашу систему:

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main EOF

Теперь установим основные пакеты:

apt update
apt install -y docker.io kubelet kubeadm kubernetes-cni

Инициализируем и запускаем k8s

kubeadm init --pod-network-cidr=10.244.0.0/16

(именно такая сеть 10.244.0.0/16 необходима для работы flannel — не изменяйте ее)

Для работы с k8s удобно использовать отдельного непривилегированного пользователя. Создадим его и скопируем в него конфигурационный файл k8s:

useradd -s /bin/bash -m kube
mkdir ~kube/.kube
cp /etc/kubernetes/admin.conf ~kube/.kube/config
chown kube: ~kube/.kube/config

Для работы с k8s используется утилита: kubectl. Используем ее только из под нашего пользователя kube. Для перехода под пользователя выполним:

su - kube

Разрешаем запуск контейнеров на мастере:

kubectl taint nodes --all node-role.kubernetes.io/master-

Настраиваем права:

kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default

Устанавливаем flannel (сетевую подсистему):

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Как проверить что всё работает

Выполните команду:

kubectl -n kube-system get pods

Вывод должен быть примерно следующим:

NAME READY STATUS RESTARTS AGE
etcd-kub01.domain.com 1/1 Running 1 4d
kube-apiserver-kub01.domain.com 1/1 Running 1 4d
kube-controller-manager-kub01.domain.com 1/1 Running 0 4d
kube-dns-7c6d8859cb-dmqrn 3/3 Running 0 1d
kube-flannel-ds-j948h 1/1 Running 0 1d
kube-proxy-rmbqq 1/1 Running 0 1d
kube-scheduler-kub01.domain.com 1/1 Running 1 4d

Устанавливаем и настраиваем веб-интерфейс

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

Создаем пользователя для доступа в веб интерфейс:

cat << EOF > account.yaml apiVersion: v1
kind: ServiceAccount
metadata: name: admin-user namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata: name: admin-user
roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin
subjects:
- kind: ServiceAccount name: admin-user namespace: kube-system
EOF kubectl -n kube-system create -f account.yaml

Запустим kube-proxy, сделать это можно так:

kubectl proxy &

И пробросим порт 8001 с вашей рабочей машины до сервера kub01:

ssh -L 8001:127.0.0.1:8001 -N kub01 &

Теперь мы можем зайти в веб интерфейс со своей рабочей машины по адресу:

http://127.0.0.1:8001/ui
(откроется веб интерфейс, где нужно указать токен)

Получить токен для доступа в веб интерфейс можно так:

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

Настраиваем Kubernetes и Ceph

В текущем контроллере kube-controller-manager-amd64:v1.9.2 отсутствует бинарник rbd, необходимый для работы с Ceph, поэтому создадим свой собственный kube-controller-manager:

Что такое RBD, зачем он нужен и почему отсутствует?

RBD (Rados Block Device) — блочное устройство, которое как раз и используется k8s для создания и монтирования партиций Docker контейнеров. В данном случае, это бинарник, входящий в состав пакета: ceph-common.

k8s не включает этот пакет в свой контроллер видимо потому, что он зависит от дистрибутива операционной системы, которую вы используете. Поэтому, при сборке своего контроллера обязательно указывайте именно Ваш дистрибутив, чтобы RBD был актуальным.

Для создания нашего kube-controller-manager сделайте следующее:
(все команды выполняем из под пользователя root)

mkdir docker
cat << EOF > docker/Dockerfile
FROM ubuntu:16.04 ARG KUBERNETES_VERSION=v1.9.2 ENV DEBIAN_FRONTEND=noninteractive \ container=docker \ KUBERNETES_DOWNLOAD_ROOT=https://storage.googleapis.com/kubernetes-release/release/${KUBERNETES_VERSION}/bin/linux/amd64 \ KUBERNETES_COMPONENT=kube-controller-manager RUN set -x \ && apt-get update \ && apt-get install -y \ ceph-common \ curl \ && curl -L ${KUBERNETES_DOWNLOAD_ROOT}/${KUBERNETES_COMPONENT} -o /usr/bin/${KUBERNETES_COMPONENT} \ && chmod +x /usr/bin/${KUBERNETES_COMPONENT} \ && apt-get purge -y --auto-remove \ curl \ && rm -rf /var/lib/apt/lists/*
EOF docker build -t "my-kube-controller-manager:v1.9.2" docker/

(обязательно указывайте актуальные версии k8s и дистрибутива ОС)

Проверяем, что наш контроллер успешно создан:

docker images | grep my-kube-controller-manager

Проверяем, что в нашем образе есть rbd:

docker run my-kube-controller-manager:v1.9.2 whereis rbd

Должны увидеть что-то вида: rbd: /usr/bin/rbd /usr/share/man/man8/rbd.8.gz

Заменяем стандартный контроллер нашим, для этого правим файл:
/etc/kubernetes/manifests/kube-controller-manager.yaml

Заменяем строку:
image: gcr.io/google_containers/kube-controller-manager-amd64:v1.9.2
на:
image: my-kube-controller-manager:v1.9.2
imagePullPolicy: IfNotPresent

(обязательно добавляем директиву imagePullPolicy, чтобы k8s не пытался скачивать этот образ из интернета)

Переходим под пользователя kube и дожидаемся пока наш контроллер запустится (ничего делать не нужно).

kubectl -n kube-system describe pods | grep kube-controller

Должны увидеть, что используется наш образ:
Image: my-kube-controller-manager:v1.9.2

Теперь, когда запустился наш контроллер с поддержкой RBD, мы можем приступить к настройке связки k8s и Ceph.

Настройка связки дисковой подсистемы (k8s + Ceph)

Добавляем ключи в k8s, для доступа к Ceph:

kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" --from-file=/etc/ceph/client.admin --namespace=kube-system
kubectl create secret generic ceph-secret-kube --type="kubernetes.io/rbd" --from-file=/etc/ceph/client.kube --namespace=default

Создаем StorageClass (default):

cat << EOF > ceph_storage.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: name: ceph-rbd annotations: {"storageclass.kubernetes.io/is-default-class":"true"}
provisioner: kubernetes.io/rbd
parameters: monitors: kub01:6789,kub02:6789,kub03:6789 pool: kube adminId: admin adminSecretName: ceph-secret adminSecretNamespace: "kube-system" userId: kube userSecretName: ceph-secret-kube fsType: ext4 imageFormat: "2" imageFeatures: "layering"
EOF kubectl create -f ceph_storage.yaml

Как проверить работу дисковой подсистемы?

Проверяем наличие StorageClass:

kube@kub01:~$ kubectl get storageclass
NAME PROVISIONER AGE
ceph-rbd (default) kubernetes.io/rbd 4d

Создадим тестовый pod с диском:

cat << EOF > test_pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata: name: claim1
spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata: name: test-pod-with-pvc
spec: volumes: - name: test-pvc-storage persistentVolumeClaim: claimName: claim1 containers: - name: test-container image: kubernetes/pause volumeMounts: - name: test-pvc-storage mountPath: /var/lib/www/html
EOF kubectl create -f test_pod.yaml

Проверим, что создался Pod (нужно дождаться создания и запуска):

kube@kub01:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-pod-with-pvc 1/1 Running 0 15m

Проверим, что создался Claim (запрос на предоставление диска):

kube@kub01:~$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
claim1 Bound pvc-076df6ee-0ce9-11e8-8b93-901b0e8fc39b 1Gi RWO ceph-rbd 12m

Проверим, что создался и сам диск:

kube@kub01:~$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-076df6ee-0ce9-11e8-8b93-901b0e8fc39b 1Gi RWO Delete Bound default/claim1 ceph-rbd 

И наконец, проверим, что диск примонтирован в системе:

root@kub01:~$ mount | grep pvc-076df6ee-0ce9-11e8-8b93-901b0e8fc39b
/dev/rbd0 on /var/lib/kubelet/pods/076fff13-0ce9-11e8-8b93-901b0e8fc39b/volumes/kubernetes.io~rbd/pvc-076df6ee-0ce9-11e8-8b93-901b0e8fc39b type ext4 (rw,relatime,stripe=1024,data=ordered)

Добавление новых (дополнительных) нод в кластер k8s

На новом сервере выполните следующие команды:

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main EOF apt update
apt install -y docker.io kubelet kubeadm kubernetes-cni ceph-common

Присоединяем ноду к мастеру:
Нам нужен ключ. Его можно получить на мастере, выполнив команду:

kubeadm token list

Либо, создать его:

kubeadm token create --print-join-command

Пример команды для присоединения (выполняем на новой ноде):

kubeadm join --token cb9141.6a912d1dd7f66ff5 8.8.8.8:6443 --discovery-token-ca-cert-hash sha256:f0ec6d8f9699169089c89112e0e6b5905b4e1b42db22815186240777970dc6fd

Установка и настройка Helm

Для быстрой и простой установки приложений в k8s был придуман Helm.

Список доступных приложений можно найти здесь.

Устанавливаем и инициализируем Helm:

curl https://storage.googleapis.com/kubernetes-helm/helm-v2.8.0-linux-amd64.tar.gz | tar -xz
./linux-amd64/helm init

P.S.: на написание этой статьи ушло 6 часов. Не судите строго, если где-то есть опечатки. Задавайте вопросы, с радостью отвечу и помогу.


x

Ещё Hi-Tech Интересное!

[Из песочницы] Исследователи из Карнеги-Меллона создали пока самые правдоподобные «deepfakes»

Когда-либо слышали о «deepfakes»? ИИ, который накладывает лицо одного человека на тело другого, использовали для замены Харрисона Форда на Николаса Кейджа в бесчисленных видеоклипах, а также и для более гнусных целей: знаменитости без их ведома появились в порно и пропаганде. ...

Очередной сказ о том, как на Мегафоне воруют деньги

upd: уточняю: это не жалоба, а статья-предупреждение, проверьте свои детализации Сидел я значит на диване, никого не трогал, переписывался в контактике (каюсь три раза). Дело было вечером, делать было нечего. Поборов лень, я встал с дивана, подошел к телефону и ...