С развитием инфраструктуры docker-контейнеров появляется необходимость управления большим числом docker-контейнеров. Для этой цели служат системы:
- Kubernetes развиваемый компанией Google
- Mesos развиваемый в сообществе Apache
- Docker Swarm от создателей Docker.
Компания Google утверждает, что уже более 9-ти лет использует в своей работе контейнеры. Поэтому разрабатываемая ими система Kubernetes является на сегодня стабильной и продвинутой.
С помощью этой статьи вы сможете легко развернуть кластер kubernetes из мастера и двух нод. И легко добавлять node-машины в дальнейшем. Мастер нода имеет API для управления кластером и дирежирует контейнерами. Ноды получают команды от мастера и запускают контейнеры.
Для начала нужно иметь 2 сервера и установить на них Docker.
Мы будем использовать 2 Docker-демона на каждом сервере:
- Docker начальной загрузки для запуска flanneld и etcd;
- Основной Docker для запуска инфраструктуры Kubernetes и запуска наших контейнеров.
Потребность в двух docker-демонах необходима по той причине, что для объединения всех контейнеров в единую сеть, будет использоваться демон flannel. Он должен запускаться не в основном Docker.
Настройка мастера
Мастер настраивается в 2 этапа:
- установка flanneld и etcd
- запуск компонент мастера
Для простоты, инициализируем переменную с IP адресом мастера:
export MASTER_IP=<IP адрес мастера, например 1.2.3.4>
Запускаем вспомогательный docker
sudo sh -c 'docker -d -H unix:///var/run/docker-bootstrap.sock \
-p /var/run/docker-bootstrap.pid \
--iptables=false \
--ip-masq=false \
--bridge=none \
--graph=/var/lib/docker-bootstrap \
2> /var/log/docker-bootstrap.log 1> /dev/null &'
Этот docker запускается с опцией --iptables=false, чтобы запускаемые им контейнеры работали только с опцией --net=host.
Запускаем etcd для flannel и API
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
--restart=always \
--net=host
-d gcr.io/google_containers/etcd:2.0.12 \
/usr/local/bin/etcd --addr=127.0.0.1:4001 \
--bind-addr=0.0.0.0:4001 \
--data-dir=/var/etcd/data
Прописываем в etcd сеть для flannel
Сеть не должна пересекаться с уже имеющимися сетями:
Сеть не должна пересекаться с уже имеющимися сетями:
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
--net=host \
gcr.io/google_containers/etcd:2.0.12 \
etcdctl set /coreos.com/network/config '{ "Network": "10.1.0.0/16" }'
Устанавливаем flannel на мастер-ноде
Flannel перенастраивает bridge, который настроил Docker. Поэтому надо остановить основной Docker, запустить Flannel и снова запустить Docker.
Останавливаем Docker
sudo service docker stop
Запускаем flannel
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
-d \
--restart=always \
--net=host \
--privileged \
-v /dev/net:/dev/net \
quay.io/coreos/flannel:0.5.0
Эта команда выведет длинный хеш, который будет использоваться в следующей команде. Скопируйте его.
Получаем настройки flannel-сети
sudo docker -H unix:///var/run/docker-bootstrap.sock \
exec <длинный-хеш> cat /run/flannel/subnet.env
Пример вывода этой команды:
FLANNEL_SUBNET=10.1.10.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
Добавляем вспомогательный Docker в автозагрузку
Создаём файл /lib/systemd/system/docker-bootstrap.socket с таким содержимым:
[Unit]
Description=Docker Socket for the API
PartOf=docker-bootstrap.service
[Socket]
ListenStream=/var/run/docker-bootstrap.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
И файл /lib/systemd/system/docker-bootstrap.service с таким содержимым:[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker-bootstrap.socket
Requires=docker-bootstrap.socket
[Service]
ExecStart=/usr/bin/docker -d -H unix:///var/run/docker-bootstrap.sock -p /var/run/docker-bootstrap.pid --iptables=false --ip-masq=false --bridge=none --graph=/var/lib/docker-bootstrap
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
В файл /lib/systemd/system/docker.service после After=network.target docker.socket
добавляем docker-bootstrap.service
После этого перечитываем конфиги systemctl
systemctl daemon-reload
systemctl enable docker-bootstrap
Настраиваем основной Docker
В конфиругационном файле или в скрипте запуска (для Ubuntu это /etc/default/docker или /etc/systemd/service/docker.service) нужно добавить:
--bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
Вместо FLANNEL_SUBNET и FLANNEL_MTU нужно прописать параметры из вывода предыдущей команды.
Команда запуска основного докера должа получится примерно такой:
/usr/bin/docker -d -H fd:// --bip="10.1.10.1/24" --mtu=1472
Удаляем существующий Docker bridge
По-умолчанию Docker создаёт bridge и именем docker0. Удалим его
sudo /sbin/ifconfig docker0 down
sudo brctl delbr docker0
Запускаем запускаем основной Docker
sudo service docker start
Запускаем kubernetes мастер
sudo docker run \
--volume=/:/rootfs:ro \
--volume=/sys:/sys:ro \
--volume=/dev:/dev \
--volume=/var/lib/docker/:/var/lib/docker:rw \
--volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
--volume=/var/run:/var/run:rw \
--net=host \
--privileged=true \
--pid=host \
--restart=always \
-d \
gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube kubelet --api-servers=http://localhost:8080 --v=2 --address=0.0.0.0 --enable-server --hostname-override=127.0.0.1 --config=/etc/kubernetes/manifests-multi --cluster-dns=10.0.0.10 --cluster-domain=cluster.local
Примечание: --cluster-dns и --cluster-domain нужны для запуска внутреннего DNS сервера. Можно исключить их из команды запуска мастера.
Примечание 2: если при запуске этого контейнера появляется ошибка "System error: The minimum allowed cpu-shares is 1024", то лечится она добавлением параметра --exec-opt native.cgroupdriver=cgroupfs в команду запуска основого Docker.
Запускаем service proxy для kubernetes
Service proxy обеспечивает балансировку нагрузку между группами контейнеров объединёных в Kubernetes services
sudo docker run -d --restart=always \
--net=host \
--privileged \
gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube proxy --master=http://127.0.0.1:8080 --v=2
Теперь у нас есть настроенный кластер из одной ноды и мастера. Можем протестировать это.
Скачаем утилиту kubectl
wget -O /usr/bin/kubectl http://storage.googleapis.com/kubernetes-release/release/v1.1.3/bin/linux/amd64/kubectl
chmod +x /usr/bin/kubectl
Запустим команду
kubectl get nodes
Пример вывода этой команды:
NAME LABELS STATUS
127.0.0.1 kubernetes.io/hostname=127.0.0.1 Ready
Добавление ноды в кластер
Добавление ноды во многом повторяет настройку мастера. Процесс состоит из 3 шагов
- запуск flanneld
- запуск kubernetes
- добавление ноды в кластер
Инициализируем 2 переменные:
export MASTER_IP=<IP адрес мастера, например 1.2.3.4>
export NODE_IP=<IP адрес ноды, например 4.3.2.1>
Запуск flanneld
Запускаем Docker для начальной загрузки
sudo sh -c 'docker -d -H unix:///var/run/docker-bootstrap.sock \
-p /var/run/docker-bootstrap.pid \
--iptables=false \
--ip-masq=false \
--bridge=none \
--graph=/var/lib/docker-bootstrap \
2> /var/log/docker-bootstrap.log 1> /dev/null &'
Останавливаем основной Docker
sudo service docker stop
Запускаем flannel
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
-d \
--net=host \
--privileged \
-v /dev/net:/dev/net \
quay.io/coreos/flannel:0.5.0 /opt/bin/flanneld --etcd-endpoints=http://${MASTER_IP}:4001
Эта команда выведет длинный хеш, который будет использоваться в следующей команде. Скопируйте его.
Получаем настройки flannel-сети
sudo docker -H unix:///var/run/docker-bootstrap.sock \
exec <длинный-хеш> cat /run/flannel/subnet.env
Пример вывода этой команды:
FLANNEL_SUBNET=10.1.90.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
Настраиваем основной Docker
В конфиругационном файле или в скрипте запуска (для Ubuntu это /etc/default/docker или /etc/systemd/service/docker.service) нужно добавить:
--bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
Вместо FLANNEL_SUBNET и FLANNEL_MTU нужно прописать параметры из вывода предыдущей команды.
Команда запуска основного докера должа получится примерно такой:
/usr/bin/docker -d -H fd:// --bip="10.1.90.1/24" --mtu=1472
Удаляем существующий Docker bridge
sudo /sbin/ifconfig docker0 down
sudo brctl delbr docker0
Запускаем запускаем основной Docker
sudo service docker start
Запуск kubernetes для ноды
Запускаем kubelet
sudo docker run \
--volume=/:/rootfs:ro \
--volume=/sys:/sys:ro \
--volume=/dev:/dev \
--volume=/var/lib/docker/:/var/lib/docker:rw \
--volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
--volume=/var/run:/var/run:rw \
--net=host \
--privileged=true \
--pid=host \
-d \
gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube kubelet --api-servers=http://localhost:8080 --v=2 --address=0.0.0.0 --enable-server --hostname-override=127.0.0.1 --config=/etc/kubernetes/manifests-multi --cluster-dns=10.0.0.10 --cluster-domain=cluster.local
Примечание: --cluster-dns и --cluster-domain можно исключить из этой команды
Запуск service proxy
sudo docker run -d \
--net=host \
--privileged \
gcr.io/google_containers/hyperkube:v1.1.3 /hyperkube proxy --master=http://${MASTER_IP}:8080 --v=2
Теперь, выполнив на мастере команду kubectl get nodes, мы увидим, что новая нода включена в кластер.
NAME LABELS STATUS
127.0.0.1 kubernetes.io/hostname=127.0.0.1 Ready
NODE_IP kubernetes.io/hostname=NODE_IP Ready
Сделано на основе документации:
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/getting-started-guides/docker-multinode/master.md
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/getting-started-guides/docker-multinode/worker.md