Уже довольно много написано статей, по установке и запуску 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 довольно хорошая документация.
Все операции производим из под привелигированого пользователя root.
Создадим временную директорию:
Установим Ceph:
Необходимо создать ключ и разложить его по всем серверам. Это нужно для утилиты ceph-deploy:
(возможно, вам понадобится поправить конфиг ssh для разрешения логинится под пользователем root).
Проверьте, что kub01 не прописан в вашем /etc/hosts как 127.0.0.1 (если прописан, удалите эту строку).
Создаем дисковый кластер и инициализируем его:
Проверяем наш дисковый кластер:
Можно взять на вооружение следующие полезные команды:
Теперь, когда мы убедились, что Ceph работает, мы создадим отдельный пул (pool) для k8s:
(можно посмотреть все существующие пулы командой: ceph df)
Теперь создадим отдельного пользователя для нашего пула kube и сохраним ключи:
(ключи понадобятся для доступа k8s к хранилищу)
Добавим репозиторий k8s в нашу систему:
Теперь установим основные пакеты:
Инициализируем и запускаем k8s
(именно такая сеть 10.244.0.0/16 необходима для работы flannel — не изменяйте ее)
Сохраните напечатанную скриптом команду для присоединения нод к кластеру.
Для работы с k8s удобно использовать отдельного непривилегированного пользователя. Создадим его и скопируем в него конфигурационный файл k8s:
Для работы с k8s используется утилита: kubectl. Используем ее только из под нашего пользователя kube. Для перехода под пользователя выполним:
Разрешаем запуск контейнеров на мастере:
Настраиваем права:
Устанавливаем flannel (сетевую подсистему):
Создаем пользователя для доступа в веб интерфейс:
Запустим kube-proxy, сделать это можно так:
И пробросим порт 8001 с вашей рабочей машины до сервера kub01:
Теперь мы можем зайти в веб интерфейс со своей рабочей машины по адресу:
http://127.0.0.1:8001/ui
(откроется веб интерфейс, где нужно указать токен)
Получить токен для доступа в веб интерфейс можно так:
В текущем контроллере kube-controller-manager-amd64:v1.9.2 отсутствует бинарник rbd, необходимый для работы с Ceph, поэтому создадим свой собственный kube-controller-manager:
Для создания нашего kube-controller-manager сделайте следующее:
(все команды выполняем из под пользователя root)
(обязательно указывайте актуальные версии k8s и дистрибутива ОС)
Проверяем, что наш контроллер успешно создан:
Проверяем, что в нашем образе есть 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 и дожидаемся пока наш контроллер запустится (ничего делать не нужно).
Должны увидеть, что используется наш образ:
Image: my-kube-controller-manager:v1.9.2
Теперь, когда запустился наш контроллер с поддержкой RBD, мы можем приступить к настройке связки k8s и Ceph.
Добавляем ключи в k8s, для доступа к Ceph:
Создаем StorageClass (default):
На новом сервере выполните следующие команды:
Присоединяем ноду к мастеру:
Нам нужен ключ. Его можно получить на мастере, выполнив команду:
Либо, создать его:
Пример команды для присоединения (выполняем на новой ноде):
Для быстрой и простой установки приложений в k8s был придуман Helm.
Список доступных приложений можно найти здесь.
Устанавливаем и инициализируем Helm:
P.S.: на написание этой статьи ушло 6 часов. Не судите строго, если где-то есть опечатки. Задавайте вопросы, с радостью отвечу и помогу.
Данная статья призвана дать исчерпывающую информацию не только по установке 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
(возможно, вам понадобится поправить конфиг ssh для разрешения логинится под пользователем root).
Проверьте, что kub01 не прописан в вашем /etc/hosts как 127.0.0.1 (если прописан, удалите эту строку).
Создаем дисковый кластер и инициализируем его:
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 был актуальным.
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:
Создадим тестовый pod с диском:
Проверим, что создался Pod (нужно дождаться создания и запуска):
Проверим, что создался Claim (запрос на предоставление диска):
Проверим, что создался и сам диск:
И наконец, проверим, что диск примонтирован в системе:
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 python
Присоединяем ноду к мастеру:
Нам нужен ключ. Его можно получить на мастере, выполнив команду:
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 часов. Не судите строго, если где-то есть опечатки. Задавайте вопросы, с радостью отвечу и помогу.