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

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

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

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

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

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

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

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

Посмотрим запущенные поды в системном неймспейсе 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. Она устанавливается в кластере на VK по умолчанию.

В 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-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

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

В Kubernetes в имплементации VK уже заданы четыре 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. После этого результат можно увидеть в своём браузере: