Criação de um Loadbalancer com Haproxy e containers Docker

1. Introdução

Segue uma stack utilizando o Loadbalancer HAproxy e containers Docker, portanto este tutorial irá abordar a criação de um Loadbalancer com HAProxy e balanceamento de carga entre containers Docker.

2. Pré-requisitos

Docker instaladoTutorial instalação do Docker.

Comunicação entre containers – Todos os containers precisam se comunicar, o ping tem que funcionar partindo de qualquer container em qualquer host docker.
Sugiro utilizar a rede Flannel para fazer esta comunicação, e aqui segue o tutorial de instalação do Flannel+Docker.

3. Criação da imagem e containers para o NGINX

Vamos criar as imagens utilizando o Dockerfile. O foco deste tutorial não é Dockerfile, mas em resumo Dockerfile são arquivos com instruções para a criação de imagens Docker.
Está bem intuitivo, se você nunca mexeu com Dockerfile não terá nenhum problema.

Definição do Dockerfile Nginx.
#vi Nginx-Dockerfile

#Utilizar o Centos Latest
FROM centos

#Quem mantem e criou a imagem - informacoes de contato.
MAINTAINER Leonardo DevOpsLab "leonardo@devopslab.com.br"

#Instala o Nginx e configura o Nginx.
RUN yum install -y epel-release
RUN yum install -y nginx
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

#Start do Nginx
CMD ["nginx"]

Criação da imagem “nginximg” utilizando o Dockerfile “Nginx-Dockerfile”.

# docker build -t nginximg -f Nginx-Dockerfile .

O ponto final no comando é proposital.

Start do container rodando o Nginx.

# docker run -d -v /root/nginx-templates/index.html:/usr/share/nginx/html/index.html --name servidor-nginx1 -h servidor-nginx1.devopslab.com.br

Arquivo index.html está sendo compartilhado entre o host docker e o container através do parâmetro:
-v /root/nginx-templates/index.html:/usr/share/nginx/html/index.html“.
Você configura o arquivo index.html do jeito que você quiser.

Eu não preciso expor (EXPOSE) a porta do container Nginx, pois estou utilizando a rede Flannel, sendo assim todos os containers estão se comunicando, tem ping e acesso a todas as portas partindo de qualquer container da rede.

Repita o comando “docker run…” para todos os containers que você for criar.

4. Criação da Imagem Haproxy e criação do container de Loadbalancer

Definição do Dockerfile HAProxy.
#vi Haproxy-Dockerfile

#Utilizar o Centos Latest
FROM centos

#Quem mantem e criou a imagem - informacoes de contato.
MAINTAINER Leonardo leonardo@devopslab.com.br

#Instala o HAproxy.
RUN yum install -y haproxy

#Expor a porta 5000TCP no container.
EXPOSE 5000

#Start do haproxy
CMD ["haproxy", "-f", "/etc/haproxy/haproxy.cfg", "-p", "/var/run/haproxy.pid"]

Criação da imagem “haproxyimg” utilizando o Dockerfile “Haproxy-Dockerfile”.

# docker build -t haproxyimg -f HAproxy-Dockerfile .

Start do container HAproxy.

# docker run -d -p 80:5000 -v /root/dockerfiles/haproxy/haproxy.cfg:/etc/haproxy/haproxy.cfg --name loadbalancer-haproxy -h loadbalancer-haproxy.devopslab.com.br haproxyimg

Arquivo haproxy.cfg está sendo compartilhado entre o host docker e o container Haproxy através do parâmetro:
“-v /root/dockerfiles/haproxy/haproxy.cfg:/etc/haproxy/haproxy.cfg”.

Mapeamos a porta 80 do host para a porta 5000 do container:
-p 80:5000

Diferente dos containers rodando o Nginx, o Loadbalacer Haproxy precisa ter a porta 80 exposta, pois ela será acessível para o mundo.

Quando eu falo acessível para o mundo, quero dizer disponível em produção, acessível para clientes externos, ou simplesmente disponível para todas as redes do seu ambiente que não seja a rede do Docker.

Arquivo haproxy.cfg.
O arquivo haproxy.cfg foi copiado de uma instalação padrão do Haproxy.
* Foi comentado a linha “daemon”.
* Adicionei o pool de containers para responder pelas requisições, 5 containers no total.
* Foi definido uma url, no caso “exemplo.devopslab.com.br”.
* Tipo de balanceamento Roundrobin.

Segue o arquivo “haproxy.cfg” completo.

#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    #daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  main *:5000
    acl frontend-nginx	hdr(host) -i exemplo.devopslab.com.br
    use_backend servidores-nginx if frontend-nginx

backend servidores-nginx
    balance     roundrobin
    server  servidor-nginx1 10.0.96.2:80 check
    server  servidor-nginx2 10.0.12.3:80 check
    server  servidor-nginx3 10.0.89.3:80 check
    server  servidor-nginx4 10.0.58.2:80 check
    server  servidor-nginx5 10.0.91.2:80 check

5. Teste do Balanceamento de carga do HAproxy

Já está tudo pronto, então vamos testar.
Partindo de qualquer lugar da sua rede, faça um teste em direção do Loadbalancer; neste caso vou utilizar o comando “curl”.

$ for i in {1..10}; do echo "---------Teste curl $i-----------"; curl exemplo.devopslab.com.br; done
---------Teste curl 1-----------
SERVIDOR 1
servidor-nginx1

---------Teste curl 2-----------
SERVIDOR 2
servidor-nginx2

---------Teste curl 3-----------
SERVIDOR 3
servidor-nginx3

---------Teste curl 4-----------
SERVIDOR 4
servidor-nginx4

---------Teste curl 5-----------
SERVIDOR 5
servidor-nginx5

---------Teste curl 6-----------
SERVIDOR 1
servidor-nginx1

---------Teste curl 7-----------
SERVIDOR 2
servidor-nginx2

---------Teste curl 8-----------
SERVIDOR 3
servidor-nginx3

---------Teste curl 9-----------
SERVIDOR 4
servidor-nginx4

---------Teste curl 10-----------
SERVIDOR 5
servidor-nginx5

Utilizei um “for” bem simples, para fazer um get na url exemplo.devopslab.com.br.

6. Bônus

Docker Registry.
Se você tiver utilizando seu próprio Docker Registry para armazenar suas próprias imagens, o comando para iniciar um container seria algo assim:

# docker run -d -v /root/nginx-templates/index.html:/usr/share/nginx/html/index.html --name servidor-nginx5 -h servidor-nginx5.devopslab.com.br repo-dockerimages.devopslab.com.br:5000/nginximg

Segue aqui o Tutorial Docker Registry.

É nóis =)

[]’s
Leonardo

Kubernetes – como instalar e configurar o Kubernetes – K8S – Gerência de containers Docker

Tutorial Kubernetes – como instalar e configurar o Kubernetes, criação de cluster e Pods com Kubernetes.

1. Introdução

Kubernetes é um sistema Open Source desenvolvido pelo Google para o gerenciamento de cluster de containeres tendo como características auto-scaling de serviços e containeres, auto-monitoração de containeres, permite o deploy de containers e serviços, load balancer, orquestração de containers, e orquestração de volumes de armazenamento ‘storages’.

O Kubernetes amigávelmente pode ser chamado de K8S, inventaram isto no Google, eu li em um dos Docs do Kubernetes e seria algo como K[eight-characters]S, o que faz todo sentido.

Mais uma pequena curiosidade, Kubernetes é derivado de uma palavra grega Kuvernetes, que significa timoneiro, aquele cara que pilota o Navio, por isto que o logo do Kuvernetes é um timão de navio.

Minions – São todos os hosts que fazem parte do cluster gerenciado pelo Kubernetes.
Serviços rodando nos Minios: kube-proxy kubelet docker e flannel

Flannel – É uma rede virtual que vai provisionar uma sub-rede para cada host do cluster, esta sub-rede será utilizada para alocar um ip para cada container e fazer a comunicação entre os containers.

Etcd – É um sistema distribuído de armazenamento do tipo key valor ou key=valor, utilizado pelo Kubernetes para armazenar todas informações sobre os Pods, containers, serviços, redes, nós do cluster, localização dos containeres, Cpus, Memória, versões de aplicativos e metados no geral.

Pod – É um grupo de um ou mais containers rodando dentro de um host/minion do cluster.

Replication Controller “RC” – Vai garantir que um determinado número de Pods estejam sempre rodando, ele monitora o cluster e em caso de algum Pod falhar, ficar off-line e etc, o replication controller tratará de subir um novo container ao Pod, mantendo o cluster funcional.

2. Pré-requisitos e Infraestrutura

Pré-requisitos
Sistema Operacional Centos 7 x86_64 instalação mínima.

Hosts – Infraestrutura
Vou utilizar um host para ser o Kubernetes e 3 Minions. Minions podem ser a quantidade que você quiser.

10.0.2.30 kubernetes-master1.devopslab.com.br
10.0.2.31 kubernetes-minion1.devopslab.com.br
10.0.2.32 kubernetes-minion2.devopslab.com.br
10.0.2.33 kubernetes-minion3.devopslab.com.br

3. DNS – Configuração do DNS

Configure o /etc/hosts de todos os nós do cluster “minions” para ter os apontamentos de DNS. Basicamente copie as informações de dns acima para todos os hosts.

4. Configuração do repositório para a instalação de pacotes

Crie o repositório em todos os hosts MASTER e MINIONS.

#vi /etc/yum.repos.d/virt7-docker-common-release.repo

[virt7-docker-common-release]
name=virt7-docker-common-release
baseurl=http://cbs.centos.org/repos/virt7-docker-common-release/x86_64/os/
gpgcheck=0

5. Instalação do Kubernetes e Docker

MASTER
#yum install kubernetes flannel etcd
O pacote kubernetes também vai instalar o Docker entre outras dependências.

#yum install kubernetes flannel etcd
...
Dependencies Resolved

==============================================================================================================================================================================================
 Package                                             Arch                               Version                                                      Repository                          Size
==============================================================================================================================================================================================
Installing:
 etcd                                                x86_64                             2.2.5-1.el7                                                  extras                             5.3 M
 flannel                                             x86_64                             0.5.3-9.el7                                                  extras                             1.7 M
 kubernetes                                          x86_64                             1.2.0-0.9.alpha1.gitb57e8bd.el7                              extras                              34 k
Installing for dependencies:
 audit-libs-python                                   x86_64                             2.4.1-5.el7                                                  base                                69 k
 checkpolicy                                         x86_64                             2.1.12-6.el7                                                 base                               247 k
 docker                                              x86_64                             1.9.1-25.el7.centos                                          extras                              13 M
 docker-forward-journald                             x86_64                             1.9.1-25.el7.centos                                          extras                             824 k
 docker-selinux                                      x86_64                             1.9.1-25.el7.centos                                          extras                              70 k
 kubernetes-client                                   x86_64                             1.2.0-0.9.alpha1.gitb57e8bd.el7                              extras                             9.3 M
 kubernetes-master                                   x86_64                             1.2.0-0.9.alpha1.gitb57e8bd.el7                              extras                              15 M
 kubernetes-node                                     x86_64                             1.2.0-0.9.alpha1.gitb57e8bd.el7                              extras                             9.3 M
 libcgroup                                           x86_64                             0.41-8.el7                                                   base                                64 k
 libsemanage-python                                  x86_64                             2.1.10-18.el7                                                base                                94 k
 policycoreutils-python                              x86_64                             2.2.5-20.el7                                                 base                               435 k
 python-IPy                                          noarch                             0.75-6.el7                                                   base                                32 k
 setools-libs                                        x86_64                             3.3.7-46.el7                                                 base                               485 k
 socat                                               x86_64                             1.7.2.2-5.el7                                                base                               255 k

Transaction Summary
==============================================================================================================================================================================================
Install  3 Packages (+14 Dependent packages)

MINIONS

#yum install kubernetes flannel

6. Configuração do Kubernetes MASTER e os MINIONS

MASTER – Kubernetes Master.
MINIONS – Hosts Minions.

Desative o Firewall e Selinux em todos os hosts MASTER e MINIONS do cluster.

#systemctl stop firewalld.service
#systemctl disable firewalld.service
#sed -i s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config
#setenforce 0

6.1 – Configuração do Kubernetes Master

MASTER – Kubernetes Config

#vi /etc/kubernetes/config
Configure a linha KUBE_MASTER para apontar para o ip MASTER.

# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://kubernetes-master1.devopslab.com.br:8080"

MASTER – Apiserserver
Comente a linha KUBE_ADMISSION_CONTROL.
#vi /etc/kubernetes/apiserver

# The address on the local server to listen to.
KUBE_API_ADDRESS="--address=0.0.0.0"

# The port on the local server to listen on.
KUBE_API_PORT="--port=8080"

# Port minions listen on
KUBELET_PORT="--kubelet-port=10250"

# Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"

# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"

# default admission control policies
#KUBE_ADMISSION_CONTROL="--admission-#control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

# Add your own!
KUBE_API_ARGS=""

MASTER – ETCD
Verifique se a porta do Etcd é 2379.
Configure o bind para 0.0.0.0:2379.
#vi /etc/etcd/etcd.conf

ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"

MASTER – Restart dos serviços e habilitação do start no boot.

[root@kubernetes-master1 ~]# for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do 
        systemctl restart $SERVICES
        systemctl enable $SERVICES
        systemctl status $SERVICES 
done

MASTER – Definição de uma rede FLANNEL
Vamos criar uma rede para que seja alocada para cada novo container do cluster.
Normalmente é uma rede 172.17.0.0/16, porém vou mudar para uma do meu interesse.
Então vamos criar uma chave valor no Etcd.

Crie um arquivo .json em qualquer pasta do servidor Master e defina a rede.

#vi flannel-config.json

{
    "Network": "10.0.10.0/16",
    "SubnetLen": 24,
    "Backend": {
        "Type": "vxlan",
        "VNI": 1
     }
}

Agora faça a criação a Key no Etcd.

#etcdctl set /atomic.io/network/config < flannel-config.json

Verificando se a key foi criada com o comando
#etcdctl get /atomic.io/network/config

#etcdctl get /atomic.io/network/config
{
    "Network": "10.0.10.0/16",
    "SubnetLen": 24,
    "Backend": {
        "Type": "vxlan",
        "VNI": 1
     }
}

6.2 – Configuração dos Minions (Nodes)

Configuração dos hosts Minions.
Cada passo descrito abaixo deve ser feito em todos os hosts Minions da sua rede.

MINIONS – Kubernetes Config
Altere apenas a linha KUBE_MASTER e informe o servidor do Kubernetes.
#vi /etc/kubernetes/config

# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://kubernetes-master1.devopslab.com.br:8080"

MINIONS – KUBERLET
Aqui você vai informar qual é o servidor da Api, setar o hostname e bind do kuberlet.
#vi /etc/kubernetes/kubelet

###
# kubernetes kubelet (minion) config

# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=0.0.0.0"

# The port for the info server to serve on
# KUBELET_PORT="--port=10250"

# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=kubernetes-minion1.devopslab.com.br"

# location of the api-server
KUBELET_API_SERVER="--api-servers=http://kubernetes-master1.devopslab.com.br:8080"

# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"

# Add your own!
KUBELET_ARGS=""

MINIONS – rede FLANNEL
Será alterado apenas a linha que informa o ip do ETCD rodando no servidor MASTER.

#vi /etc/sysconfig/flanneld

# etcd url location.  Point this to the server where etcd runs
FLANNEL_ETCD="http://kubernetes-master1.devopslab.com.br:2379"

# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_KEY="/atomic.io/network"

# Any additional options that you want to pass
#FLANNEL_OPTIONS=""

Observe a linha: ‘FLANNEL_ETCD_KEY=”/atomic.io/network”
Esta key “/atomic.io/network” foi criada anteriormente no ETCD do Kubernetes Master.

MINIONS – Restart dos serviços e habilitação do start no boot

[root@kubernetes-minion1 ~]# for SERVICES in kube-proxy kubelet docker flanneld; do 
    systemctl restart $SERVICES
    systemctl enable $SERVICES
    systemctl status $SERVICES 
done

6.3 – Validação do MASTER e MINIONS

MINIONS
Verificação da rede.
Verifique se foram criadas as redes para o docker e flannel.

[root@kubernetes-minion1 ~]# ip -4 a|grep inet
    inet 127.0.0.1/8 scope host lo
    inet 10.0.2.31/24 brd 10.0.2.255 scope global enp0s3
    inet 10.0.10.1/24 scope global docker0
    inet 10.0.10.0/16 scope global flannel.1

Teste de consulta ao Etcd
#curl -s http://kubernetes-master1.devopslab.com.br:2379/v2/keys/atomic.io/network/subnets | python -mjson.tool

[root@kubernetes-minion1 ~]#curl -s http://kubernetes-master1.devopslab.com.br:2379/v2/keys/atomic.io/network/subnets | python -mjson.tool
{
    "action": "get",
    "node": {
        "createdIndex": 32,
        "dir": true,
        "key": "/atomic.io/network/subnets",
        "modifiedIndex": 32,
        "nodes": [
            {
                "createdIndex": 133,
                "expiration": "2016-04-03T01:08:09.060073648Z",
                "key": "/atomic.io/network/subnets/10.0.10.0-24",
                "modifiedIndex": 133,
                "ttl": 84138,
                "value": "{\"PublicIP\":\"10.0.2.31\",\"BackendType\":\"vxlan\",\"BackendData\":{\"VtepMAC\":\"8e:28:15:ca:cd:3b\"}}"
            },
            {
                "createdIndex": 374,
                "expiration": "2016-04-03T01:42:01.861701761Z",
                "key": "/atomic.io/network/subnets/10.0.14.0-24",
                "modifiedIndex": 374,
                "ttl": 86171,
                "value": "{\"PublicIP\":\"10.0.2.32\",\"BackendType\":\"vxlan\",\"BackendData\":{\"VtepMAC\":\"b6:1b:ee:eb:ce:ef\"}}"
            },
            {
                "createdIndex": 434,
                "expiration": "2016-04-03T01:45:36.592848197Z",
                "key": "/atomic.io/network/subnets/10.0.91.0-24",
                "modifiedIndex": 434,
                "ttl": 86385,
                "value": "{\"PublicIP\":\"10.0.2.33\",\"BackendType\":\"vxlan\",\"BackendData\":{\"VtepMAC\":\"4e:84:7d:78:21:00\"}}"
            }
        ]
    }
}

MASTER
No servidor Master faça um “kubectl get nodes” para verificar todos os nós do cluster.

#kubectl get nodes

[root@kubernetes-master1 ~]# kubectl get nodes
NAME                                  LABELS                                                       STATUS    AGE
kubernetes-minion1.devopslab.com.br   kubernetes.io/hostname=kubernetes-minion1.devopslab.com.br   Ready     53m
kubernetes-minion2.devopslab.com.br   kubernetes.io/hostname=kubernetes-minion2.devopslab.com.br   Ready     6m
kubernetes-minion3.devopslab.com.br   kubernetes.io/hostname=kubernetes-minion3.devopslab.com.br   Ready     2m

7. Criação de Pods com o Kubernets

Vamos criar 3 containeres com a imagem nginx e com a porta 80 exposta e um replication controller nomeado como webserver-nginx.

#kubectl run webserver-nginx –image=nginx –replicas=3 –port=80

[root@kubernetes-master1 ~]# kubectl run webserver-nginx --image=nginx --replicas=3 --port=80
replicationcontroller "webserver-nginx" created

Listando os Pods do cluster
#kubectl get pods

[root@kubernetes-master1 ~]# kubectl get pods
NAME                    READY     STATUS    RESTARTS   AGE
webserver-nginx-2th95   0/1       Pending   0          33m
webserver-nginx-v4404   0/1       Pending   0          33m
webserver-nginx-za52c   0/1       Pending   0          33m

Este status pending é normal, pois o Kubernetes está provisionando os Pods, pode demorar alguns minutos dependendo do tamanho da imagem.

No final você terá todos os Pods rodando.
#kubectl get pods

[root@kubernetes-master1 ~]#  kubectl get pods 
NAME                    READY     STATUS    RESTARTS   AGE
webserver-nginx-2th95   1/1       Running   0          54m
webserver-nginx-v4404   1/1       Running   0          54m
webserver-nginx-za52c   1/1       Running   1          54m

Verificando o Replication controller
#kubectl get rc

[root@kubernetes-master1 ~]# kubectl get rc
CONTROLLER        CONTAINER(S)      IMAGE(S)   SELECTOR              REPLICAS   AGE
webserver-nginx   webserver-nginx   nginx      run=webserver-nginx   3          59m

Verificando informações sobre um Pod.
Você criou um Pod pelo Kubernetes mas você não sabe muita coisa sobre ele, como os Ips.
#kubectl describe pod webserver-nginx-2th95

[root@kubernetes-master1 ~]# kubectl describe pod  webserver-nginx-2th95
Name:				webserver-nginx-2th95
Namespace:			default
Image(s):			nginx
Node:				kubernetes-minion2.devopslab.com.br/10.0.2.32
Start Time:			Sat, 02 Apr 2016 00:05:49 -0300
Labels:				run=webserver-nginx
Status:				Running
Reason:				
Message:			
IP:				10.0.14.2
Replication Controllers:	webserver-nginx (3/3 replicas created)
Containers:
  webserver-nginx:
    Container ID:	docker://a08a160b25fb141a8546028b09349c50adf4442b93e19a15e6500fc789ad695b
    Image:		nginx
    Image ID:		docker://6f62f48c4e55d700cf3eb1b5e33fa051802986b77b874cc351cce539e5163707
    QoS Tier:
      cpu:		BestEffort
      memory:		BestEffort
    State:		Running
      Started:		Sat, 02 Apr 2016 00:59:18 -0300
    Ready:		True
    Restart Count:	0
    Environment Variables:
Conditions:
  Type		Status
  Ready 	True 
No volumes.
Events:
  FirstSeen	LastSeen	Count	From						SubobjectPath				Reason	Message
  ─────────	────────	─────	────						─────────────				──────	───────
  38m		38m		1	{kubelet kubernetes-minion2.devopslab.com.br}	implicitly required container POD	Pulled	Successfully pulled image "registry.access.redhat.com/rhel7/pod-infrastructure:latest"
  38m		38m		1	{kubelet kubernetes-minion2.devopslab.com.br}	implicitly required container POD	Created	Created with docker id f7add7ef632a

Consultando os Ips de todos os Pods de um específico Replication Controller.
#kubectl get pods -l run=webserver-nginx -o yaml | grep podIP

[root@kubernetes-master1 ~]# kubectl get pods -l run=webserver-nginx -o yaml | grep podIP
    podIP: 10.0.14.2
    podIP: 10.0.10.2
    podIP: 10.0.91.2

8. Criando um serviço e acessando os serviços dos Pods

Até o momento nós temos o Kubernetes rodando, Pods criados, porta 80 exposta nos containeres, e Nginx instalado, tudo bonito.

Mas como você vai acessar os serviço http do Nginx? Qual é a Url? Qual é o Ip?.
Veja quando nós temos um cluster auto gerenciável como nós criamos aqui, a ideia é que todos os Pods estejam rodando e quando algum deles cair o próprio cluster se encarregará de subir um novo container, e este container com um novo IP.

Então não adianta eu saber os Ips do containers, se um deles morrer, será criado um outro, com um novo Ip, Id e etc.

Aí que entra a ideia de Serviço, vamos criar um serviço que atuará como Loadbalancer do cluster, este serviço vai me disponibilizar um IP do cluster, eu vou acessar meus serviços por este Ip, para mim tanto faz quais são os containeres, Ips, onde estão e etc, eu quero apenas o ip do cluster, e que este responda pelos meus containers.

Vamos ver como isto funciona.
Consultando o RC.
#kubectl get rc

[root@kubernetes-master1 ~]# kubectl get rc
CONTROLLER        CONTAINER(S)      IMAGE(S)   SELECTOR              REPLICAS   AGE
webserver-nginx   webserver-nginx   nginx      run=webserver-nginx   3          1h

Criando um serviço.
#kubectl expose rc webserver-nginx –port=80

[root@kubernetes-master1 ~]# kubectl expose rc webserver-nginx --port=80
service "webserver-nginx" exposed

Consultando o IP do cluster.
#kubectl get service webserver-nginx

[root@kubernetes-master1 ~]# kubectl get service webserver-nginx
NAME              CLUSTER_IP      EXTERNAL_IP   PORT(S)   SELECTOR              AGE
webserver-nginx   10.254.174.71   <none>        80/TCP    run=webserver-nginx   1m

Consultando os Ips dos Pods do Cluster.
kubectl describe service webserver-nginx

[root@kubernetes-master1 ~]# kubectl describe service webserver-nginx
Name:			webserver-nginx
Namespace:		default
Labels:			run=webserver-nginx
Selector:		run=webserver-nginx
Type:			ClusterIP
IP:			10.254.174.71
Port:			<unnamed>	80/TCP
Endpoints:		10.0.10.2:80,10.0.14.2:80,10.0.91.2:80
Session Affinity:	None
No events.

[root@kubernetes-master1 ~]# kubectl get ep webserver-nginx
NAME              ENDPOINTS                                AGE
webserver-nginx   10.0.10.2:80,10.0.14.2:80,10.0.91.2:80   3m

Nosso CLUSTER_IP é 10.254.174.71 e este IP é acessível apenas de dentro da nossa Infraestrutura, ou seja apenas os hosts Minions tem acesso a este ip.

Então a partir de qualquer host Minion você pode fazer um curl para validar se os serviços de Nginx estão respondendo.
#curl 10.254.174.71

[root@kubernetes-minion1 ~]# curl 10.254.174.71
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@kubernetes-minion1 ~]# 

Agora se você quer acessar o cluster externamente, torná-lo público ou disponível para outras redes vamos utilizar algumas das opções como Loadbalancer, EXTERNAL_IP ou NodePort. NodePort é o conhecido expose do Docker, você vai criar um Pod e expor a porta do host Docker/Minion, podendo acessar o serviço do container através do Ip do host Docker/Minion.

Lembrando CLUSTER_IP é acessível apenas dentro da rede dos hosts Minions.

Eu vou criar novos tópicos abordando o acesso público, que na verdade o que vale mesmo é você criar um cluster e poder acessá-lo externamente. Mas veja bem, um cluster interno pode ser muito útil, pode existir serviços que você não queira que seja público como por exemplo um pool de servidores de cache ou algum pool de NoSQL como Cassandra. Nós temos que saber trabalhar com os 2 casos, Cluster Interno e Cluster externo.

Referências.
http://kubernetes.io/docs/getting-started-guides/centos/centos_manual_config/
http://kubernetes.io/docs/getting-started-guides/fedora/fedora_manual_config/
http://kubernetes.io/docs/getting-started-guides/fedora/flannel_multi_node_cluster/#master-setup
http://kubernetes.io/docs/user-guide/simple-nginx/
http://kubernetes.io/docs/user-guide/replication-controller/
http://kubernetes.io/docs/user-guide/deploying-applications/

Obrigado

Leonardo Macedo

Cluster de armazenamento XtreemFS

Instalação e configuração do cluster de Armazenamento XtreemFS

Este é um tutorial hands on para a instalação e configuração do cluster de armazenamento XtreemFS.
Mas antes seguem algumas características do cluster XtreemFS.

XtreemFS é um sistema de armazenamento distribuído, replicável, escalável e tolerante a falhas.

Veja a página do produto: http://www.xtreemfs.org/
Blog: http://xtreemfs.blogspot.com.br/

Réplica de arquivos
O XtreemFS replica os arquivos para múltiplos servidores de armazenamento, para qualquer localidade.

Tolerância a falhas
Arquivos distribuídos em múltiplos storages. O XtreemFS automaticamente distribuí os arquivos entre as replicas de storage, então em caso de qualquer falha em uma das réplicas, o próprio gerenciador do XtreemFS irá eleger uma nova réplica de forma transparente.

Leitura e Escrita
Fora o tradicional Read and Write, o XtreemFS permite a replicação de dados do tipo Read-Only, Que pode servir como um cache.

Escalável
Você pode aumentar ou diminuir o número de servidores de armazenamento possibilitando elasticidade e escalabilidade.

Permissões
Permite o controle de leitura e escrita por usuários.

Look&Feel
XtreemFS é um filesystem fácil de usar, o intuíto é montar uma partição via rede, com o mínimo de configuração.

Segurança
Suporte a certificados SSL, assim você pode distribuir arquivospela internet com segurança.

Desempenho
Dados distribuidos entre os storages, aumentando a banda de I/O, similar a configuração RAID 0.

Cache
O cliente XtreemFS permite a configuração de cache local, aumentando a velocidade de leitura de dados.

Backup
Criação de snapshots de metadados, lhe garantindo um backup full de toda a estrutura.

Suporte
Pode ser montado em Windows, Linux e OSX pois utiliza o padrão POSIX.

Visite o site do XtreemFS para outras caracterísca, aqui eu listei apenas algumas, mas a documentação é muito mais detalhada.

1. Componentes do cluster XtreemFS.

O cluster XtreemFS possuí 3 componentes para o funcionamento, no caso o DIR, MRC e OSD.

DIR – Directory service
Diretório de Serviços, usado pelo MRC, OSD e Clientes para encontrar os servidores que fazem parte do cluster e mapeamento dos volumes.

MRC – Metadata and Replica catalog
Metadados e replicação de catálogos, é neste servidor que a árvore de diretórios e todos os metadados dos arquivos serão mapeaedos, é o MRC que sabe em quais OSDs estão os arquivos carregados pelos clientes. Se você perder o MRC, você basicamente perdeu todo o ambiente, é impossível recuperar os dados mesmo tendo os storages de armazenamento intactos pois somente o MRC sabe onde estão todos os binários que formam o arquivo completo.
Por exemplo, você carregou um arquivo de 100MB, este arquivo será particionado em vários arquivos menores de 128K, distribuídos em uma árvore de diretórios espalhados pelos OSDs, somente o MRC sabe quais são os diretórios corretos do arquivo.

OSD – Objedct Sorage Device
É o storage propriamente dito, será nos OSDs que tudo será armazenado, então é no OSD que você vai provisionar os discos para armazenamento, podendo ser um disco local, ou em outro storage via rede como ISCSI ou Fibra, enfim, é onde os dados brutos serão armazenados.

2. Arquitetura

 

Sistema Operacional Centos 7 – 64 bits instalação minima.
1 DIR – xtreemfs-dir01.devopslab.com.br
1 MRC – xtreemfs-mrc01.devopslab.com.br
3 OSD – xtreemfs-osd01.devopslab.com.br, xtreemfs-osd2.devopslab.com.br, xtreemfs-osd3.devopslab.com.br
1 cliente – xtreemfs-cli01.devopslab.com.br

 

3. Pré requisitos

Configuração do File Descriptor.

vi /etc/security/limits.conf

*		 soft	 nofile		4096
*		 hard	 nofile		63536

Selinux desativado

# vi /etc/selinux/config

SELINUX=disabled

Firewall desativado

systemctl disable firewalld.service

Reinicie os servidores DIR, MRC, OSD para que as modificações façam efeito. Não necessáriamente precisa reiniciar, tem como fazer tudo isto online, mas vamos facilitar as coisas.

4. Adicionar o repositório XtreemFS

cd /etc/yum.repos.d/

wget http://download.opensuse.org/repositories/home:/xtreemfs/CentOS_7/home:xtreemfs.repo

5. Instalação do Servidor e Cliente

Cliente

yum install xtreemfs-client xtreemfs-tools

Servidores – DIR, MRC, OSD

yum install xtreemfs-server

Para Debian e Ubuntu:
http://www.xtreemfs.org/download_pkg.php

6. Configuração do cluster

Configuração dos servidores DIR e OSD.

Fuse
O módulo “fuse” precisa estar carregado em todos os servidores (DIR, MRC, OSD).

Configuração persistente do módulo fuse. Faça isto nos servidores do cluster.

echo 'fuse' > /etc/modules-load.d/fuse.conf

Carregar em tempo de execução.

modprobe fuse
lsmod | grep fuse

Configurações
Servidor DIR: xtreemfs-dir01.devopslab.com.br

systemctl enable  xtreemfs-dir.service
systemctl start  xtreemfs-dir.service

Servidor MRC: xtreemfs-mrc01.devopslab.com.br

vi  /etc/xos/xtreemfs/mrcconfig.properties
dir_service.host = xtreemfs-dir01.devopslab.com.br

systemctl enable xtreemfs-mrc.service
systemctl start xtreemfs-mrc.service

Servidores OSDs: xtreemfs-osd01.devopslab.com.br, xtreemfs-osd02.devopslab.com.br e xtreemfs-osd03.devopslab.com.br

vi  /etc/xos/xtreemfs/osdconfig.properties
dir_service.host = xtreemfs-dir01.devopslab.com.br

systemctl enable xtreemfs-osd.service
systemctl start xtreemfs-osd.service

Por padrão todos os objetos serão armazenados na pasta “/var/lib/xtreemfs/objs” dos servidores OSD. Este caminho pode ser alterado no arquivo osdconfig.properties, e apontar para uma partição separada, um storage e etc.

7. Startup

O módulo fuse precisa estar carregado

lsmod | grep  fuse

Servidor DIR: xtreemfs-dir01.devopslab.com.br

/etc/init.d/xtreemfs-dir start

Servidor MRC: xtreemfs-mrc01.devopslab.com.br

/etc/init.d/xtreemfs-mrc start

Servidores OSDs: xtreemfs-osd01.devopslab.com.br, xtreemfs-osd01.devopslab.com.br

/etc/init.d/xtreemfs-osd start

8. Status dos serviços

Acesse pelo navegador os endereços e respectivas portas para a consulta do status dos serviços MRC, DIR e OSD.
Portas: 30636 (MRC), 30638 (DIR), 30640 (OSD)

MRC
http://xtreemfs-mrc01.devopslab.com.br:30636

DIR
http://xtreemfs-dir01.devopslab.com.br:30638

OSD
http://xtreemfs-osd01.devopslab.com.br:30640

O cluster já está pronto para o uso, a configuração básica é super fácil, então vamos montar a partição do cluster no cliente e fazer alguns testes.

9. Cliente

No cliente crie um volume com o nome de sua preferência no servidor de Metadados MRC.

Comando para a criação do volume.

mkfs.xtreemfs xtreemfs-MRC01.devopslab.com.br/vol-clusterx
[root@xtreemfs-cli01 vol-clusterx]# mkfs.xtreemfs xtreemfs-mrc01.devopslab.com.br/vol-clusterx
Trying to create the volume: xtreemfs-mrc01.devopslab.com.br/vol-clusterx
Using options:
  Owner:			root
  Owning group:			root
  Mode:				777
  Access Control Policy:	POSIX
  Quota:			0
  Default striping policy:		RAID0
  Default stripe size (object size):	128
  Default stripe width (# OSDs):	1
Successfully created volume "vol-clusterx" at MRC: xtreemfs-mrc01.devopslab.com.br/vol-clusterx

Verifique o status do serviço MRC. Existirá na url várias informações do MRC e algumas informações do volume “vol-clusterx”.
http://xtreemfs-mrc01.devopslab.com.br:30636

Crie um ponto de montagem e monte o volume mapeado no servidor DIR.

[root@xtreemfs-cli01 vol-clusterx]# mkdir /vol-clusterx
[root@xtreemfs-cli01 vol-clusterx]# mount xtreemfs-DIR01.devopslab.com.br/vol-clusterx /vol-clusterx

Como estamos utilizando 3 servidores OSD e queremos que os arquivos sejam replicados para os 3, vamos definir a política de Striping, então caso seu cluster tenha mais de 3 volumes, aumente o “–replication-factor”.

xtfsutil --set-drp --replication-policy WqRq --replication-factor 3 /vol-clusterx
[root@xtreemfs-cli01 vol-clusterx]#xtfsutil --set-drp --replication-policy WqRq --replication-factor 3 /vol-clusterx
Updated default replication policy to: WQRQ with 3 replicas

Verificando o ponto de montagem.

[root@xtreemfs-cli01 vol-clusterx]# df -h
Filesystem                                             Size  Used Avail Use% Mounted on
/dev/mapper/centos-root                                4.0G  1.3G  2.8G  31% /
devtmpfs                                               910M     0  910M   0% /dev
tmpfs                                                  920M     0  920M   0% /dev/shm
tmpfs                                                  920M  8.3M  912M   1% /run
tmpfs                                                  920M     0  920M   0% /sys/fs/cgroup
/dev/sda1                                              497M  152M  346M  31% /boot
tmpfs                                                  184M     0  184M   0% /run/user/0
xtreemfs@xtreemfs-dir01.devopslab.com.br/vol-clusterx  4.0G  1.2G  2.9G  29% /vol-clusterx

FSTAB
Configure o fstab para a auto-montagem.

vi /etc/fstab
xtreemfs-dir01.devopslab.com.br/vol-clusterx /vol-clusterx xtreemfs defaults,_netdev,allow_other, -d=INFO,log-file-path=/tmp/xtreemfs.log 0 0

TESTES
Vou fazer um upload para o volume “/vol-clusterx” e ver se foi replicado.

root@Desktop:~#du -hs Filme.avi
1.2G	Filme.avi

root@Desktop:~#scp Filme.avi.avi root@xtreemfs-cli01:/vol-clusterx/Filme.avi

O arquivo está no ponto de montagem “vol-clusterx”.

[root@xtreemfs-cli01 /]# ls /vol-clusterx/; du -hs /vol-clusterx/Filme.avi 
Filme.avi
1.2G	/vol-clusterx/Filme.avi

Vamos verificar a replicação do arquivo com a ferramenta “xtfsutil”. O “xtfsutil” já foi instalado no client em um passo anterior na instalação do pacote “xtreemfs-tools”.

 
[root@xtreemfs-cli01 vol-clusterx]# xtfsutil  Filme.avi
Path (on volume)     /Filme.avi
XtreemFS file Id     9c492d5e-70cc-4ae7-b22d-17e8a3035065:21
XtreemFS URL         pbrpc://xtreemfs-dir01.devopslab.com.br:32638/vol-clusterx/Filme.avi
Owner                root
Group                root
Type                 file
Replication policy   WqRq
XLoc version         0
Replicas:
  Replica 1
     Striping policy     STRIPING_POLICY_RAID0 / 1 / 128kB
     OSD 1               0ec904e2-cdc5-4c9e-9d5f-1792e0d07893 (10.0.0.135:32640)
  Replica 2
     Striping policy     STRIPING_POLICY_RAID0 / 1 / 128kB
     OSD 1               0d7b7906-734c-4885-8594-97318eaebbef (10.0.0.133:32640)
  Replica 3
     Striping policy     STRIPING_POLICY_RAID0 / 1 / 128kB
     OSD 1               d94909c3-9b16-4449-8163-b69048117756 (10.0.0.132:32640)

Veja que a política de stripping está funcionando.

Vamos verificar se o arquivo existe nos OSDs.

Servidor 1: xtreemfs-osd01.devopslab.com.br

[root@xtreemfs-osd01 /]# du -hs /var/lib/xtreemfs/objs/
1.2G	/var/lib/xtreemfs/objs/
[root@xtreemfs-osd01 /]# ls /var/lib/xtreemfs/objs/
C1  flease_lock.1115684804
[root@xtreemfs-osd01 /]# 

Servidor 2: xtreemfs-osd02.devopslab.com.br

[root@xtreemfs-osd2 /]# du -hs /var/lib/xtreemfs/objs/
1.2G	/var/lib/xtreemfs/objs/
[root@xtreemfs-osd2 /]# ls /var/lib/xtreemfs/objs/
C1  flease_lock.1911808723
[root@xtreemfs-osd2 /]#

Servidor 3: xtreemfs-osd03.devopslab.com.br

[root@xtreemfs-osd3 objs]# du -hs /var/lib/xtreemfs/objs/
1.2G	/var/lib/xtreemfs/objs/
[root@xtreemfs-osd3 objs]# ls /var/lib/xtreemfs/objs/
C1  flease_lock.663390777
[root@xtreemfs-osd3 objs]#

Para finalizar …
Algumas observações ou dicas se você assim preferir.

Aumento do cluster
Crie um novo servidor OSD, por exemplo xtreemfs-osdNN.devopslab.com.br, após configurado o novo servidor automaticamente começará a receber os novos arquivos.

Tolerância a falha
Os servidores DIR e MRC suportam a replicação de dados para se ter uma tolerância a falhas, logo se por ventura um destes 2 servidores morrerem, simplesmente uma outra réplica assumirá o cluster continuando todo o trabalho.

Disco separado nos OSDs
Neste tutorial optei por utilizar a pasta padrão de armazeamento de dados, no caso a pasta “/var/lib/xtreemfs/objs/”, no entanto você pode criar uma partição separada (fdisk …) nos servidores OSD, para o armazenamento dos arquivos. Neste caso você vai criar uma partição comum ext4 com o fdisk, montar e alterar o arquivo “osdconfig.properties” para que os objetos passem a ser gravados no novo local.

Att

Leonardo