Разворачиваем кластер kubernetes на платформе mail.ru cloud solutions

Как запустить основные инструменты
10 минут

Для полноценной работы с кластером Kubernetes, помимо стандартных сервисов, которые входят в дистрибутив, необходимо установить некоторые дополнительные сервисы:

    1. Сеть — настройка диапазонов IP, инкапсуляции, маршрутизации.
    2. Мониторинг.
    3. Ingress Controller — балансировщик нагрузки http/https, который позволяет маршрутизировать http-запросы на основе доменного имени и пути. С помощью него можно хостить на одном IP-адресе много сайтов и приложений и экономить IP-адреса.
    4. Persistent Storage — для постоянного хранения данных в условиях динамично меняющейся инфраструктуры: добавление/удаление нод, перезапуск подов на различных машинах и так далее.
    5. Helm — пакетный менеджер для автоматизации развёртывания приложений.

На облачной платформе Mail.Ru Cloud Solutions (MCS) можно развернуть кластер Kubernetes с нуля. В кластере «из коробки» запущены 4 из этих 5 дополнительных сервисов. Рассмотрим каждый из них и проверим их работоспособность. В конце покажем, как просто добавить в кластер Helm.

Итак, что у нас есть после запуска кластера Kubernetes на MCS:


1. Запущенная сеть Calico

Каждой ноде назначается своя подсеть для подов. Обычно у сетей в Kubernetes есть два режима работы: оверлейный и неоверлейный (host gateway).

    • В оверлейном режиме вся сеть между подами инкапсулируется. Протокол инкапсуляции зависит от конкретной реализации сети (например: calico — IPinIP, flannel — vxlan).
    • В неоверлейном режиме трафик между подами не инкапсулируется, а ходит по хостовой сети с внутренними IP-адресами подов. Маршрутизация в этом режиме организована по принципу “NodeSubnet via NodeIP”. Например, в Calico — при помощи BGP.

На MCS по умолчанию действует неоверлейный режим работы.

Посмотрим запущенные поды в системном неймспейсе Kubernetes kube-system:kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-79c97cf859-4zdgt 1/1 Running 0 3h
calico-node-55p66 2/2 Running 0 3h
calico-node-b7lsd 2/2 Running 0 3h
calico-node-l5m88 2/2 Running 0 3h
calico-node-rrdd8 2/2 Running 0 3h

Доказательством того, что сеть настроена и работает корректно, может служить тот факт, что в запущенном кластере можно стартовать работающие приложения. Ниже мы запустим несколько приложений.


2. Система сбора метрик Prometheus и Grafana

Для сбора метрик в Kubernetes используется система Prometheus. Она устанавливается в кластере на MCS по умолчанию.

В Prometheus есть встроенная база данных временных рядов. Prometheus собирает метрики с различных экспортеров на нодах кластера. Например, node-exporter собирает метрики хостов: загрузка процессора, оперативной памяти, диска, показатели работы сетевого стека и так далее. Метрики также собираются со многих компонентов Kubernetes и его дополнений: kube-apiserver,kube-controller-manager, kube-scheduler, kubelet, etcd и других.

Метрики можно просматривать через встроенный веб-интерфейс, но он не очень удобен для постоянного отображения метрик. С этой задачей куда лучше справляется Grafana, который позволяет создавать информативные дашборды.

По умолчанию поды мониторинга запускаются в неймспейсе prometheus-monitoring. Посмотрим поды, запущенные в этом неймспейсе:kubectl get po -n prometheus-monitoring
NAME READY STATUS RESTARTS AGE
prometheus-monitoring grafana-dd64f69cc-2mmpf 1/1 Running 0 3h
prometheus-monitoring prometheus-7cdfbd7d5f-sv6j5 1/1 Running 0 3h

Чтобы получить доступ к дашборду, выполним командуkubectl proxy и зайдём на адресhttp://127.0.0.1:8001/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy

При создании кластера по умолчанию ставится минималистичный Kubernetes dashboard, который позволяет управлять всеми базовыми ресурсами Kubernetes. Дополнительно можно установить систему сбора метрик Heapster, она позволит отображать базовые метрики Kubernetes прямо в Kubernetes dashboard. Она не так функциональна, как Prometheus, но её достаточно для сбора метрик о потреблении ресурсов подами и нодами. Вместе с Heapster устанавливается база данных InfluxDB, в которую пишутся все собранные метрики, и дашборд Grafana для отображения метрик удобном виде.

kubectl get po --all-namespaces
NAME READY STATUS RESTARTS AGE
heapster-5c6d75b6c7-72hsj 1/1 Running 0 3h

Для подключения к дашборду можно использовать тот жеkubectl proxy. Дашборд будет открываться по адресуhttp://127.0.0.1:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/


3. Load balancer Nginx-Ingress

kubectl get po -n ingress-nginx
NAME READY STATUS RESTARTS AGE
default-http-backend-85c9b5f6f8-8m8c4 1/1 Running 0 21h
default-http-backend-85c9b5f6f8-rsggf 1/1 Running 0 21h
nginx-ingress-controller-7c95b49bb6-d44ck 1/1 Running 0 21h
nginx-ingress-controller-7c95b49bb6-pb8kv 1/1 Running 0 21h
kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend ClusterIP 10.254.171.158 80/TCP 21h
ingress-nginx LoadBalancer 10.254.45.49 192.0.2.124 80:32604/TCP,443:32312/TCP 21h

Чтобы проверить работу ingress-controller, создадим сначала pod с веб сервером:kubectl run nginx --image=nginx -l app=hello-world

