Mudanças entre as edições de "Servidor de Aplicações em Contêineres"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 215: Linha 215:
 
** -h servidor-web → o nome de host do contêiner é ''servidor-web''. <br />
 
** -h servidor-web → o nome de host do contêiner é ''servidor-web''. <br />
 
** --restart=on-failure:10 → o contêiner será reiniciado quando falhar, no entanto, caso ocorram 10 falhas consecutivas, o reinício automático é interrompido. <br />
 
** --restart=on-failure:10 → o contêiner será reiniciado quando falhar, no entanto, caso ocorram 10 falhas consecutivas, o reinício automático é interrompido. <br />
**
+
** --dns=191.36.8.2 → o servidor de nomes ''191.36.8.2'' é usado. O endereço pode ser encontrado dentro do arquivo ''/etc/resolv.conf'' dentro do contêiner. <br />
 +
** --dns-search=sj.ifsc.edu.br → o domínio de busca é ''sj.ifsc.edu.br''. <br />
 +
** --device=/dev/kvm:/dev/kvm → o contêiner terá acesso ao dispositivo de virtualização ''kvm''. <br />
 +
** --privileged → o contêiner terá permissões para acessar todos os dispositivos devidamente reconhecidos do sistema de gerência. <br />
 +
** -v /home/servidor-web:/var/www/html → o diretório ''/home/servidor'' do sistema de gerência é associado com o diretório ''/var/www/html'' do contêiner. <br />
 +
** debian:jessie → a imagem base utilizada é o Debian na versão Jessie.
  
 
=== Configuração da rede ===
 
=== Configuração da rede ===

Edição das 11h31min de 25 de setembro de 2017

A estrutura

  • Sistema Operacional de gerência (instalado em máquina virtual VMWare): Container Linux by CoreOS 1409.8.0 (Ladybug);
    • Versão da distribuição: 1409.8.0;
    • Nome da versão da distribuição: Ladybug;
    • Nome da distribuição: Container Linux by CoreOS;
  • Contêiner Docker com sistema base Debian 8 (Jessie), dispondo das seguintes aplicações:
    • Quartus 13.0sp1 com Modelsim Altera 10.1d;
    • Quartus 16.0 com Modelsim Altera 10.4d;
    • MatLab 2015a;
    • Octave 4.2.1;
    • Omnet++ 5.0;
    • Gdrive;
  • Contêiner Docker com sistema base Debian 9 (Stretch).
    • Aluno responsável: Gustavo Paulo Medeiros da Silva;
    • Professor orientador: Ramon Mayor Martins;
    • Aplicações: Node.js, csdr;
    • Site: IFSC-SDR

O CoreOS

Logomarca do Container Linux by CoreOS

O CoreOS é um sistema operacional de código aberto voltado à execução de contêineres. Seu objetivo é permitir a execução de aplicações em qualquer ambiente. Fornece ferramentas de gerência de contêineres como Docker e Rocket, que é feito pela mesma equipe que criou o Container Linux. Possui suporte ao Kubernetes, que é uma poderosa ferramenta de gerência de contêineres, baseada na experiência que a Google teve. O CoreOS também tem seu código no GitHub.

Instalação do Container Linux

Para a instalação do CoreOS, baixe a ISO da versão de produção do sistema através deste link. A versão de produção é a mais indicada para ambientes que necessitam de uma maior estabilidade no sistema operacional. Após baixada a ISO, grave-a em um pendrive usando o comando "dd", ou outro gravador de imagens em dispositivos de sua preferência. Em seguida, dê boot do sistema, que começará a ser carregado e irá concluir em uma tela com o login já feito. Digite sudo su para se tornar root. Neste momento, os sistema está apenas carregado em memória. Antes de instalá-lo, primeiramente a rede deve ser corretamente configurada, já que o script de instalação baixa uma imagem que é o sistema a ser gravado no disco rígido. É possível utilizar o comando "ifconfig", o comando "ip" ou o serviço "systemd-networkd" para a configuração da rede, além do comando "route" para definir o gateway. De modo que a configuração seja mais rápida, optar-se-á pela utilização do comando "ifconfig" para a configuração da rede, como mostrado no exemplo abaixo:

ifconfig eth0 191.36.8.33/27
route add default gw 191.36.8.62
echo "nameserver 8.8.8.8" > /etc/resolv.conf

No uso do comando ifconfig, a interface de rede eth0 foi definida com o endereço IP 191.36.8.33 com máscara de sub-rede 255.255.255.224 ou /27. No uso do comando route, foi definido como roteador principal o endereço IP 191.36.8.62.
No uso do comando echo, foi gravado no arquivo resolv.conf, localizado em /etc, o servidor para a busca de nomes.
Após a configuração de rede, instale o Container Linux utilizando o seguinte script presente em /bin:

coreos-install -C stable -d /dev/sda

O script coreos-install está localizado em /bin e é um shell script. Ao utilizar o argumento -C e o parâmetro stable, definiu-se o canal de atualizações bem como o estágio de desenvolvimento da imagem que será baixada, verificada e gravada no HD. O argumento -d vem de device e especifica o dispositivo o qual a imagem baixada será gravada.
Após isso, reinicie o sistema utilizando o comando reboot. O sistema será rapidamente desligado e ligado novamente, é importante ser rápido quando a tela do grub ↓

Coreos-grub.png

aparecer para que se edite um parâmetro de boot a fim de modificar a senha de usuário.

Coreos-grub2.png

Adicione no final da linha linux$suf $gptprio_kernel $gptprio_cmdline $linux_cmdline o parâmetro init=/bin/bash, como mostrado na imagem abaixo. Lembrando que a disposição do teclado está para inglês estadunidense.

Coreos-grub3.png

Após adicionar o parâmetro no final da linha, pressione a tecla "F10" para dar o boot, que se concluirá com uma tela parecida com a imagem abaixo.

Coreos-grub4.png

Digite o comando mount -o remount / a fim de dar permissão de escrita.

Coreos-grub5.png

Agora, mude a senha do usuário "core" utilizando o comando passwd, como mostrado na imagem abaixo:

Coreos-grub6.png

Reinicie o sistema e você já poderá logar com o usuário "core" e a senha que você definiu anteriormente. Para tornar-se root, digite sudo su após estar logado.

Configuração da Rede

A configuração da rede pode dar-se de duas formas, via SystemD ou via Cloud Config. Nesse primeiro momento, será explicada a configuração via SystemD. Para tanto, inicialmente criaremos um arquivo com a extensão .network em /etc/systemd/network.

vi /etc/systemd/network/0-eth0.network

E escreveremos no arquivo as configurações de rede, como no modelo abaixo:

[Match]
Name=eth0

[Network]
DNS=191.36.8.2
Address=191.36.8.33/27
Gateway=191.36.8.62

Agora basta reiniciar o serviço que gerencia a rede:

systemctl restart systemd-networkd

O Docker

Logomarca do Docker

O Container Linux by CoreOS já vem com o Docker. Digitando docker version, obtemos a seguinte saída:

docker version
Client:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.7.6
 Git commit:   a82d35e
 Built:        Tue Sep  5 20:35:08 2017
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.7.6
 Git commit:   a82d35e
 Built:        Tue Sep  5 20:35:08 2017
 OS/Arch:      linux/amd64

Baixando uma imagem base

Para baixar uma imagem de sistema operacional base para um contêiner, digite:

docker pull nome_imagem:tag

Por exemplo, para baixar uma imagem base Debian Stretch

docker pull debian:stretch

As tags podem ser obtidas no Docker Hub.

Criando um contêiner

Para a criação de um contêiner, utiliza-se o comando docker com o parâmetro run. Observe o exemplo abaixo:

docker run -it debian:stretch

O comando acima já é suficiente para a criação de um contêiner, no entanto, é possível definir mais parâmetros:

localhost core # docker run ···

-it → assim que o contêiner for criado, entrega ao terminal atual um console tty interativo;
--name=nome_do_conteiner → define o nome do contêiner. Caso este parâmetro seja omitido, o Docker selecionará randomicamente um nome.
--net nome_da_rede → especifica o nome da rede. Caso este parâmetro seja omitido, o Docker associará o contêiner à rede padrão chamada "docker0", de nome "bridge".
--ip <endereço IP> → especifica um endereço IP fixo para o contêiner. Caso este parâmetro seja omitido, o Docker atribuirá um endereço IP seguindo uma sequência em ordem crescente. Salientando que na interface padrão "docker0" NÃO é possível escolher o endereço IP do contêiner, apenas em interfaces criadas pelo usuário, algo que será explicado mais adiante.
-p porta_do_host:porta_do_conteiner → associa uma porta do sistema operacional gerente a uma porta do contêiner. Apesar de prático, este parâmetro bagunça muito as regras do IPTables o que faz com que, ao possuir um grande número de contêineres, fique mais difícil de fazer algum ajuste.
-v /pasta/no/sistema:/pasta/no/conteiner → associa um diretório do sistema operacional gerente a um diretório dentro do contêiner. Também é possível criar volumes.
-h nome_de_host → define o nome de host (hostname) do contêiner.
--privileged → dá ao contêiner acesso a todo o hardware do sistema operacional gerente. É recomendado o uso apenas em casos que realmente necessitem de tal recurso.
--cap-add=habilidade → dá ao contêiner habilidades de gerência como se fosse o sistema operacional gerente. Por exemplo, em caso de --cap-add=NETWORK, permite o contêiner modificar a rede do sistema operacional gerente. Este parâmetro deve ser usado muito cautelosamente.
-d → executa o contêiner em segundo plano.
--dns=endereço_IP → define um servidor DNS para o contêiner.
--dns-search → define o domínio de busca do servidor DNS.
--mac-address=" " → define o endereço MAC do dispositivo de rede do contêiner.
--restart=" " ' → quando definido --restart=always, sempre que o contêiner for interrompido, o Docker reiniciar-lo-á. Caso --restart=on-failure, quando contêiner for finalizado com saída diferente de 0, o Docker reiniciar-lo-á. Caso --restart=on-failure:n, o qual n é um número natural, após n vezes que o contêiner falhar e for reiniciado, o Docker interromperá os reinícios automáticos.
--device=/dev/dispositivo → permite o contêiner utilizar um determinado dispositivo.
-rm → cria um contêiner temporário, assim que o contêiner for parado, ele será automaticamente excluído.

Abaixo, segue um exemplo da criação de um contêiner:

docker run -d --name=Portainer -h portainer -v /var/run/docker.sock:/var/run/docker.sock -v /home/portainer:/data portainer/portainer

O exemplo acima cria um contêiner denominado Portainer, que tem dois pontos de montagem (-v), o primeiro montando o arquvio /var/run/docker.sock do sistema de gerência no arquivo /var/run/docker.sock dentro do contêiner. O segundo ponto de montagem, conecta o diretório /home/portainer do sistema de gerência com o diretório /data do contêiner. Por fim, como último argumento de linha de comando, é dado o nome da imagem, nesse caso portainer/portainer. Com o parâmetro -h,foi definido o nome de host. Note que foi omitida a tag da imagem, quando isso ocorre, é dada a tag latest, que corresponde à última versão da imagem (portainer/portainer:latest).


Outro exemplo:

docker run -it -d --name=servidor-web --net faixa10 --ip 10.10.10.110 -h servidor-web --restart=on-failure:10 --dns=191.36.8.2 --dns-search=sj.ifsc.edu.br --device=/dev/kvm:/dev/kvm --privileged -v /home/servidor-web:/var/www/html debian:jessie

No exemplo acima:

  • É criado um contêiner
    • -it → com tty interativo
    • -d → o contêiner, assim que criado, ficará em execução em segundo plano.
    • --name=servidor-web → o nome do contêiner é servidor-web
    • --net faixa10 → ele está associado à ponte denominada faixa10
    • --ip 10.10.10.110 → o endereço IP do contêiner é 10.10.10.110
    • -h servidor-web → o nome de host do contêiner é servidor-web.
    • --restart=on-failure:10 → o contêiner será reiniciado quando falhar, no entanto, caso ocorram 10 falhas consecutivas, o reinício automático é interrompido.
    • --dns=191.36.8.2 → o servidor de nomes 191.36.8.2 é usado. O endereço pode ser encontrado dentro do arquivo /etc/resolv.conf dentro do contêiner.
    • --dns-search=sj.ifsc.edu.br → o domínio de busca é sj.ifsc.edu.br.
    • --device=/dev/kvm:/dev/kvm → o contêiner terá acesso ao dispositivo de virtualização kvm.
    • --privileged → o contêiner terá permissões para acessar todos os dispositivos devidamente reconhecidos do sistema de gerência.
    • -v /home/servidor-web:/var/www/html → o diretório /home/servidor do sistema de gerência é associado com o diretório /var/www/html do contêiner.
    • debian:jessie → a imagem base utilizada é o Debian na versão Jessie.

Configuração da rede

O Docker trabalha com dispotivos de rede virtuais do tipo ponte, nulo e até mesmo a própria rede do sistema operacional de gerência. Ao ser instalado, ele cria automaticamente a ponte denominada docker0, que dentro do Docker recebe o nome de bridge.
É possível também criar interfaces de rede virtuais através do Docker com o comando docker network. Por exemplo:

docker network create --driver bridge --subnet=10.10.10.0/24 --gateway=10.10.10.10 --opt "com.docker.network.bridge.name"="faixa10" faixa10

Redirecionamento de Portas

Para fazer o redirecionamento de uma porta do contêiner para o sistema de gerência e vice-versa, basta adicionar uma regra no arquivo regras-iptables presente no diretório /home. Abaixo, um exemplo:

→ Redirecionando apenas uma porta:

-A PREROUTING -d 191.36.8.33/32 -p tcp -m tcp --dport PORTA_DO_IP_EXTERNO -j DNAT --to-destination IP_DO_CONTÊINER:PORTA_DO_CONTÊINER
-A PREROUTING -d 191.36.8.33/32 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.10.10.200:80

No exemplo acima, a porta externa 443 foi redirecionada para a porta 80 do contêiner de endereço IP 10.10.10.200.

→ Redirecionando uma faixa de portas:

-A PREROUTING -d 191.36.8.33/32 -p tcp -m tcp --dport FAIXA_DE_PORTAS_EXTERNAS -j DNAT --to-destination IP_DO_CONTÊINER:FAIXA_DE_PORTAS_DO_CONTÊINER
-A PREROUTING -d 191.36.8.33/32 -p tcp -m tcp --dport 10000:20000 -j DNAT --to-destination 10.10.10.150:30000-40000

No exemplo acima, a faixa de portas externa 10000:20000 foi redirecionada para a faixa de portas 30000:40000 do contêiner de endereço IP 10.10.10.150.
A faixa de portas externas deve ter a mesma quantidade de portas que a faixa de portas do contêiner.
O argumento -p bagunça demasiadamente as regras do IPTables, criando três regras para cada redirecionamento.

Scripts para criação de usuários

Devido à falta de informações suficientes providas pelo LDAP, não foi possível usar os usuários de rede dos alunos. De maneira a agilizar a criação e remoção de contas, foram criados scripts para realizar essas funções.
O script abaixo verifica o nome completo do aluno e retorna o seu nome de usuário. Caso retorne mais de um nome de usuário ou não retorne nenhum nome de usuário, o mesmo deve ter seu nome retirado da lista e ser criado manualmente:
Atualização: O script de criação de usuários já verifica quais os alunos que não retornaram nome de usuário e também aqueles que retornaram mais de um nome de usuário, ignorando-os e criando apenas os usuários dos alunos que retornaram apenas um nome de usuário.
Abaixo, a sintaxe de utilização do script de verificação:

root@quartus-matlab:/# ./ler-lista lista

No comando acima, o script obtém o nome completo dos usuário a partir do arquivo "lista". A lista do com o nome completo dos usuários tem o formato CSV (comma separated value), como no exemplo abaixo:

MATRÍCULA,NOME,SOBRENOME
123456789-0,MARIO,DE ANDRADE
246801357-9,JOAO,VITOR DOS PASSOS

Abaixo, o script de verificação:

#!/bin/bash

FILE=$1
while IFS=, read -r matricula nome sobrenome
do
  echo "Usuario $nome $sobrenome de matricula $matricula."
  ldap=$(ldapsearch -h 191.36.8.12 -b "dc=cefetsc,dc=edu,dc=br" -x "(&(cn=$nome)(sn=$sobrenome))"  | sed -n 's/dn: uid=\(.*\),ou=Alunos,dc=cefetsc,dc=edu,dc=br/\1/p')
  contagem=$(echo "$ldap" |wc -l)
  
  if [ -z "${ldap}" ]; then
  echo "O usário não foi encontrado através do cirtério de busca utilizado."
  echo " "

  elif (( "$contagem" > 1 )); then
  echo "Retornou mais de um nome de usuário."

  else

  echo "$ldap"
  echo " "

  fi
done < $1

Abaixo, o script para a criação de usuários, que ignora usuários já existentes no sistema, alunos que não retornaram nome e usuário e alunos que retornaram mais de um nome de usuário:

root@quartus-matlab:/# ./criar-usuarios lista curso

Abaixo, o script de criação dos usuários dos alunos via lista:

#!/bin/bash

FILE=$1
curso=$2
verificar=$(cut -d: -f1 /etc/passwd)

while IFS=, read -r matricula nome sobrenome
do
  echo "Usuario $nome $sobrenome de matricula $matricula"
  ldap=$(ldapsearch -h 191.36.8.12 -b "dc=cefetsc,dc=edu,dc=br" -x "(&(cn=$nome)(sn=$sobrenome))"  | grep uid: |cut -f2 -d " ")
  usuariolocal=$(echo "$verificar" |grep -w "^$ldap")
  contagem=$(echo "$ldap" |wc -l)

  if [ "$usuariolocal" = "$ldap" ]; then

    echo "O usuário $usuariolocal já existe no sistema!."
    echo " "

  elif (( "$contagem" > 1 )); then
    echo "Retornou mais de um nome de usuário."

  else

    echo "Criando usuario $ldap para o aluno $nome $sobrenome do curso $curso."
    useradd -m -d /home/alunos/$ldap -s /bin/bash  -c "$nome $sobrenome,$curso,$matricula" $ldap

    echo "Usando a matricula $matricula como senha temporária do usuario $ldap."
    echo "$ldap:$matricula" |chpasswd
  
    echo "Obrigando usuário $ldap a mudar senha no proximo login."
    chage -d 0 $ldap

    echo "Adicionando usuário $ldap ao grupo alunos."
    addgroup $ldap alunos
  
    echo "Mudando a permissão da pasta /home/alunos/$ldap."
    chmod -R 700 /home/alunos/$ldap

    echo "Mudando grupo dono da pasta /home/alunos/$ldap."
    chown -R $ldap:alunos /home/alunos/$ldap

    echo "Dando permissão de leitura aos usuários do grupo professores."
    setfacl -m g:professores:r /home/alunos/$ldap
 
    echo "Conta $ldap do usuário $nome $sobrenome criada"
    echo " "

  fi
done < $1

Há também um script para a criação manual de usuários de alunos, caso seja encontrado mais de um nome de usuário para o mesmo aluno ou caso não seja encontrado nenhum nome de usuário.
A sintaxe de utilização é:

root@quartus-matlab:/# ./criar-usuario-aluno "nome_de_usuario" "NOME COMPLETO" "matrícula" "curso"
root@quartus-matlab:/# ./criar-usuario-aluno "maria.fs" "MARIA FONSECA DE SOUZA" "246801357-9" "Engenharia de Telecomunicações"

O código do script é:

#!/bin/bash

nomedeusuario=$1
nomecompleto=$2
matricula=$3
curso=$4

  echo "Criando usuario $nomedeusuario para o aluno $nomecompleto"
  useradd -m -d /home/alunos/$nomedeusuario -s /bin/bash  -c "$nomecompleto,$curso,$matricula" $nomedeusuario

  echo "Usando a matricula $matricula como senha do usuario $nomedeusuario."
  echo "$nomedeusuario:$matricula" |chpasswd
  
  echo "Obrigando usuario a mudar senha no proximo login."
  chage -d 0 $nomedeusuario

  echo "Adicionando usuario $nomedeusuario ao grupo alunos"
  addgroup $nomedeusuario alunos

  echo "Mudando grupo dono da pasta /home/alunos/$nomedeusuario."
  chown -R $nomedeusuario:alunos /home/alunos/$nomedeusuario
  
  echo "Mudando a permissao da pasta /home/alunos/$nomedeusuario"
  chmod -R 700 /home/alunos/$nomedeusuario
  
  echo "Conta $nomedeusuario do usuario $nomecompleto criada"
  echo " "

E há um script para a criação de usuários para os professores, usando a seguinte sintaxe:

root@quartus-matlab:/# ./criar-usuario-professor "usuario" "Nome Completo" "senhatemporaria"

#!/bin/bash

nomedeusuario=$1
nomecompleto=$2
senha=$3

  echo "Criando usuário $nomedeusuario para o professor $nomecompleto."
  useradd -m -d /home/professores/$nomedeusuario -s /bin/bash  -c "$nomecompleto" $nomedeusuario

  echo "Usando $senha como senha temporária do usuario $nomedeusuario."
  echo "$nomedeusuario:$senha" |chpasswd
  
  echo "Obrigando usuário a mudar senha no próximo login."
  chage -d 0 $nomedeusuario

  echo "Adicionando usuário $nomedeusuario ao grupo professores."
  addgroup $nomedeusuario professores
  
  echo "Mudando a permissão da pasta /home/professores/$nomedeusuario."
  chmod -R 700 /home/professores/$nomedeusuario
  
  echo "Conta $nomedeusuario do usuário $nomecompleto criada."
  echo " "

Uso do Gdrive

O Gdrive é uma ferramenta de gerência, em modo texto, de arquivos e diretórios no Google Drive. Abaixo, serão listados comandos úteis para o uso da ferramenta.


  • Uso

$ gdrive list → Lista os arquivos e pastas do diretório raiz. Na primeira vez que for executado, informará um link para que você acesse pelo navegador. Acessando o link, você receberá um código, copie e cole esse código no terminal ao lado de "Enter verification code:". Após isso você poderá usar a aplicação para manipular os arquivo da sua conta do Google Drive.

$ gdrive upload arquivo → envia um arquivo para o diretório raiz do Google Drive.
$ gdrive upload --parent ID_DA_PASTA arquivo → enviar um arquivo para uma pasta específica.
$ gdrive upload -r /caminho/da/pasta/no/pc → envia uma pasta com todo seu contéudo para o diretório raiz do sistema.
$ gdrive upload --parent ID_DA_PASTA -r /caminho/da/pasta/no/pc → envia uma pasta com todo seu conteúdo para uma pasta específica.
O ID da pasta pode ser obtido pela URL do Google Drive: https://drive.google.com/drive/u/0/folders/ID_DA_PASTA ;

$ gdrive download ID_DO_ARQUIVO → baixa um arquivo.

Programando Localmente a FPGA via JTAG na Nuvem

Executar os comandos abaixo na maquina local

/opt/altera/13.0sp1/nios2eds/nios2_command_shell.sh 
jtagd
jtagconfig --enableremote senha
jtagconfig

Verificar se a porta 6XXXX está em uso

ssh  usuario@191.36.8.33 netstat -lnt | grep 127.0.0.1:60[0-9][0-9][0-9]

Estabelecer um tunel ssh reverso fazendo um bind entre 6XXXX não utilizada e a porta da jtag local

ssh -XC -R 6XXXX:localhost:1309 usuario@191.36.8.33

Para o número da porta a sugestão é utilizar o ID do usuário.

No Quartus é necessário abrir o programador [Tools > Programmer] em seguida [Edit > Hardware Setup] na aba [JTAG Settings] [Add Server] preencher os campos:

Server name: 127.0.0.1:6XXXX
Server password: senha

JTAG settings QUARTUS13.png

Em seguida é necessário selecionar a JTAG na aba [Hardware Settings]

Hardware settings QUARTUS13.png