Kubernetes — это предназначенный для контейнерной оркестровки фреймворк с открытым исходным кодом. Он был создан с учетом богатейшего опыта Google в области создания сред управления контейнерами и позволяет выполнять контейнеризованные приложения в готовом к промышленной эксплуатации кластере. В механизме Kubernetes много движущихся частей и способов их настройки — это различные системные компоненты, драйверы сетевого транспорта, утилиты командной строки, не говоря уже о приложениях и рабочих нагрузках.


По ходу этой статьи мы установим Kubernetes 1.6 на реальную (не виртуальную) машину под управлением Ubuntu 16.04 примерно за 10 минут. В результате у вас появится возможность начать изучать взаимодействие с Kubernetes посредством его CLI kubectl.

Обзор Kubernetes:



Компоненты Kubernetes, автор Julia Evans


Что нам понадобится


Для развертывания кластера я предлагаю использовать физическую машину от сервиса Packet. Вы также можете проделать описанные мною шаги в виртуальной машине или на домашнем компьютере, если на них в качестве операционной системы установлена Ubuntu 16.04.

Зайдите на Packet.net и создайте новый проект. Для целей этой статьи нам хватит хоста Type 0 (4 ядра Atom и 8GB RAM за 0,05$/час).


При настройке хоста не забудьте выбрать в качестве ОС Ubuntu 16.04. В отличие от Docker Swarm Kubernetes лучше работает с проверенными временем релизами Docker. К счастью, репозиторий Ubuntu apt содержит Docker 1.12.6.


  • Установите Docker.

$ apt-get update && apt-get install -qy docker.io

Не обновляйте Docker на этом хосте. Использовать более свежие версии для сборки образов можно в инструментарии CI или на ноутбуке.

Установка


  • Установите apt-репозиторий Kubernetes.

$ apt-get update && apt-get install -y apt-transport-https
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
OK

$ cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main  
EOF

Теперь обновите список пакетов командой apt-get update.


  • Установите kubelet, kubeadm и kubernetes-cni.

kubelet отвечает за выполнение контейнеров на хостах кластера. kubeadm является удобной утилитой для настройки различных компонентов, составляющих кластер, а kubernetes-cni нужен для работы с сетевыми компонентами.


CNI расшифровывается как Container Networking Interface и представляет из себя спецификацию, определяющую взаимодействие сетевых драйверов с Kubernetes.

$ apt-get update
$ apt-get install -y kubelet kubeadm kubernetes-cni

  • Инициализируйте кластер с помощью kubeadm.

Из документации:


kubeadm предназначен для создания сразу «из коробки» безопасного кластера с помощью таких механизмов, как RBAC.

В Docker Swarm по умолчанию есть драйвер оверлейной сети, но с kubeadm решение остается за нами. Команда все еще работает над обновлением инструкций, поэтому я покажу, как использовать драйвер, наиболее похожий на докеровский, — flannel от CoreOS.


Flannel


Flannel позволяет организовать программно определяемую сеть (Software Defined Network, SDN), используя для этого модули ядра Linux overlay и ipvlan.


В Packet машина подключается к двум сетям: первая — это сеть дата-центра, которая соединяет хосты, входящие в определенный регион и проект, а вторая — это выход в Интернет. Брандмауэр по умолчанию не настроен, поэтому при желании ограничить сетевую активность придется настроить iptables или ufw вручную.


Внутренний IP-адрес можно выяснить с помощью ifconfig:


root@kubeadm:~# ifconfig bond0:0  
bond0:0   Link encap:Ethernet  HWaddr 0c:c4:7a:e5:48:d4  
          inet addr:10.80.75.9  Bcast:255.255.255.255  Mask:255.255.255.254
          UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1

Воспользуемся этим внутренним IP-адресом для трансляции Kubernetes API.


$ kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=10.80.75.9 --skip-preflight-checks --kubernetes-version stable-1.6

  • --pod-network-cidr необходим драйверу flannel и определяет адресное пространство для контейнеров.
  • --apiserver-advertise-address определяет IP-адрес, который Kubernetes будет афишировать в качестве своего API-сервера.
  • --skip-preflight-checks позволяет kubeadm не проверять ядро хоста на наличие требуемых функций. Это нужно из-за отсутствия метаданных ядра на хостах Packet.
  • --kubernetes-version stable-1.6 жестко определяет версию кластера (в данном случае 1.6); при желании использовать, например, Kubernetes 1.7 пропустите этот флаг.

Вот что мы должны получить на выходе:


[init] Using Kubernetes version: v1.6.6
[init] Using Authorization mode: RBAC
[preflight] Skipping pre-flight checks
[certificates] Generated CA certificate and key.
[certificates] Generated API server certificate and key.
[certificates] API Server serving cert is signed for DNS names [kubeadm kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.80.75.9]
[certificates] Generated API server kubelet client certificate and key.
[certificates] Generated service account token signing key and public key.
[certificates] Generated front-proxy CA certificate and key.
[certificates] Generated front-proxy client certificate and key.
[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[apiclient] Created API client, waiting for the control plane to become ready
[apiclient] All control plane components are healthy after 36.795038 seconds
[apiclient] Waiting for at least one node to register
[apiclient] First node has registered after 3.508700 seconds
[token] Using token: 02d204.3998037a42ac8108
[apiconfig] Created RBAC rules
[addons] Created essential addon: kube-proxy
[addons] Created essential addon: kube-dns

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run (as a regular user):

  sudo cp /etc/kubernetes/admin.conf $HOME/
  sudo chown $(id -u):$(id -g) $HOME/admin.conf
  export KUBECONFIG=$HOME/admin.conf

You should now deploy a pod network to the cluster.  
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:  
  http://kubernetes.io/docs/admin/addons/

You can now join any number of machines by running the following on each node  
as root:

  kubeadm join --token 02d204.3998037a42ac8108 10.80.75.9:6443

  • Создайте непривилегированного пользователя.

В установке Ubuntu от Packet нет обычного пользователя, поэтому давайте создадим его.


# useradd packet -G sudo -m -s /bin/bash
# passwd packet

  • Настройте переменные окружения для нового пользователя.

Теперь, используя приведенное выше сообщение о создании кластера, можно настроить переменные окружения.


Войдите под учетной записью нового пользователя: sudo su packet.


$ cd $HOME
$ sudo whoami

$ sudo cp /etc/kubernetes/admin.conf $HOME/
$ sudo chown $(id -u):$(id -g) $HOME/admin.conf
$ export KUBECONFIG=$HOME/admin.conf

$ echo "export KUBECONFIG=$HOME/admin.conf" | tee -a ~/.bashrc

  • Примените конфигурацию сети для подов (flannel).

Теперь с помощью kubectl и двух записей из документации flannel мы применим к кластеру конфигурацию сети:


$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel-rbac.yml
clusterrole "flannel" created  
clusterrolebinding "flannel" created

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

serviceaccount "flannel" created  
configmap "kube-flannel-cfg" created  
daemonset "kube-flannel-ds" created 

Сеть для подов сконфигурирована.


  • Разрешите использование однохостового (single-host) кластера.

Обычно в кластер Kubernetes входит несколько хостов, поэтому по умолчанию контейнеры не могут быть запущены на мастере. Но поскольку у нас только одна нода, разрешим на ней запуск контейнеров с помощью операции taint.


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

В качестве альтернативы можно было бы добавить в кластер вторую машину, используя join token из вывода kubeadm.

  • Проверьте работоспособность кластера.

Многие компоненты Kubernetes выполняются в виде контейнеров кластера в скрытом пространстве имен kube-system. Вывести информацию о них можно следующим образом:


$ kubectl get all --namespace=kube-system

NAME                                 READY     STATUS    RESTARTS   AGE  
po/etcd-kubeadm                      1/1       Running   0          12m  
po/kube-apiserver-kubeadm            1/1       Running   0          12m  
po/kube-controller-manager-kubeadm   1/1       Running   0          13m  
po/kube-dns-692378583-kqvdd          3/3       Running   0          13m  
po/kube-flannel-ds-w9xvp             2/2       Running   0          1m  
po/kube-proxy-4vgwp                  1/1       Running   0          13m  
po/kube-scheduler-kubeadm            1/1       Running   0          13m

NAME           CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE  
svc/kube-dns   10.96.0.10   <none>        53/UDP,53/TCP   14m

NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE  
deploy/kube-dns   1         1         1            1           14m

NAME                    DESIRED   CURRENT   READY     AGE  
rs/kube-dns-692378583   1         1         1         13m 

Как видно из листинга, все сервисы находятся в состоянии Running, значит, с кластером все в порядке. Если эти компоненты находятся в состоянии загрузки из Интернет, они могут быть еще не запущены.


Запустите контейнер


Теперь в кластере можно запустить контейнер. В Kubernetes контейнеры организованы в поды (Pods), которые используют общий IP-адрес, привязаны к одной и той же ноде (хосту) и могут использовать общие тома.


Проверьте, что сейчас у вас нет запущенных подов (контейнеров):


$ kubectl get pods

Теперь с помощью kubectl run запустите контейнер. Мы развернем Node.js- и Express.js-микросервис, генерирующий идентификаторы GUID по HTTP.


Этот код был изначально написан для руководства по Docker Swarm. Соответствующие исходники можно найти по этой ссылке: Scale a real microservice with Docker 1.12 Swarm Mode

$ kubectl run guids --image=alexellis2/guid-service:latest --port 9000
deployment "guids" created  

Теперь в колонке Name можно увидеть, какое имя было назначено новому поду и когда он был запущен:


$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE  
guids-2617315942-lzwdh   0/1       Pending   0          11s  

Используйте Name для проверки состояния пода:


$ kubectl describe pod guids-2617315942-lzwdh
...
Pulling            pulling image "alexellis2/guid-service:latest"  
...

Раз у нас есть работающей контейнер, можно взять его IP-адрес и получать сгенерированные идентификаторы с помощью curl:


$ kubectl describe pod guids-2617315942-lzwdh | grep IP:
IP:        10.244.0.3

$ curl http://10.244.0.3:9000/guid ; echo
{"guid":"4659819e-cf00-4b45-99d1a9f81bdcf6ae","container":"guids-2617315942-lzwdh"}

$ curl http://10.244.0.3:9000/guid ; echo
{"guid":"1604b4cb-88d2-49e2-bd38-73b589da0469","container":"guids-2617315942-lzwdh"}

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


$ kubectl logs guids-2617315942-lzwdh
listening on port 9000  

Очень полезной функцией для отладки контейнеров является возможность подключаться к их консоли и выполнять там различные команды:


$ kubectl exec -t -i guids-2617315942-lzwdh sh
/ # head -n3 /etc/os-release
NAME="Alpine Linux"  
ID=alpine  
VERSION_ID=3.5.2  
/ # exit

  • Панель инструментов (Dashboard).

Панель инструментов Kubernetes также устанавливается в качестве пода, к которому мы потом сможем обратиться на локальной машине. Поскольку мы не открывали Kubernetes выход в Интернет, для доступа к панели инструментов воспользуемся SSH-туннелем.


$ kubectl create -f https://git.io/kube-dashboard
$ kubectl proxy
Starting to serve on 127.0.0.1:8001  

Теперь создадим туннель на хост Packet и откроем в веб-браузере страницу http://localhost:8001/ui/.


$ ssh -L 8001:127.0.0.1:8001 -N



Более подробную информацию можно получить здесь: Dashboard check it out on Github.


Подведем итоги


Вы создали кластер Kubernetes и запустили свой первый микросервис. Теперь вы можете начать изучать компоненты кластера, используя в работе интерфейс командной строки kubectl.


  • Учитесь на примерах.

Руководство Kubernetes by Example, созданное Michael Hausenblas, показалось мне детальным и доступным.


  • Добавьте больше нод.

Состоящий из одной ноды кластер у нас теперь есть, можно начинать добавлять еще ноды Type 0, используя join token, полученный от kubeadm.


  • Сравните с Docker Swarm.

Docker Swarm — это встроенный в Docker CE и EE инструмент оркестровки. Кластер Docker Swarm может быть поднят одной командой. Более подробную информацию можно почерпнуть из моих уроков по Docker Swarm.


Благодарности:


Спасибо @mhausenblas, @_errm и @kubernetesonarm за обратную связь и советы по настройке кластера Kubernetes.


Ссылки:


  1. Оригинал: Kubernetes on bare-metal in 10 minutes.

Комментарии (31)


  1. inook
    15.08.2017 09:56

    Digital Ocean так-то дешевле, можно за $5 почувствовать себя DevOps«ом


    1. r-moiseev
      15.08.2017 11:39

      В Scaleway за 2.99 и машинка получше