И сервис для него:kubectl expose deployment/nginx --port=80 --target-port=80

Ingress-controller в Kubernetes выполняет задачи по балансировке трафика, маршрутизации по доменным именам и подпутям в HTTP, поддерживает терминацию TLS. Создавая ресурс Ingress, мы создаём новые правила для балансировщика нагрузки. В данном случае все запросы на домен example.com будут отправленны на сервис nginx, порт 80:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx
          servicePort: 80

Запускаем ingress-ресурс:kubectl create -f ingress.yaml

Смотрим, что запустилось:kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
test-ingress example.com 192.0.2.124 80 3m

Ingress-controller маршрутизирует трафик по доменам на основании заголовка «Host:» в запросе. Чтобы можно было зайти по URL через браузер, добавляем адрес сервиса ingress-nginx в файл hosts на своём компьютере:192.0.2.124 example.com

Результат можно увидеть в браузере по адресуexample.com


4. Persistent Storage

В MCS для организации хранилища используется интеграция с OpenStack Cinder.

В Kubernetes в имплементации MCS уже заданы четыре Storage Class (SC). Два HDD и два SSD. Отличаются они Reclaim policy. Если Reclaim policy = retain, то при удалении PVC не будет удалён сам PV, к которому был привязан данный PVC.

kubectl get storageclasses
NAME PROVISIONER AGE
hdd (default) kubernetes.io/cinder 21h
hdd-retain kubernetes.io/cinder 21h
ssd kubernetes.io/cinder 21h
ssd-retain kubernetes.io/cinder 21h

Некоторые сервисы уже используют хранилище:kubectl get pvc --all-namespaces
NAMESPACE NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
kube-system grafana-pvc Bound pvc-a0b500f9-e286-11e8-9dcd-fa163efef724 10Gi RWO hdd 7d
kube-system influxdb-pvc Bound pvc-9e3b9fd9-e286-11e8-9dcd-fa163efef724 10Gi RWO hdd 7d
prometheus-monitoring grafana-pvc Bound pvc-bdd5aba5-e286-11e8-9dcd-fa163efef724 10Gi RWO hdd 7d
prometheus-monitoring prometheus-pvc Bound pvc-b53a0789-e286-11e8-9dcd-fa163efef724 10Gi RWO hdd 7d

Для проверки persistent storage создадим PVC и Pod:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
  storageClassName: ssd
---
kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

Зайдём в под и запишем что-нибудь на persistent volume:kubectl exec -it mypod /bin/bash
root@mypod:/# cd /var/www/html
root@mypod:/var/www/html# echo 'Hello World!' > index.html

Удалим под:kubectl delete po mypod

И создадим заново:

kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

Проверим, что данные были сохранены:kubectl exec -it mypod cat /var/www/html/index.html
Hello World!

Как показано выше, данные сохранились, несмотря на то, что под с приложением nginx был удалён.


Остается добавить крайний дополнительный компонент — пакетный менеджер Helm

Helm в комплекте не идёт, но его очень легко поставить.

Для начала Скачайте helm на свой локальный компьютер:curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.11.0-linux-amd64.tar.gz
tar -xvf helm-v2.11.0-linux-amd64.tar.gz
cd linux-amd64/

Создайте CA для шифрования соединений с helm:mkdir HELM-CA
cd HELM-CA
openssl genrsa -out ca.key.pem 4096
openssl req -key ca.key.pem -new -x509 -days 7300 -subj '/ON=tiller/CN=tiller' -sha256 -out ca.cert.pem -extensions v3_ca
openssl genrsa -out tiller.key.pem 4096
openssl genrsa -out helm.key.pem 4096
openssl req -key tiller.key.pem -new -sha256 -out tiller.csr.pem -subj '/ON=Tiller Server/CN=tiller-server'
openssl req -key helm.key.pem -new -sha256 -out helm.csr.pem -subj '/CN=helm'
openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365
openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in helm.csr.pem -out helm.cert.pem -days 365
mkdir $(../helm home)
cp ca.cert.pem $(../helm home)/ca.pem
cp helm.cert.pem $(../helm home)/cert.pem
cp helm.key.pem $(../helm home)/key.pem
cd ..

Helm использует серверный компонент tiller для взаимодействия с Kubernetes API. Для его нормальной работы необходимо создать RBAC для аутентификации в Kubernetes.

yaml-файл:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system

Создаем RBAC:kubectl apply -f tiller-rbac.yaml

Инициализируем helm:./helm init --tiller-tls \
--tiller-tls-cert HELM-CA/tiller.cert.pem \
--tiller-tls-key HELM-CA/tiller.key.pem \
--tls-ca-cert HELM-CA/ca.cert.pem \
--tiller-tls-verify \
--service-account=tiller

Теперь можно работать с helm!

Пример использования helm

Для примера запустим WordPress через helm:./helm install --name my-wordpress --set ingress.hosts[0].name=wordpress.local \
--set ingress.enabled=true --set persistence.storageClass=ssd stable/wordpress --tls

При запуске helm мы передаем аргументы для кастомизации установки: включаем создание ingress, задаем ему доменное имя, подключаем персистентное хранилище для базы данных.

Через некоторое время wordpress запустится:kubectl get po
NAME READY STATUS RESTARTS AGE
my-wordpress-mariadb-0 1/1 Running 0 4m
my-wordpress-wordpress-69dfc4d786-988h7 1/1 Running 0 4m

Чтобы увидеть результат, пропишем адрес wordpress.local в /etc/hosts. После этого результат можно увидеть в своём браузере: