Изучаем Kubernetes с помощью Minikube & Docker на MacOS

Совсем недавно я узнал как управлять кластером Kubernetes с помощью изящного инструмента Minikube, который запускает кластер  внутри виртуальной машины на вашей локальной рабочей станции всего с одним узлом.

Minikube – это не только отличная локальная среда разработки, но еще и один из способов узнать наиболее распространенные команды, которые создают вашу «мышечную память»(действия на автомате).

Этот мануал немножко расширенный “Hello word” для новичков в Kubernetes.

Вступление

Kubernetes – популярная система с открытым исходным кодом для автоматизации развертывания, масштабирования и управления контейнерами(контейнерные приложения), группируя их в логические блоки для удобства работы с ними.

Кластер Kubernetes состоит из двух типов:

● Мастер(Master) координирует работу кластера

● Узлы(Nodes) – это своеобразные рабочие, которые запускают приложения

Kubernetes основан на внутреннем планировщике задач Google под названием Borg, который использовался для запуска масштабных рабочих нагрузок.

Сегодня этот проект с открытым исходным кодом поддерживается технологическими партнерами, которые используют Kubernetes  как часть инфраструктуры в своих масштабных проектах. Проект также обладает надежным сообществом в GitHub, Slack channel и группе разработчиков Google, которые вы обязательно должны посетить.

Установка

Установка Minikube на MacOS (Sierra) проста. Несколько простых команд и ваш кластер установлен и запущен.

Если вы счастливый обладатель Linux или Windows, то ознакомьтесь с другим руководством.

Что нам нужно?

Чтобы использовать Minikube, нам нужен гипервизор (англ. Hypervisor) и инструмент командной строки Kubernetes kubectl.

Мой выбор пал на VirtualBox и Docker,  но есть и другие варианты.

Все что нам нужно мы можем установить одной простой командой brew:

$ brew update && brew install kubectl && brew cask install docker minikube virtualbox

Теперь убедитесь, что все прошло успешно – просто проверьте какие версии вы сейчас используете:

$ docker –version # docker version X.X.X, build abc123
docker-compose –version # docker-compose version X.X.X, build abc123
docker-machine –version # docker-machine version X.X.X, build abc123
minikube version # minikube version vX.X.X
kubectl version –client # Client Version: version.Info(…)

Minikube

Давайте пойдем дальше и запустим кластер minikube:

$ minikube start
Starting local Kubernetes v1.6.4 cluster…
Starting VM…
SSH-ing files into VM…
Setting up certs…
Starting cluster components…
Connecting to cluster…
Setting up kubeconfig…
Kubernetes is available at https://192.168.99.100:8443.
Kubectl is now configured to use the cluster.

И выглядит это как-то так:

photo_2017-06-28_10-20-05

Наш локальный кластер Kubernetes теперь запущен. И обратите внимание, что kubectl уже настроен на пользование нашего кластера. Это  можно понять из последней строки на скриншоте:

photo_2017-06-28_10-20-14

Теперь давайте проверим статус minikube:

$ minikube status
minikube: Running
localkube: Running

Kubernetes также имеет довольно простой в использовании графический интерфейс, давайте посмотрим на панель мониторинга вашего кластера Minikube:

$ minikube dashboard

Screen-Shot-2017-06-10-at-9.30.37-PM

Kubernetes

В документе Kubernetes Basics содержатся все полезные диаграммы и интерактивная учебная «оболочка», которая отлично подходит для ознакомления с наиболее часто используемыми командами. Я настоятельно рекомендую вам потратить 20-30 минут и начальная база знаний об этом инструменте у вас в кармане.

Kubectl

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

Сначала давайте выведаем любую информацию у кластера kubectl:

$ kubectl cluster-info
Kubernetes master is running at https://192.168.99.100:8443

Адрес 192.168.99.100 – это внешний IP кластера minikube, назначенный DHCP.

Теперь давайте узнаем базовую информацию о нашем кластере: например сколько узлов у нас работает(подсказка: minikube запускает один узел при помощи виртуальной машины):

photo_2017-06-28_10-20-24

Сама команда:

$ kubectl get nodes
NAME STATUS AGE VERSION
minikube Ready 1m v1.6.4

Теперь давайте определим, какие контейнеры могут работать:

$ kubectl get pods –all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system kube-addon-manager-minikube 1/1 Running 1 5m
kube-system kube-dns-196007617-bhrsr 3/3 Running 1 5m
kube-system kubernetes-dashboard-r0rtq 1/1 Running 1 5m

kubeconfig

В настоящий момент единственным кластером должен быть «minikube», но давайте уж сделаем все наверняка, чтобы не было проблем в дальнейшем:

$ kubectl config use-context minikube
Switched to context “minikube”.

Убедитесь, что все верно с помощью current-context:

$ kubectl config current-context
minikube

Теперь, когда мы установили и подтвердили наш contex, давайте посмотрим на весь kubeconfig:

$ kubectl config view
apiVersion: v1
clusters:
– cluster:
certificate-authority: /Users/jmac/.minikube/ca.crt
server: https://192.168.99.100:8443
name: minikube
contexts:
– context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
– name: minikube
user:
client-certificate: /Users/jmac/.minikube/apiserver.crt
client-key: /Users/jmac/.minikube/apiserver.key  

Деплоим  Hello World

Проект minikube на GitHub предлагает демонстрацию быстрого запуска, которую мы можем развернуть и в которой используется предварительно построенное приложение Docker, называемое hello-minikube (доступное из общедоступного контейнерного хранилища google) – эквивалент Kubernetes для «Hello World!».

Так что давайте развернем и запустим  все это дело!

$ kubectl run hello-minikube –image=gcr.io/google_containers/echoserver:1.4 –port=8080
deployment “hello-minikube” created

Успех ) ! Давайте убедимся, что все прошло нормально:

$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-minikube 1 1 1 1 18s

Kubernetes dashboard доступен на http://localhost:8080/ui:

1

Что у нас насчет pods (группа контейнеров с общими разделами, запускаемых как единое целое)?

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-minikube-938614450-zfrhp 1/1 Running 0 55s

Kubernetes dashboard, в которой вы можете увидеть все ваши pods:

photo_2017-06-28_10-21-04 Ну и вот вам скрин всех выше описанных команд для наглядности:

DeepinScreenshot20170629104200

Отлично, теперь мы должны открыть наше приложение для внешнего доступного IP с помощью команды expose:

$ kubectl expose deployment hello-minikube –type=NodePort
service “hello-minikube” exposed

Посмотрим, какие службы запущены:

$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-minikube 10.0.0.189 8080:31406/TCP 1m
kubernetes 10.0.0.1 443/TCP 1h

Чтобы получить URL-адрес вашего открытого сервиса, вы можете использовать команду minikube:

$ minikube service hello-minikube –url
http://192.168.99.100:31406

Вы можете также дополнить команду выше curl -ом, чтобы получить ответ:

$ curl $(minikube service hello-minikube –url)
CLIENT VALUES:
client_address=172.17.0.1
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://192.168.99.100:8080/
SERVER VALUES:
server_version=nginx: 1.10.0 – lua: 10001
HEADERS RECEIVED:
accept=*/*
host=192.168.99.100:31406
user-agent=curl/7.51.0
BODY:

Вот как все это выглядит:

DeepinScreenshot20170629104233

Ну все!!! Убираем игрушки в коробку и приступаем к серьезным делам – сначала удалим сервис и развертывание:

$ kubectl delete deployment,service hello-minikube
deployment “hello-minikube” deleted
service “hello-minikube” deleted

И убеждаемся что все удалено:

$ kubectl get deployments
No resources found.
$ kubectl get pods
No resources found.

Деплой веб-службы с помощью Docker

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

$ mkdir hello-nodejs && cd hello-nodejs && touch Dockerfile server.js

Создание веб-службы

Создаем базовый http-сервер, используя nodeJS, который будет возвращает HTTP 200 и ответ Hello Hello!:

$ vim server.js
var http = require(‘http’);
var handleRequest = function(request, response){
console.log(“rx request for url:” + request.url);
response.writeHead(200)
response.end(‘Hello World!’)
};
var www = http.createServer(handleRequest);
www.listen(8080);

Создание контейнера с помощью Docker

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

FROM node:6.9.2
EXPOSE 8080
COPY server.js .
CMD node server.js

Для minikube должны быть установлены переменные окружения Docker:

$ eval $(minikube docker-env)

Достаточно просто? Хорошо, давайте теперь построим контейнер!

$ docker build -t hello-node:v1 .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM node:6.9.2
—> faaadb4aaf9b
Step 2 : EXPOSE 8080
—> Using cache
—> e78d6f95b487
Step 3 : COPY server.js .
—> Using cache
—> 30a49bb02305
Step 4 : CMD node server.js
—> Using cache
—> eb22cf1abcf6
Successfully built eb22cf1abcf6

Деплой приложения

Ну так не бойтесь,  запускайте:

$ kubectl run hello-nodejs –image=hello-nodejs:v1 –port=8080
deployment “hello-nodejs” created

Теперь можно проверять  развертывание и контейнеры:

$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-nodejs 1 1 1 1 1m

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-node-2686040790-0t8q4 1/1 Running 0 1m

Далее мы указываем инструкцию EXPOSEс которая говорит Docker, что наше новое приложение в контейнере должно использовать определенный порт:

$ kubectl expose deployment hello-nodejs –type=NodePort
service “hello-nodejs” exposed

Проверяем, что все правильно запущено и работает:

$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-nodejs 10.0.0.13 8080:32272/TCP 2m
kubernetes 10.0.0.1 443/TCP 1dм

Но мы не будем верить на слово и проверим функциональность:

$ curl $(minikube service hello-nodejs –url)
Hello World!

Ура! Мы сделали это! Мы написали наш собственный простой веб-сервис,«упаковали» его в контейнер и развернули его в кластере Kubernetes!

Удаляем приложение

Теперь, когда мы знаем, как разворачивать приложение, давайте выведем из эксплуатации это приложение, удалив развертывание и службу:

$ kubectl delete deployment,service hello-nodejs
deployment “hello-nodejs” deleted
service “hello-nodejs” deleted

Убедитесь что вы все сделали правильно:

$ kubectl get deployments,services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/kubernetes 10.0.0.1 443/TCP 1d

Выключаем Minikube

И теперь, когда мы все сделали, давайте закроем minikube:

$ minikube stop
Stopping local Kubernetes cluster…
Machine stopped.

Почему контейнеры?

“Old Way” (старый способ) деплоя приложений заключался в установке приложений на хост с помощью диспетчера пакетов. Все это приводило к запутыванию библиотечных файлов, используемых как приложениями, так и операционной системой хоста. Соответственно дальнейшая поддержка становилась просто невозможна.

“New Way” (новый способ) – это развертывание контейнеров на основе виртуализации уровня операционной системы, а не аппаратной виртуализации. Контейнеры изолированы друг от друга,  имеют свои собственные файловые системы,  не видят процессы друг друга, что также ограничивает использование ресурсов. Самая главная фишка – обособленность от базовой инфраструктуры. Вы сможете легко перенести приложение в другую среду: достаточно загрузить образ в репозиторий и скачать его на сервере.

Методы Kubectl

Инструмент командной строки kubectl поддерживает несколько различных подходов к созданию и управлению объектами Kubernetes. Существует три метода: императивные команды, конфигурация императивных объектов и конфигурация декларативных объектов.

При использовании императивных команд пользователь работает непосредственно с живыми объектами в кластере, предоставляя операции команде kubectl в качестве аргументов или флагов.

Примеры:

$ kubectl run nginx –image nginx
$ kubectl create deployment nginx –image nginx

При использовании императивной конфигурации объекта команда kubectl указывает операцию, необязательные флаги и по крайней мере одно имя файла. Указанный файл должен содержать полное определение объекта в формате YAML или JSON.

Примеры:

$ kubectl create -f nginx.yaml
$ kubectl delete -f nginx.yaml -f redis.yaml
$ kubectl replace -f nginx.yaml

При использовании конфигурации декларативных объектов пользователь работает с файлами конфигурации объектов, хранящимися локально, однако пользователь не определяет операции, которые должны выполняться в файлах.

Примеры:

$ kubectl apply -f configs/
$ kubectl apply -R -f configs/