Você está na página 1de 83

DESCRIÇÃO

Conceitos importantes sobre automatização da implantação, escalonamento e gerenciamento de aplicações via Kubernetes e via OpenShift,
computação acelerada por GPU com Python e Docker Swarm.

PROPÓSITO
O emprego de ferramentas avançadas de desenvolvimento permite ao DevSecOps (desenvolvimento, segurança e operação) obter agilidade,
segurança e ganho de produtividade. Portanto, é importante compreender os conceitos envolvidos e escolher soluções adequadas, como
Kubernetes e OpenShift para automatizar a implantação, o escalonamento e o gerenciamento de aplicações; e de computação acelerada por
GPU com Python e Docker Swarm.

PREPARAÇÃO
É necessário um computador com o sistema operacional Linux, podendo ser uma máquina física ou virtual, com acesso à internet.
OBJETIVOS

MÓDULO 1

Empregar a automatização da implantação, escalonamento e gerenciamento de aplicações via Kubernetes

MÓDULO 2

Empregar a automatização da implantação, escalonamento e gerenciamento de aplicações via OpenShift

MÓDULO 3

Reconhecer computação acelerada por GPU com Python

MÓDULO 4

Descrever Docker Swarm


INTRODUÇÃO
Para entendermos os tópicos avançados em computação distribuída e paralela, iniciaremos apresentando conceitos importantes sobre
containers, seguiremos com um caso de automatização da implantação, escalonamento e gerenciamento de aplicações via Kubernetes e um
caso de automatização da implantação, escalonamento e gerenciamento de aplicações via OpenShift, ambos na nuvem. Em seguida,
estudaremos um exemplo de uso de computação acelerada por GPU com Python utilizando CUDA/NVIDIA e, por fim, exemplificaremos o uso
do Microsoft Azure com Docker Swarm.

MÓDULO 1

 Empregar a automatização da implantação, escalonamento e gerenciamento de aplicações via Kubernetes

ESTUDO DE CASO EM NUVEM ‒ INTRODUÇÃO


Com a necessidade de informações precisas para a tomada de decisões, as aplicações, os sistemas e repositórios de informações vêm
aumentando de forma vertiginosa dentro das organizações. A necessidade de uso de sistemas computacionais aumentou muito a demanda
por soluções tecnológicas, tanto em suporte como em desenvolvimento de sistemas personalizados.
OS RECURSOS DE TECNOLOGIA DA INFORMAÇÃO TORNARAM-SE
DIFERENCIAL ESTRATÉGICO, AUMENTANDO O POTENCIAL
COMPETITIVO DAS ORGANIZAÇÕES.

Para atender a essa demanda, grandes servidores passaram a utilizar a tecnologia de containers em substituição às máquinas virtuais.

Máquinas virtuais (VMs)

As máquinas virtuais (VMs) tradicionais permitem a virtualização da infraestrutura de computação.


Containers

Os containers permitem a virtualização de aplicativos de software.

Diferentemente das máquinas virtuais, os containers usam o sistema operacional (SO) do host, em vez de trazerem um sistema próprio.
Como eles não incluem o sistema operacional completo, os containers exigem recursos computacionais mínimos e são rápidos e fáceis de
instalar.

Essa eficiência permite que eles sejam implantados em clusters, com os containers individuais encapsulando componentes únicos de
aplicativos complexos.

Separar os componentes dos aplicativos em containers diferentes permite que os desenvolvedores atualizem componentes individuais sem
retrabalhar todo o aplicativo.
KUBERNETES
Para facilitar a tarefa de orquestrar microsserviços distribuídos em containers ao longo de clusters, várias soluções de orquestração foram
criadas, entre elas a Kubernetes ou “k8s”, que é uma plataforma de código aberto, desenvolvida pelo Google e disponibilizada em
2014, portável e extensiva para o gerenciamento de cargas de trabalho e serviços distribuídos em containers, que facilita tanto a
configuração declarativa quanto a automação dos containers Linux.

Um cluster Kubernetes consiste em um conjunto de servidores de processamento, chamados nós, que executam aplicações containerizadas.
Todo cluster possui ao menos um servidor de processamento (worker node).

O servidor de processamento hospeda os Pods, que são componentes de uma aplicação. O ambiente de gerenciamento gerencia os nós de
processamento e os Pods no cluster. Em ambientes de produção, o ambiente de gerenciamento geralmente executa em múltiplos
computadores e um cluster geralmente executa em múltiplos nós (nodes), provendo tolerância a falhas e alta disponibilidade.
KUBERNETES IMPLEMENTA TODOS OS MECANISMOS DE ALTA
DISPONIBILIDADE, ISOLAMENTO E ALTA PERFORMANCE DE
CLUSTERS TRADICIONAIS, SÓ QUE AQUI, APLICADO AO CONCEITO DE
CONTAINERS.

Dessa forma, Kubernetes torna possível a criação de um ambiente crítico e concorrente sob a perspectiva de microsserviços, totalmente
baseado em containers, implementa, ainda, um alto nível de abstração. Essa abstração, chamada de Pods, faz com que os containers
sejam independentes da máquina nó. Dentre as várias vantagens, está a facilidade de fazer com que um container “enxergue” o(s) outro(s)
dentro do cluster.

Além de possuir interface gráfica que permite monitorar o ambiente de maneira visual, o Kubernetes permite resolver vários problemas
críticos do uso de cluster de containers, entre eles:

Possibilita o deploy de aplicações em containers Docker (mas não apenas ele) de maneira eficiente e simplificada

Modelo de escala de containers eficiente

Recursos nativos para update de aplicações já existentes

Debug de aplicações já “conteinerizadas” no cluster

Balanceamento de carga entre containers iguais

Os componentes da camada de gerenciamento tomam decisões globais sobre o cluster (por exemplo, agendamento de Pods), bem como
detectam e respondem aos eventos do cluster (por exemplo, iniciando um novo Pod quando o campo réplicas de um Deployment não está
atendido).
Os componentes da camada de gerenciamento podem ser executados em qualquer máquina do cluster. Contudo, para simplificar, os scripts
de configuração normalmente iniciam todos os componentes da camada de gerenciamento na mesma máquina, e não executam containers
de usuário nessa máquina.

Para o uso do Kubernetes, é necessária a instalação do:

KUBEADM

Ferramenta desenvolvida para fornecer "atalhos" de práticas recomendadas para a criação de clusters Kubernetes.

KUBELET

Agente que é executado em cada nó no cluster. Ele garante que os containers estejam sendo executados em um Pod.

KUBECTL

Utilitário de linha de comando usado para se comunicar com o servidor da API do cluster.
INSTALAÇÃO E CONFIGURAÇÃO DO KUBERNETES
Existem distribuições para os principais sistemas operacionais. Optaremos pelo mais recomendado, o Linux.

Para isso, precisaremos da configuração básica de processador com mínimo de 2 CPUs, 2GB ou mais de memória RAM por máquina,
conectividade total entre as máquinas do cluster (neste caso internet – nuvem) e nome de host exclusivo, endereço MAC e product_uuid para
cada nó.

 DICA

Você pode obter o endereço MAC das interfaces de rede usando o comando ip link ou ifconfig -a. O product_uuid pode ser verificado usando
o comando sudo cat/sys/class/dmi/id/product_uuid. É muito provável que os dispositivos de hardware tenham endereços exclusivos, embora
algumas máquinas virtuais possam ter valores idênticos.

O KUBERNETES USA ESSES VALORES PARA IDENTIFICAR


EXCLUSIVAMENTE OS NÓS NO CLUSTER.

Se esses valores não forem exclusivos para cada nó, o processo de instalação pode falhar. Se você tiver mais de um adaptador de rede e
seus componentes do Kubernetes não forem alcançáveis na rota padrão, recomendo adicionar rota (s) IP para que os endereços de cluster
do Kubernetes passem pelo adaptador apropriado.
Certifique-se de que o módulo br_netfilter esteja carregado. Isso pode ser feito executando lsmod | grep br_netfilter. Para carregá-lo
explicitamente, chame sudo modprobe br_netfilter.

Como um requisito para o iptables do seu nó Linux ver corretamente o tráfego em ponte, você deve garantir que net.bridge.bridge-nf-call-
iptables esteja definido como 1 em sua configuração sysctl, como exemplo:

1 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf


2 br_netfilter
3 EOF
4
5 cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
6 net.bridge.bridge-nf-call-ip6tables = 1
7 net.bridge.bridge-nf-call-iptables = 1
8 EOF
9 sudo sysctl --system

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Usaremos uma distribuição baseada em Debian para este exemplo. Siga os passos abaixo:

ATUALIZE O ÍNDICE DO PACOTE APT E INSTALE OS PACOTES NECESSÁRIOS


PARA USAR O REPOSITÓRIO APT DO KUBERNETES:
sudo apt-get update

sudo apt-get install -y apt-transport-https ca-certificates curl

BAIXE A CHAVE DE ASSINATURA PÚBLICA DO GOOGLE CLOUD:


sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
ADICIONE O REPOSITÓRIO APT DO KUBERNETES:
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee
/etc/apt/sources.list.d/kubernetes.list

ATUALIZE O ÍNDICE DO PACOTE APT, INSTALE KUBELET, KUBEADM E KUBECTL


E FIXE SUAS VERSÕES:
sudo apt-get update

sudo apt-get install -y kubelet kubeadm kubectl

sudo apt-mark hold kubelet kubeadm kubectl

O kubelet agora está reiniciando a cada poucos segundos, enquanto espera em um loop de travamento que o kubeadm diga a ele o que
fazer.

VAMOS AGORA CONFIGURAR UM DRIVER CGROUP!

Tanto o tempo de execução do container quanto o kubelet têm uma propriedade chamada "driver cgroup", que é importante para o
gerenciamento de cgroups em máquinas Linux.

O kubeadm permite que você transmita uma estrutura KubeletConfiguration durante a inicialização do kubeadm. Esse KubeletConfiguration
pode incluir o campo cgroupDriver que controla o driver cgroup do kubelet. Se não definirmos o campo cgroupDriver em
KubeletConfiguration, o init do kubeadm o padronizará como systemd.

Crie um balanceador de carga kube-apiserver com um nome que possa ser resolvido por um servidor DNS. Em um ambiente de nuvem, você
deve colocar os nós do plano de controle atrás de um balanceador de carga de encaminhamento de TCP. Esse balanceador de carga
distribui o tráfego para todos os nós do plano de controle íntegros em sua lista de destino. A verificação de saúde de um apiserver é uma
verificação de TCP na porta em que o kube-apiserver escuta (valor padrão: 6443).

 ATENÇÃO

Não é recomendado usar um endereço IP diretamente em um ambiente de nuvem. O balanceador de carga deve ser capaz de se comunicar
com todos os nós do plano de controle na porta apiserver. Ele também deve permitir o tráfego de entrada em sua porta de escuta. Certifique-
se de que o endereço do balanceador de carga sempre corresponda ao endereço do ControlPlaneEndpoint do kubeadm.

A configuração keepalived consiste em dois arquivos: o arquivo de configuração de serviço e um script de verificação de saúde que
será chamado periodicamente para verificar se o nó que contém o IP virtual ainda está operacional. Presume-se que os arquivos
residam em um diretório / etc / keepalived. Observe que, no entanto, algumas distribuições do Linux podem mantê-los em outro lugar.

A seguinte configuração foi usada com sucesso com o keepalived versão 2.0.17:

1 ! /etc/keepalived/keepalived.conf
2 ! Configuration File for keepalived
3 global_defs {
4 router_id LVS_DEVEL
5 }
6 vrrp_script check_apiserver {
7 script "/etc/keepalived/check_apiserver.sh"
8 interval 3
9 weight -2
10 fall 10
11 rise 2
12 }
13
14 vrrp_instance VI_1 {
15 state ${STATE}
16 interface ${INTERFACE}
17 virtual_router_id ${ROUTER_ID}
18 priority ${PRIORITY}
19 authentication {
20 auth_type PASS
21 auth_pass ${AUTH_PASS}
22 }
23 virtual_ipaddress {
24 ${APISERVER_VIP}
25 }
26 track_script {
27 check_apiserver
28 }
29 }

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Existem alguns marcadores de posição no estilo de variável bash para preencher:

${STATE} é MASTER para um e BACKUP para todos os outros hosts, portanto, o IP virtual será inicialmente atribuído ao MASTER.

${INTERFACE} é a interface de rede que participa da negociação do IP virtual, por exemplo, eth0.

${ROUTER_ID} deve ser o mesmo para todos os hosts de cluster keepalived, embora único entre todos os clusters na mesma sub-rede.
Muitas distros pré-configuram seu valor para 51.

${PRIORITY} deve ser maior no nó do plano de controle do que nos backups. Portanto, 101 e 100, respectivamente, serão suficientes.

${AUTH_PASS} deve ser o mesmo para todos os hosts de cluster keepalived, por exemplo, 42.

${APISERVER_VIP} é o endereço IP virtual negociado entre os hosts de cluster keepalived.


A configuração keepalived acima usa um script de verificação de saúde ‒ /etc/keepalived/check_apiserver.sh ‒ responsável por garantir que
no nó que contém o IP virtual o servidor API esteja disponível.

Esse script pode ter a seguinte aparência:

1 #!/bin/sh
2
3 errorExit() {
4 echo "*** $*" 1>&2
5 exit 1
6 }
7 curl --silent --max-time 2 --insecure https://localhost:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "E
8 if ip addr | grep -q ${APISERVER_VIP}; then
9 curl --silent --max-time 2 --insecure https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/ -o /dev/null || e
10 fi

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Existem alguns marcadores de posição no estilo de variável bash para preencher:

$ {APISERVER_VIP}

É o endereço IP virtual negociado entre os hosts de cluster keepalived.

$ {APISERVER_DEST_PORT}

A porta por meio da qual o Kubernetes se comunicará com o servidor da API.configuração proxy.

A configuração do HAProxy consiste em um arquivo: o arquivo de configuração do serviço que se supõe residir em um diretório /etc/haproxy.
Observe que, no entanto, algumas distribuições do Linux podem mantê-los em outro lugar. A seguinte configuração foi usada com sucesso
com o haproxy versão 2.1.4:

1
1
2 # /etc/haproxy/haproxy.cfg
3 #---------------------------------------------------------------------
4 # Global settings
5 #---------------------------------------------------------------------
6 global
7 log /dev/log local0
8 log /dev/log local1 notice
9 daemon
10
11 #---------------------------------------------------------------------
12 # common defaults that all the 'listen' and 'backend' sections will
13 # use if not designated in their block
14 #---------------------------------------------------------------------
15 defaults
16 mode http
17 log global
18 option httplog
19 option dontlognull
20 option http-server-close
21 option forwardfor except 127.0.0.0/8
22 option redispatch
23 retries 1
24 timeout http-request 10s
25 timeout queue 20s
26 timeout connect 5s
27 timeout client 20s
28 timeout server 20s
29 timeout http-keep-alive 10s
30 timeout check 10s
31
32 #---------------------------------------------------------------------
33
33
# apiserver frontend which proxys to the control plane nodes
34
#---------------------------------------------------------------------
35
frontend apiserver
36
bind *:${APISERVER_DEST_PORT}
37
mode tcp
38
option tcplog
39
default_backend apiserver
40
41
#---------------------------------------------------------------------
42
# round robin balancing for apiserver
43
#---------------------------------------------------------------------
44
backend apiserver
45
option httpchk GET /healthz
46
http-check expect status 200
47
mode tcp
48
option ssl-hello-chk
49
balance roundrobin
50
server ${HOST1_ID} ${HOST1_ADDRESS}:${APISERVER_SRC_PORT} check
# [...]

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Novamente, existem alguns marcadores de posição no estilo de variável bash para expandir:

$ {APISERVER_DEST_PORT}: a porta por meio da qual o Kubernetes se comunicará com o servidor da API.

$ {APISERVER_SRC_PORT}: a porta usada pelas instâncias do servidor API.

$ {HOST1_ID}: um nome simbólico para o primeiro host do servidor API com balanceamento de carga.

$ {HOST1_ADDRESS}: um endereço resolvível (nome DNS, endereço IP) para o primeiro host do servidor API com balanceamento de carga.
Linhas de servidor adicionais, uma para cada host de servidor API com balanceamento de carga.

Se o keepalived e haproxy forem executados nos nós do plano de controle, eles podem ser configurados para serem executados
como pods estáticos. Tudo o que é necessário aqui é colocar os respectivos arquivos de manifesto no diretório /etc/kubernetes/manifests
antes de inicializar o cluster. Durante o processo de bootstrap, o kubelet ativará os processos para que o cluster possa usá-los durante a
inicialização. Para essa configuração, dois arquivos de manifesto precisam ser criados em /etc/ kubernetes /manifests.

O manifesto para keepalived: /etc/kubernetes/manifests/keepalived.yaml:


1
2 apiVersion: v1
3 kind: Pod
4 metadata:
5 creationTimestamp: null
6 name: keepalived
7 namespace: kube-system
8 spec:
9 containers:
10 - image: osixia/keepalived:2.0.17
11 name: keepalived
12 resources: {}
13 securityContext:
14 capabilities:
15 add:
16 - NET_ADMIN
17 - NET_BROADCAST
18 - NET_RAW
19 volumeMounts:
20 - mountPath: /usr/local/etc/keepalived/keepalived.conf
21 name: config
22 - mountPath: /etc/keepalived/check_apiserver.sh
23 name: check
24
24
hostNetwork: true
25
volumes:
26
- hostPath:
27
path: /etc/keepalived/keepalived.conf
28
name: config
29
- hostPath:
30
path: /etc/keepalived/check_apiserver.sh
31
name: check
status: {}

 Atenção! Para visualização completa do código utilize a rolagem horizontal

O manifesto para haproxy, /etc/kubernetes/manifests/haproxy.yaml:

1 apiVersion: v1
2 kind: Pod
3 metadata:
4 name: haproxy
5 namespace: kube-system
6 spec:
7 containers:
8 - image: haproxy:2.1.4
9 name: haproxy
10 livenessProbe:
11 failureThreshold: 8
12 httpGet:
13 host: localhost
14 path: /healthz
15 port: ${APISERVER_DEST_PORT}
16 scheme: HTTPS
17
18 volumeMounts:
19 - mountPath: /usr/local/etc/haproxy/haproxy.cfg
20 name: haproxyconf
21 readOnly: true
22 hostNetwork: true
23 volumes:
24 - hostPath:
25 path: /etc/haproxy/haproxy.cfg
26 type: FileOrCreate
27 name: haproxyconf
status: {}

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Observe que aqui, novamente, um placeholder precisa ser preenchido: ${APISERVER_DEST_PORT} precisa conter o mesmo valor que em
/etc/haproxy/haproxy.cfg (veja no código anterior). Essa combinação foi usada com sucesso com as versões utilizadas no exemplo. Outras
versões também podem funcionar ou podem exigir alterações nos arquivos de configuração. Com os serviços ativados, agora o cluster
Kubernetes pode ser inicializado usando o kubeadm ini.
AUTOMATIZANDO APLICAÇÕES COM KUBERNETES
Para finalizar o estudo desse módulo, assista ao vídeo a seguir. Nele, apresentamos um estudo de caso de automatização da implantação,
escalonamento e gerenciamento de aplicações via Kubernetes:
VERIFICANDO O APRENDIZADO

MÓDULO 2

 Empregar a automatização da implantação, escalonamento e gerenciamento de aplicações via OpenShift

INTRODUÇÃO
Com as facilidades advindas do uso de tecnologia, o software está se tornando a ferramenta na qual se constrói o futuro de nossas
empresas, sejam pequenas ou grandes. No centro dessa mudança está a evolução do próprio desenvolvimento de software.
CRIAR MODELOS DE DESENVOLVIMENTO MAIS DINÂMICOS E
ESCALONÁVEIS E AS PRÁTICAS ÁGEIS DE DESENVOLVIMENTO SÃO
AÇÕES NECESSÁRIAS PARA SE MANTER COMPETITIVO NO MERCADO.

Os containers Linux se posicionaram no mercado como a nova base sobre a qual se deve construir conexões entre o desenvolvimento e as
operações, e aproveitar a infraestrutura para seu aplicativo, desde nuvem pública à infraestrutura privada, tornou-se uma necessidade.

OPENSHIFT
O OpenShift é um produto de software de computador da Red Hat para implantação e gerenciamento de softwares baseados em container.
Ele é uma distribuição suportada do Kubernetes usando Docker e ferramentas DevOps para desenvolvimento acelerado de aplicações.
Red Hat OpenShift

O Red Hat OpenShift pode ser executado em qualquer cloud, com recursos avançados para implantações em cloud híbrida.

OpenShift Container Platform

O OpenShift Container Platform pode ser usado em infraestruturas on-premise e de cloud pública.

Isso permite uma abordagem híbrida para a implantação de aplicações como soluções autogerenciadas. Todas as variantes da plataforma
do OpenShift estão disponíveis para acelerar a produtividade do desenvolvedor e fornecer a portabilidade de aplicações em uma
base consistente na cloud híbrida.

O objetivo do OpenShift é fornecer a melhor experiência para desenvolvedores e administradores de sistemas de desenvolvimento,
implantação e execução de aplicativos.

Em outras palavras, OpenShift é uma camada além do Docker e do Kubernetes, que o torna acessível e fácil para o desenvolvedor para criar
aplicativos e uma plataforma que é um sonho para as operadoras implantarem para cargas de trabalho de desenvolvimento e produção.

INSTALAÇÃO E CONFIGURAÇÃO DO OPENSHIFT


Neste exemplo, utilizaremos Linux baseado em Debian (Ubuntu desktop 20.4). Primeiro, vamos instalar o Docker CE em seu sistema para
executar todos os serviços OKD em containers do Docker. Por padrão, a versão mais recente do Docker CE está disponível no repositório
padrão do Ubuntu 20.04.

Você pode instalá-lo executando apenas o seguinte comando:

apt-get install docker.io -y

Depois que o Docker estiver instalado, inicie o serviço Docker e habilite-o para iniciar na inicialização com os seguintes comandos:
systemctl start docker

systemctl enable docker

Vamos verificar o status do serviço Docker com o seguinte comando:

systemctl status docker

Você deve ver a seguinte saída:

1 ? docker.service ‒ Docker Application Container Engine


2 Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled)
3 Active: active (running) since Fri 2020-05-29 12:25:47 UTC; 2s ago
4 TriggeredBy: ? docker.socket
5 Docs: https://docs.docker.com
6 Main PID: 48433 (dockerd)
7 Tasks: 10
8 Memory: 36.5M
9 CGroup: /system.slice/docker.service
10 ??48433 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
11
12 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.215078550Z" level=warning msg="Your ker
13 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.215139097Z" level=warning msg="Your ker
14 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.215169580Z" level=warning msg="Your ker
15 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.215721944Z" level=info msg="Loading con
16 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.418058547Z" level=info msg="Default bri
17 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.515158041Z" level=info msg="Loading con
18 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.545778830Z" level=info msg="Docker daem
19 May 29 12:25:47 ubuntu2004 dockerd[4843 3]: time="2020-05-29T12:25:47.546068892Z" level=info msg="Daemon has
20 May 29 12:25:47 ubuntu2004 dockerd[48433]: time="2020-05-29T12:25:47.599029431Z" level=info msg="API listen
21 May 29 12:25:47 ubuntu2004 systemd[1]: Started Docker Application Container Engine.
 Atenção! Para visualização completa do código utilize a rolagem horizontal

Vamos utilizar a versão V3.11.0 do OpenShift Origin. Você pode baixá-lo do repositório Git Hub usando o seguinte comando:

wget https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz

Assim que o download for concluído, extraia o arquivo baixado com o seguinte comando:

tar -xvzf openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz

Em seguida, altere o diretório para o diretório extraído e copie os binários kubectl e oc para o diretório /usr/local/ bin.

cd openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit

cp oc kubectl /usr/local/bin/

A seguir, verifique a instalação do utilitário cliente OpenShift usando o seguinte comando:

oc version

Você deve ver a seguinte saída:

oc v3.11.0+0cbc58b

kubernetes v1.11.0+d4cacc0

features: Basic-Auth GSSAPI Kerberos SPNEGO

Em seguida, você precisará criar um novo arquivo daemon.json e permitir o uso do registro Insecure Docker.

nano /etc/docker/daemon.json

Adicione a seguinte linha:

"insecure-registries" : [ "172.30.0.0/16" ]
}

Salve, feche o arquivo e reinicie o serviço Docker para implementar as alterações.

systemctl restart docker

Agora, inicie o cluster OpenShift Origin especificando o IP do seu sistema:

oc cluster up --public-hostname=your-server-ip

Assim que o servidor for iniciado com sucesso, você deve obter o seguinte resultado:

1 Login to server ...


2 Creating initial project "myproject" ...
3 Server Information ...
4 OpenShift server started.
5
6 The server is accessible via web console at:
7 https://your-server-ip:8443
8
9 You are logged in as:
10 User: developer
11 Password:
12
13 To login as administrator:
14 oc login -u system:admin

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora, faça login em seu cluster como usuário administrador com o seguinte comando:

oc login -u system:admin
Depois de fazer o login, você deve obter o seguinte resultado:

1 Logged into "https://your-server-ip:8443" as "system:admin" using existing credentials.


2 You have access to the following projects and can switch between them with 'oc project ':
3
4 default
5 kube-dns
6 kube-proxy
7 kube-public
8 kube-system
9 * myproject
10 openshift
11 openshift-apiserver
12 openshift-controller-manager
13 openshift-core-operators
14 openshift-infra
15 openshift-node
16 openshift-service-cert-signer
17 openshift-web-console
18
19 Using project "myproject".

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Em seguida, mude para o projeto padrão com o seguinte comando:

oc project default

Agora, verifique o status atual do seu projeto com o seguinte comando:

oc status
Você deve obter a seguinte saída:

1 In project default on server https://your-server-ip:8443


2
3 svc/docker-registry - 172.30.1.1:5000
4 dc/docker-registry deploys docker.io/openshift/origin-docker-registry:v3.11
5 deployment #1 deployed 2 minutes ago - 1 pod
6
7 svc/kubernetes - 172.30.0.1:443 -> 8443
8
9 svc/router - 172.30.94.157 ports 80, 443, 1936
10 dc/router deploys docker.io/openshift/origin-haproxy-router:v3.11
11 deployment #1 deployed 2 minutes ago - 1 pod
12
13 View details with 'oc describe /' or list everything with 'oc get all'.

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora, faça login no OpenShift com o usuário desenvolvedor com o seguinte comando:

oc login

Será solicitado que você forneça um nome de usuário e uma senha conforme mostrado abaixo:

Authentication required for https://your-server-ip:8443 (openshift)


Username: developer
Password:

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Forneça o nome de usuário como desenvolvedor e a senha como desenvolvedor e pressione Enter. Você deve ver a seguinte saída:
Login successful.
You have one project on this server: "myproject"
Using project "myproject".

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para criar um novo projeto, execute o seguinte comando:

oc new-project dev --display-name="Project - Dev" --description="My Project"

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você deve ver a seguinte saída:

Now using project "dev" on server "https://your-server-ip:8443".


You can add applications to this project with the 'new-app' command. For example, try:
oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git to build a new example application in Rub

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora, abra seu navegador e digite a URL https: //seu-ip-servidor: 8443/console. Você deverá ver a página de login do OpenShift:

Forneça seu nome de usuário e senha de desenvolvedor e clique no botão Login.


Captura de tela de login do Software OpenShift após instalação.

Você deverá ver a seguinte página:

Clique no botão Criar Projeto.


Captura de tela de console do Software OpenShift.

Você deverá ver a seguinte página:

Forneça todas as informações necessárias e clique no botão Criar para criar um novo projeto (Create Project).
Captura de tela de console do Software OpenShift – Criar projeto.

Para implantar aplicativo no OpenShift Origin, primeiro, faça login no OpenShift com o usuário desenvolvedor executando o seguinte
comando:

oc login

Faça login com o usuário desenvolvedor conforme mostrado abaixo:


1
2 Authentication required for https://your-server-ip:8443 (openshift)
3 Username: developer
4 Password:
5 Login successful.
6
7 You have access to the following projects and can switch between them with 'oc project ':
8
9 * dev
10
11 my-project
12 myproject

Using project "dev".

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Depois de fazer o login, mude o projeto para my-project, que você criou por meio do console da Web OpenShift:

oc project my-project

Resultado:

Now using project "my-project" on server "https://your-server-ip:8443".

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Em seguida, verifique o status do seu projeto atual com o seguinte comando:

oc status

Resultado:

In project My Project (my-project) on server https://your-server-ip:8443


You have no services, deployment configs, or build configs.
Run 'oc new-app' to create an application.

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Em seguida, marque uma imagem de aplicativo no registro do Docker Hub com o seguinte comando:
oc tag --source=docker openshift/deployment-example:v2 deployment-example:latest

Resultado:

Tag deployment-example:latest set to openshift/deployment-example:v2.

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Em seguida, implante um aplicativo no OpenShift com o seguinte comando:

oc new-app deployment-example

Você deve ver a seguinte saída:

1 --> Found image da61bb2 (4 years old) in image stream "my-project/deployment-example" under tag "latest" for
2 * This image will be deployed in deployment config "deployment-example"
3 * Port 8080/tcp will be load balanced by service "deployment-example"
4 * Other containers can access this service through the hostname "deployment-example"
5 * WARNING: Image "my-project/deployment-example:latest" runs as the 'root' user which may not be permitt
6 --> Creating resources ...
7 deploymentconfig.apps.openshift.io "deployment-example" created
8 service "deployment-example" created
9 --> Success
10 Application is not exposed. You can expose services to the outside world by executing one or more of the
11 'oc expose svc/deployment-example'
12 Run 'oc status' to view your app.

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora, verifique o status de implantação do aplicativo com o seguinte comando:


oc status

Você deve ver a seguinte saída:

1 In project My Project (my-project) on server https://your-server-ip:8443


2 svc/deployment-example - 172.30.87.146:8080
3 dc/deployment-example deploys istag/deployment-example:latest
4 deployment #1 deployed 36 seconds ago - 1 pod
5 2 infos identified, use 'oc status --suggest' to see details.

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para obter informações sobre seu serviço, execute o seguinte comando:

oc get svc

Resultado:

1 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE


2 deployment-example ClusterIP 172.30.87.146 8080/TCP 1m

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para obter informações detalhadas, execute o seguinte comando:

oc describe svc deployment-example

Resultado:
1
2 Name: deployment-example
3 Namespace: my-project
4 Labels: app=deployment-example
5
6 Annotations: openshift.io/generated-by=OpenShiftNewApp
7 Selector: app=deployment-example,deploymentconfig=deployment-example
8 Type: ClusterIP
9 IP: 172.30.87.146
10 Port: 8080-tcp 8080/TCP
11 TargetPort: 8080/TCP
12 Endpoints: 172.17.0.10:8080
Session Affinity: None
Events:

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você também pode verificar o status dos pods usando o seguinte comando:

oc get pods

Resultado:

1 Resultado:
2 NAME READY STATUS RESTARTS AGE
3 deployment-example-1-b9prf 1/1 Running 0 2m

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora, exponha o aplicativo para acesso externo usando o seguinte comando:

oc expose service/deployment-example

Resultado:
Resultado:
route.route.openshift.io/deployment-example exposed

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para exibir as informações das rotas, execute o seguinte comando:

oc get routes

Você deve obter a seguinte saída:

1 NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD


2 deployment-example deployment-example-my-project.your-server-ip.nip.io deployment-example 8080-

 Atenção! Para visualização completa do código utilize a rolagem horizontal


AUTOMATIZANDO APLICAÇÕES COM OPENSHIFT
Para finalizar o estudo desse módulo, assista ao vídeo a seguir. Nele, apresentamos um estudo de caso de automatização da implantação,
escalonamento e gerenciamento de aplicações via Openshift:
VERIFICANDO O APRENDIZADO

MÓDULO 3

 Reconhecer computação acelerada por GPU com Python


INTRODUÇÃO AO PYTHON

PYTHON É UMA LINGUAGEM DE PROGRAMAÇÃO DINÂMICA DE ALTA


PRODUTIVIDADE AMPLAMENTE USADA EM APLICATIVOS DE CIÊNCIA,
ENGENHARIA E ANÁLISE DE DADOS.

Há uma série de fatores que influenciam a popularidade do Python, incluindo sua sintaxe limpa e expressiva, estruturas de dados padrão,
biblioteca padrão abrangente, "baterias incluídas", documentação excelente, amplo ecossistema de bibliotecas e ferramentas, disponibilidade
de suporte profissional e uma grande e aberta comunidade.
Talvez o mais importante, porém, seja a alta produtividade que uma linguagem interpretada e digitada dinamicamente como o Python permite.
Python é ágil e flexível, o que o torna uma ótima linguagem para prototipagem rápida, mas também para construir sistemas completos.

 ATENÇÃO

Mas a maior força do Python também pode ser sua maior fraqueza: sua flexibilidade e sintaxe de alto nível sem tipo podem resultar em baixo
desempenho para programas com uso intensivo de dados e computação. Por esse motivo, os programadores Python preocupados com a
eficiência geralmente reescrevem seus loops mais internos em C e chamam as funções C compiladas do Python.

Existem vários projetos que visam tornar essa otimização mais fácil, como o Cython, mas geralmente exigem o aprendizado de uma nova
sintaxe. Idealmente, os programadores Python gostariam de tornar seu código Python existente mais rápido sem usar outra linguagem de
programação e, naturalmente, muitos gostariam de usar aceleradores para obter um desempenho ainda maior de seu código.
CUDA/NVIDIA

O NVIDIA CUDA É UMA PLATAFORMA DE COMPUTAÇÃO PARALELA E


UM MODELO DE PROGRAMAÇÃO PARA SER USADO COM GPUS.

GPUS

Graphic Processing Units, unidades de processamento gráfico, em inglês.

Com ele, toda a parte “pesada” do código é executada nos diversos núcleos da placa de vídeo enquanto apenas a parte sequencial do
código é executada no processador, obtendo um ganho significativo de performance.

 ATENÇÃO

O uso da GPU tem custos indiretos. Se o cálculo não for pesado o suficiente, o custo (em tempo) de usar uma GPU pode ser maior do que o
ganho. Por outro lado, se o cálculo for pesado, você pode ver uma grande melhoria na velocidade.

Vários termos importantes no tópico de programação CUDA estão listados aqui:


Host: a CPU

Device: a GPU

Host memory: a memória principal do sistema

Device memory: memória integrada em um cartão GPU

Kernel: uma função GPU lançada pelo host e executada no dispositivo

Device function: uma função GPU executada no dispositivo que só pode ser chamada a partir do dispositivo (ou seja, a partir de um kernel ou
outra função do dispositivo).

Numba oferece suporte à programação de GPU CUDA compilando diretamente um subconjunto restrito de código Python em kernels CUDA e
funções de dispositivo seguindo o modelo de execução CUDA. Kernels escritos em Numba parecem ter acesso direto aos arrays NumPy.
Matrizes NumPy são transferidas entre a CPU e a GPU automaticamente. Numba funciona permitindo que você especifique assinaturas de
tipo para funções Python, o que permite a compilação em tempo de execução (isto é, “Just-in-Time” ou compilação JIT).

A capacidade do Numba de compilar código dinamicamente significa que você não abre mão da flexibilidade do Python. Esse é um
grande passo para fornecer a combinação ideal de programação de alta produtividade e computação de alto desempenho.

 EXEMPLO

O decorador @vectorize, no código a seguir, gera uma versão compilada e vetorizada da função escalar em tempo de execução para que
possa ser usada para processar matrizes de dados em paralelo na GPU.
1
2 import numpy as np
3 from numba import vectorize
4
5
5
@vectorize(['float32(float32, float32)'], target='cuda')
6
def Add(a, b):
7
return a + b
8
9
# Initialize arrays
10
N = 100000
11
A = np.ones(N, dtype=np.float32)
12
B = np.ones(A.shape, dtype=A.dtype)
13
C = np.empty_like(A, dtype=A.dtype)
14
15
# Add arrays on GPU
C = Add(A, B)

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para compilar e executar a mesma função na CPU, simplesmente mudamos o destino para 'cpu', o que produz desempenho no nível do
código C vetorizado e compilado na CPU. Essa flexibilidade ajuda a produzir código mais reutilizável e permite desenvolver em máquinas
sem GPUs.

Um dos pontos fortes da plataforma de computação paralela CUDA é a variedade de bibliotecas aceleradas por GPUs disponíveis.

Outro projeto da equipe Numba, chamado pyculib, fornece uma interface Python para as bibliotecas CUDA cuBLAS (álgebra linear densa),
cuFFT (Fast Fourier Transform) e cuRAND (geração de número aleatório).

Muitos aplicativos serão capazes de obter uma aceleração significativa apenas usando essas bibliotecas, sem escrever nenhum código
específico da GPU. Por exemplo, o código a seguir gera um milhão de números aleatórios uniformemente distribuídos na GPU usando o
gerador de números pseudoaleatórios “XORWOW”.

1 import numpy as np
2 from pyculib import rand as curand
3
3
4
prng = curand.PRNG(rndtype=curand.PRNG.XORWOW)
5
rand = np.empty(100000)
6
prng.uniform(rand)
7
print rand[:10]

 Atenção! Para visualização completa do código utilize a rolagem horizontal

INSTALAÇÃO DO NUMBA

NUMBA É UM PROJETO DE CÓDIGO ABERTO, LICENCIADO POR BSD,


QUE SE BASEIA FORTEMENTE NAS CAPACIDADES DO COMPILADOR
LLVM.

O back-end da GPU do Numba utiliza o NVIDIA Compiler SDK baseado em LLVM. Os wrappers pyculib em torno das bibliotecas CUDA
também são de código aberto e licenciados por BSD.

Para começar a usar o Numba, a primeira etapa é baixar e instalar a distribuição Anaconda Python, uma "distribuição Python totalmente
gratuita, pronta para empresas, para processamento de dados em grande escala, análise preditiva e computação científica" que inclui muitos
pacotes populares (Numpy, SciPy, Matplotlib, IPython etc).

Digite o comando:
apt-get install libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora, você pode ativar a instalação fazendo um source no arquivo ~/.bashrc: source ~/.bashrc

Assim que tiver feito isso, você será levado ao ambiente de programação padrão de base do Anaconda, e seu prompt de comando mudará
para o seguinte: (base) summy@ubuntu:~$

Embora o Anaconda venha com esse ambiente de programação padrão de base, você deve criar ambientes separados para seus
programas e mantê-los isolados um do outro. Você pode, ainda, verificar sua instalação fazendo o uso do comando conda, por exemplo,
com list:

(base) summy@ubuntu:~$ conda list

Você receberá a saída de todos os pacotes disponíveis através da instalação do Anaconda.

1 # packages in environment at /home/sammy/anaconda3:


2 # Name Version Build Channel
3 _ipyw_jlab_nb_ext_conf 0.1.0 py37_0
4 _libgcc_mutex 0.1 main
5 alabaster 0.7.12 py37_0
6 anaconda 2020.02 py37_0
7 ...

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Agora que o Anaconda está instalado, podemos seguir em frente para a configuração dos ambientes dele.
 ATENÇÃO

Os ambientes virtuais do Anaconda lhe permitem manter projetos organizados pelas versões do Python e pelos pacotes necessários. Para
cada ambiente do Anaconda que você configurar, especifique qual versão do Python usar e mantenha todos os arquivos de programação
relacionados dentro desse diretório.

Primeiro, podemos verificar quais versões do Python estão disponíveis para que possamos usar: (base) summy@ubuntu:~$ conda search
"^python$"

VAMOS CRIAR UM AMBIENTE USANDO A VERSÃO MAIS RECENTE DO


PYTHON 3.

Podemos conseguir isso atribuindo a versão 3 ao argumento python. Vamos chamar o ambiente de my_env, mas você pode usar um nome
mais descritivo para o ambiente, especialmente se estiver usando ambientes para acessar mais de uma versão do Python.

(base) summy@ubuntu:~$ conda create --name my_env python=3

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você receberá uma saída com informações sobre o que está baixado e quais pacotes serão instalados e, em seguida, será solicitado a
prosseguir com y ou n. Assim que concordar, digite y.

O utilitário conda agora irá obter os pacotes para o ambiente e informá-lo assim que estiver concluído. Você pode ativar seu novo ambiente
digitando o seguinte:
(base) summy@ubuntu:~$ conda activate my_env

Com seu ambiente ativado, seu prefixo do prompt de comando irá refletir que você não está mais no ambiente base, mas no novo ambiente
que acabou de criar.

(my_env) summy@ubuntu:~$

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Dentro do ambiente, você pode verificar se está usando a versão do Python que tinha intenção de usar: (my_env) summy@ubuntu:~$ python
–version

 RESPOSTA

Python 3.8.2

Quando estiver pronto para desativar seu ambiente do Anaconda, você pode fazer isso digitando: (my_env) summy@ubuntu:~$ conda
deactivate

Observe que pode substituir a palavra source por . para obter os mesmos resultados. Para focar em uma versão mais específica do
Python, você pode passar uma versão específica para o argumento python, como 3.5, por exemplo:

(base) summy@ubuntu:~$ conda create -n my_env35 python=3.5

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você pode inspecionar todos os ambientes que configurou com este comando:
(base) summy@ubuntu:~$ conda info –envs

# conda environments:
#
base * /home/sammy/anaconda3
my_env /home/sammy/anaconda3/envs/my_env
my_env35 /home/sammy/anaconda3/envs/my_env35

 Atenção! Para visualização completa do código utilize a rolagem horizontal

O asterisco indica o ambiente ativo atual. Cada ambiente que você criar com o conda create virá com vários pacotes padrão:

_libgcc_mutex

ca-certificates

certifi

libedit

libffi

libgcc-ng

libstdcxx-ng
ncurses

openssl

pip

python

readline

setuptools

sqlite

tk

wheel

xz

zlib

Você pode acrescentar pacotes adicionais, como o Numpy, por exemplo, com o seguinte comando:

(base) summy@ubuntu:~$ conda install --name my_env35 numpy


Se você já sabe que gostaria de um ambiente Numpy após a criação, pode concentrá-lo em seu comando conda create:

(base) summy@ubuntu:~$ conda create --name my_env python=3 numpy

Se você não estiver mais trabalhando em um projeto específico e não tiver mais necessidade do ambiente associado, pode removê-lo. Para
fazer isso, digite o seguinte:

(base) summy@ubuntu:~$ conda remove --name my_env35 --all

 ATENÇÃO

Agora, quando você digitar o comando conda info --envs, o ambiente que removeu não será mais listado.

Você deve garantir regularmente que o Anaconda esteja atualizado para que você esteja trabalhando com todas as versões mais recentes do
pacote. Para fazer isso, deve primeiro atualizar o utilitário conda: (base) summy@ubuntu:~$ conda update conda

Quando solicitado a fazer isso, digite y para continuar com a atualização. Assim que a atualização do conda estiver concluída, você pode
atualizar a distribuição do Anaconda:

(base) summy@ubuntu:~$ conda update anaconda

 ATENÇÃO

Novamente, quando solicitado a fazer isso, digite y para continuar. Isso garantirá que você esteja usando as versões mais recentes do conda
e do Anaconda.
Depois de instalar o Anaconda, instale os pacotes CUDA necessários digitando:

conda install numba cudatoolkit pyculib

 Atenção! Para visualização completa do código utilize a rolagem horizontal

O Anaconda (anteriormente Continuum Analytics) reconheceu que alcançar grandes acelerações em alguns cálculos requer uma interface de
programação mais expressiva com controle mais detalhado sobre o paralelismo do que as bibliotecas e a vetorização automática de loop
podem fornecer.

Portanto, o Numba possui outro conjunto importante de recursos que constitui o que é conhecido não oficialmente como “CUDA
Python”.

Numba expõe o modelo de programação CUDA, assim como em CUDA C / C ++, mas usando a sintaxe Python pura, para que os
programadores possam criar kernels paralelos personalizados e ajustados sem deixar o conforto e as vantagens do Python para trás. O
CUDA JIT da Numba (disponível via decorador ou chamada de função) compila funções CUDA Python em tempo de execução,
especializando-as para os tipos que você usa, e sua API CUDA Python fornece controle explícito sobre transferências de dados e fluxos
CUDA, entre outros recursos.

O exemplo de código a seguir demonstra isso com um kernel de conjunto Mandelbrot simples. Observe que a função mandel_kernel
usa as estruturas cuda.threadIdx, cuda.blockIdx, cuda.blockDim e cuda.gridDim fornecidas por Numba para calcular os índices globais de
pixel X e Y para o segmento atual. Como em outras linguagens CUDA, lançamos o kernel inserindo uma "configuração de execução"
(linguagem CUDA para o número de threads e blocos de threads a serem usados para executar o kernel) entre colchetes, entre o nome da
função e a lista de argumentos: mandel_kernel [griddim, blockdim] (- 2.0, 1.0, -1.0, 1.0, d_image, 20). Você também pode ver o uso das
funções de API to_host e to_device para copiar dados de e para a GPU.
1
2 @cuda.jit
3 def mandel_kernel(min_x, max_x, min_y, max_y, image, iters):
4 height = image.shape[0]
5 width = image.shape[1]
6
7 pixel_size_x = (max_x - min_x) / width
8 pixel_size_y = (max_y - min_y) / height
9
10 startX = cuda.blockDim.x * cuda.blockIdx.x + cuda.threadIdx.x
11 startY = cuda.blockDim.y * cuda.blockIdx.y + cuda.threadIdx.y
12 gridX = cuda.gridDim.x * cuda.blockDim.x;
13 gridY = cuda.gridDim.y * cuda.blockDim.y;
14
15 for x in range(startX, width, gridX):
16 real = min_x + x * pixel_size_x
17 for y in range(startY, height, gridY):
18 imag = min_y + y * pixel_size_y
19 image[y, x] = mandel(real, imag, iters)
20
21 gimage = np.zeros((1024, 1536), dtype = np.uint8)
22 blockdim = (32, 8)
23 griddim = (32,16)
24
25 start = timer()
26 d_image = cuda.to_device(gimage)
27 mandel_kernel[griddim, blockdim](-2.0, 1.0, -1.0, 1.0, d_image, 20)
28 d_image.to_host()
29 dt = timer() - start
30
31 print "Mandelbrot created on GPU in %f s" % dt
32
imshow(gimage)
 Atenção! Para visualização completa do código utilize a rolagem horizontal

 SAIBA MAIS

Em um servidor com uma GPU NVIDIA Tesla P100 e uma CPU Intel Xeon E5-2698 v3, este código CUDA Python Mandelbrot é executado
quase 1700 vezes mais rápido do que a versão Python pura. 1700x pode parecer uma aceleração irreal, mas tenha em mente que estamos
comparando o código Python compilado, paralelo e acelerado por GPU ao código Python interpretado de thread único na CPU.
COMPUTAÇÃO ACELERADA COM PYTHON
No vídeo a seguir, abordamos o conceito de computação acelerada com Python utilizando CUDA/Nvidia:

VERIFICANDO O APRENDIZADO

MÓDULO 4

 Descrever Docker Swarm


INTRODUÇÃO AO DOCKER

DOCKER É UMA PLATAFORMA ABERTA PARA DESENVOLVIMENTO,


ENVIO E EXECUÇÃO DE APLICATIVOS.

O Docker permite que você separe seus aplicativos de sua infraestrutura para que possa entregar software rapidamente. Com o Docker, é
possível gerenciar sua infraestrutura da mesma forma que gerencia seus aplicativos. Tirando proveito das metodologias do Docker para
envio, teste e implantação de código rapidamente, você pode reduzir significativamente o atraso entre escrever o código e executá-lo na
produção.

INSTALAÇÃO DO DOCKER
Antes de instalar o Docker Engine pela primeira vez em uma nova máquina host, você precisa configurar o repositório do Docker. Depois
disso, pode instalar e atualizar o Docker a partir do repositório. Atualize o índice do pacote apt e instale os pacotes para permitir que o apt use
um repositório sobre HTTPS:

1 $sudo apt-get update


2
3 $ sudo apt-get install \
4
5 apt-transport-https \
6 ca-certificates \
7 curl \
8 gnupg \
lsb-release

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Adicione a chave GPG oficial do Docker:

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-arch

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Use o seguinte comando para configurar o repositório estável. Para adicionar o repositório noturno ou de teste, adicione a palavra nightly ou
test (ou ambos) após a palavra stable nos comandos abaixo:

$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Atualize o índice do pacote apt e instale a versão mais recente do Docker Engine e containerd ou vá para a próxima etapa para instalar uma
versão específica:

$ sudo apt-get update


$ sudo apt-get install docker-ce docker-ce-cli containerd.io

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para instalar uma versão específica do Docker Engine, liste as versões disponíveis no repo, selecione e instale uma. Liste as versões
disponíveis em seu repo:

$ apt-cache madison docker-ce

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Instale uma versão específica usando a string de versão da segunda coluna:

$ sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Verifique se o Docker Engine está instalado corretamente executando a imagem hello-world:

$ sudo docker run hello-world

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Este comando baixa uma imagem de teste e a executa em um container. Quando o container é executado, ele imprime uma mensagem
informativa e sai. O Docker Engine está instalado em execução. O grupo docker é criado, mas nenhum usuário é adicionado a ele.

Você precisa usar sudo para executar comandos do Docker.


Continue a pós-instalação do Linux para permitir que usuários sem privilégios executem comandos do Docker e para outras etapas de
configuração opcionais.

CONFIGURANDO A CLI DO AZURE

Quando a CLI do Azure for configurada, você precisará fazer login. Você será solicitado a inserir um código em seu navegador. Depois disso,
o comando continuará:

az login

To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code C3H44PMX7 to authent

 Atenção! Para visualização completa do código utilize a rolagem horizontal

O comando deve retornar um json semelhante a este:

[
{
"cloudName": "AzureCloud",
"id": "xxxxxxx",
"isDefault": true,
"name": "Free Trial",
"state": "Enabled",
"tenantId": "xxxxxx",
"user": {
"name": "xxxxx",
"type": "user"
}
}
]

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Depois de fazer login, você pode executar comandos az, como o az account show mostrando algumas informações da conta:

1 {
2 "environmentName": "AzureCloud",
3 "id": "c1ddf2e6-8c94-490c-a1f0-e54d24f76323",
4 "isDefault": true,
5 "name": "Free Trial",
6 "state": "Enabled",
7 "tenantId": "930763d2-b2ba-4d30-bd7b-908bbf4ac227",
8 "user": {
9 "name": "davy.dewaele@ixor.be",
10 "type": "user"
11 }
12 }

 Atenção! Para visualização completa do código utilize a rolagem horizontal

DOCKER SWARM NA MICROSOFT AZURE


O método que usaremos para configurar o Docker Swarm no Azure é usando um modelo do Azure que é criado pela equipe do Docker (e não
pela Microsoft). Ao usar este tema, poderemos utilizar as versões mais recentes do Docker/Swarm, ao mesmo tempo em que nos integramos
perfeitamente ao Microsoft Azure Cloud.

 ATENÇÃO

Antes de começarmos com o Docker para Azure, devemos criar uma entidade de serviço em nosso Active Directory. Pense nisso como um
usuário que tem permissões para fazer coisas de infraestrutura de baixo nível, como escalar suas VMs, atualizar suas regras de balanceador
de carga. Operações necessárias para uma solução dinâmica Docker Swarm no Azure.

Existem duas maneiras de criar um principal de serviço:

Por meio de um container do docker, conforme descrito no guia do Docker para Azure.


Por meio do Portal do Azure (no módulo Active Directory, criando um registro de aplicativo).

Vamos usar a linha de comando e ativar o container do docker, que leva 3 argumentos:

O nome principal do serviço

O nome do grupo de recursos

A Região Azure

O comando é parecido com este:


docker run -ti docker4x/create-sp-azure sp1 swarm1 westeurope

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Isso vai criar:

Um aplicativo do Active Directory que permite que o swarm dimensione/exponha portas

Um ServicePrincipal (com um ID de aplicativo e segredo de aplicativo)

Um grupo de recursos

Você precisará fazer o login através do seu navegador para iniciar a CLI. Depois disso, você receberá um bom resumo no final.

1 Your access credentials ==================================================


2 AD ServicePrincipal App ID: 98369e6d-9d9c-419d-86fa-075ce0cdcc83
3 AD ServicePrincipal App Secret: FITLMrNLMpokhi3YvZPbm7y36FDsUkXn
4 AD ServicePrincipal Tenant ID: 930763d2-b2ba-4d30-bd7b-908bbf4ac227
5 Resource Group Name: swarm1
6 Resource Group Location: westeurope

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você pode olhar no portal para ver se a entidade de serviço foi criada.
 Captura de tela do portal Microsoft Azure após iniciar CLI.

O APPID E O APPSECRET SERÃO NECESSÁRIOS AO EXECUTAR O


MODELO DOCKER.

Existem duas maneiras de instalar a oferta Docker para Azure, por meio da IU do Azure, seguindo o link do modelo do Docker para Azure, e
por meio da CLI do Azure, permitindo automatizar ainda mais a implantação. Abordaremos as duas opções.

INSTALANDO O DOCKER PARA AZURE USANDO A IU DO AZURE.


Seguiremos as etapas no guia do Docker para Azure. Ao clicar no botão para instalar o Docker para Azure, você será redirecionado para o
portal do Azure, onde será solicitado a preencher algumas propriedades como:

AppID;

AppSecret;

Public SSH Key;

Number + Type of workers;

Number + Type of managers.


 Captura de tela do portal do Microsoft Azure após instalação.

A criação de toda a pilha levará alguns minutos. Você pode monitorar o progresso na janela de notificações. Quando a implantação for
concluída, você será redirecionado para a seção de visão geral do grupo de recursos. Aqui você encontrará todos os recursos que foram
criados usando o modelo Docker para Azure.
 Captura de tela do portal Microsoft Azure visão de recursos.

O modelo criou vários recursos, incluindo:

IP público para o balanceador de carga (para expor seus aplicativos)

IP público para o balanceador de carga SSH (para SSH-ing em seu gerenciador de swarm)

Conjuntos de escala de VM, capazes de gerar máquinas virtuais

Balanceadores de carga

Redes virtuais

Contas de armazenamento
VOCÊ TAMBÉM PODE INSTALAR O DOCKER PARA AZURE USANDO A
CLI.

Novamente, certifique-se de ter criado o principal de serviço:

docker run -ti docker4x/create-sp-azure docker-for-azure-sp docker-for-azure-rg centralus

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Em seguida, crie a implantação:

az group deployment create --name docker-swarm-deployment --resource-group docker-for-azure-rg --template-uri htt


Please provide string value for 'adServicePrincipalAppID' (? for help): xxxxxx
Please provide securestring value for 'adServicePrincipalAppSecret' (? for help): xxxxxx
Please provide string value for 'sshPublicKey' (? for help): ssh-rsa xxxxxx

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você precisará fornecer:

adServicePrincipalAppID;

adServicePrincipalAppSecret;

chave SSH pública.


Você pode utilizar um arquivo de parâmetros como este para uma instalação silenciosa completa de toda a pilha sem que ela solicite nada:
1
2 {
3 "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
4 "contentVersion": "1.0.0.0",
5 "parameters": {
6 "adServicePrincipalAppID": {
7 "value": "2069aee6-5520-4790-8cc1-ae4e745e01bc"
8 },
9 "adServicePrincipalAppSecret": {
10 "value": "34279fd7-1fd5-451b-95fe-cb8f84f2615b"
11 },
12 "enableSystemPrune": {
13 "value": "no"
14 },
15 "managerCount": {
16 "value": 1
17 },
18 "managerVMSize": {
19 "value": "Standard_D1_v2"
20 },
21 "sshPublicKey": {
22 "value": "ssh-rsa xxxxxx"
23 },
24 "swarmName": {
25 "value": "dockerswarm"
26 },
27 "workerCount": {
28 "value": 2
29 },
30 "workerVMSize": {
31
32 "value": "Standard_D1_v2"
33 }
}
}

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para tanto, execute o seguinte comando:

docker run -ti docker4x/create-sp-azure docker-for-azure-sp docker-for-azure-rg centralus az group deployment cre

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Para saber como se conectar ao gerenciador de swarm, você precisa ir para o modelo de implantação do cluster de swarm (por meio do
grupo de recursos):
 Captura de tela do portal Microsoft Azure – grupo de recursos.

Ao clicar no modelo, você encontrará duas propriedades interessantes:

DefaultDNSTargets;

SSH targets.

 Captura de tela do portal Microsoft Azure – Default DNS.

O DefaultDNSTargets dá acesso ao cluster swarm. Todos os aplicativos que forem iniciados lá serão disponibilizados naquele IP. Os
serviços Docker Swarm que expõem uma porta verão sua porta exposta por meio do balanceador de carga externo nesse IP. Os SSH Targets
mostrarão como você pode acessar o cluster swarm via SSH.
 Captura de tela do portal Microsoft Azure ‒ DefaultDNSTargets.

Por padrão, o gerenciador Swarm escutará na porta 50000. Para SSH no gerenciador, execute este comando:

ssh -A docker@52.174.20.207 -p 50000

 Atenção! Para visualização completa do código utilize a rolagem horizontal

 ATENÇÃO

Observe como usamos o encaminhamento de chave do Agente SSH. Isso vai se tornar importante mais tarde, quando quisermos fazer login
nos nós de trabalho.

Mas, uma vez que estamos no gerenciador de swarm, podemos executar os comandos docker conhecidos:

Docker version
Welcome to Docker!

swarm-manager000000:~$ docker -v
Docker version 17.06.0-ce, build 02c1d87

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Docker containers

1 swarm-manager000000:~$ docker ps
2 CONTAINER ID IMAGE COMMAND CREATED
3 1891668c2a41 docker4x/l4controller-azure:17.06.0-ce-azure2 "loadbalancer run ..." 2 minutes ago
4 5069b42130ea docker4x/meta-azure:17.06.0-ce-azure2 "metaserver -iaas_..." 2 minutes ago
5 1e55147b18b1 docker4x/guide-azure:17.06.0-ce-azure2 "/entry.sh" 2 minutes ago
6 79db940f7e63 docker4x/logger-azure:17.06.0-ce-azure2 "python /server.py" 3 minutes ago
7 456a2a2df8fd docker4x/init-azure:17.06.0-ce-azure2 "/entry.sh" 4 minutes ago
8 20c56749ed4e docker4x/agent-azure:17.06.0-ce-azure2 "supervisord --con..." 5 minutes ago

 Atenção! Para visualização completa do código utilize a rolagem horizontal

See the swarm nodes

1 swarm-manager000000:~$ docker node ls


2 ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
3 r62i4rpvp1kmxlf7goamkbsy8 swarm-worker000000 Ready Active
4 rwk7lhwndmg86m4rkaa3upwmu * swarm-manager000000 Ready Active Leader
5 vtvh17ce0qsc37ecy8k5dng11 swarm-worker000001 Ready Active

 Atenção! Para visualização completa do código utilize a rolagem horizontal


Caso esteja vendo algo assim:

warm-manager000000:~$ docker node ls


Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to c

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Você sabe que algo está errado, e um bom lugar para começar é verificar os logs do container docker init-azure (veja abaixo). Normalmente,
os erros surgem ao usar o responsável pelo serviço errado. Em caso de erros, você pode excluir o grupo e começar de novo:

az group delete --name docker-for-azure-test-rg


Are you sure you want to perform this operation? (y/n): y
| Running ..

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Problemas de depuração. Em termos de depuração, o comando a seguir fornecerá alguns insights sobre o que aconteceu quando o Azure
estava configurando o cluster swarm.

docker logs $(docker ps -a | grep init-azure | cut -d' ' -f1)

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Conecte-se a um trabalhador. Para se conectar aos trabalhadores de que você precisa:

Faça login no gerenciador com encaminhamento do Agente SSH (switch -A);

Descubra o domínio de pesquisa DNS da instalação (procure em /etc/resolv.conf);


SSH nas máquinas.

swarm-manager000000:~$ ssh docker@swarm-worker000001.oqzhphocr3cublz2fzkpyrwd5c.ax.internal.cloudapp.net

 Atenção! Para visualização completa do código utilize a rolagem horizontal

UM DOS ITENS CRIADOS DURANTE A DISTRIBUIÇÃO DO DOCKER


PARA AZURE É UM BALANCEADOR DE CARGA EXTERNO.

O balanceador de carga externo possui um IP que pode ser acessado da internet. Assim que começarmos a adicionar serviços de enxame
que expõem uma porta, você notará que essas portas também serão exportadas no balanceador de carga.
 Captura de tela do portal Microsoft Azure – Balanceador de carga externa.

Serviços de lançamento. Inicialmente, criaremos nossa rede:

1 docker network create \


2 --driver overlay \
3 --subnet 10.0.9.0/24 \
4 --gateway 10.0.9.99 \
5 cnet

 Atenção! Para visualização completa do código utilize a rolagem horizontal

E, então, inicie um serviço:

docker service create --network cnet --name nginx1 -p 80:80 nginx


 Atenção! Para visualização completa do código utilize a rolagem horizontal

Observe como agora vemos uma regra associada ao nosso balanceador de carga:

 Captura de tela do portal Microsoft Azure – Balanceador externo.

E, se olharmos mais de perto, veremos de fato a regra do balanceador de carga que encaminhará o tráfego externo em nosso balanceador
de carga na porta 00 para nosso serviço Swarm (também em execução na porta 80).
 Captura de tela do portal Microsoft Azure – Balanceador externo.

Esses serviços ficarão disponíveis imediatamente por meio do balanceador de carga:

1 docker service create --network cnet --name nginx2 -p 81:80 nginx


2 docker service create --network cnet --name nginx3 -p 82:80 nginx
3 docker service create --network cnet --name nginx4 -p 0:80 nginx
4 docker service create --network cnet --name nginx5 nginx
5
6 docker service scale nginx3=10

 Atenção! Para visualização completa do código utilize a rolagem horizontal

Com todos esses containers sendo gerados, é importante ser capaz de ler arquivos de log para obter melhores insights sobre seus
containers. Você provavelmente está familiarizado com o comando docker logs para ler os logs vindos de um container, mas no Azure, ao
tentar olhar os logs do docker, você receberá o seguinte erro:
swarm-worker000001:~$ docker logs -f d7e9d806f872
Error response from daemon: configured logging driver does not support reading

 Atenção! Para visualização completa do código utilize a rolagem horizontal

O Docker para Azure usa um driver de log diferente e usa um container logger-azure para garantir que todos os logs de todos os containers
sejam centralizados. Se você observar o grupo de recursos usados para criar o docker swarm, verá uma conta de armazenamento
chamada on6fwskwzstvqlogs.

 Captura de tela do portal Microsoft Azure – Driver log.

Quando você se conecta a esta conta de armazenamento, o Azure mostra os cmds para se conectar a ela a partir do Windows ou Linux.
 Captura de tela do portal Microsoft Azure – servidor de arquivos – pasta LOG.

No Linux, você pode montar a pasta de logs em um servidor virtual na mesma região (não funciona nas VMs Docker Swarm).
 Captura de tela do portal Microsoft Azure – servidor de arquivos – pasta LOG.

Para montar a pasta de registro, basta executar os seguintes comandos:

1 mkdir -p /var/logs/docker
2 sudo mount -t cifs //le66r7q7iia3klogs.file.core.windows.net/docker4azurelogs /var/logs/docker -o vers=3.0,u

 Atenção! Para visualização completa do código utilize a rolagem horizontal


DOCKER SWARM
Chegamos ao fim de mais um módulo. E, para finalizar os estudos, apresentamos o conceito de Docker Swarm, incluindo estudo de caso em
Microsoft Azure, no vídeo a seguir:
VERIFICANDO O APRENDIZADO

CONCLUSÃO

CONSIDERAÇÕES FINAIS
Estudamos conceitos importantes sobre automatização da implantação, escalonamento e gerenciamento de aplicações via Kubernetes e via
OpenShift, incluindo estudo de caso na nuvem em ambos. Compreendemos computação acelerada por GPU com Python com CUDA/NVIDIA
e finalizamos com a aprendizagem sobre Docker Swarm, com estudo de caso em Microsoft Azure.
 PODCAST
Ouça o podcast a seguir. Nele, apresentamos uma visão geral do conteúdo, focando as vantagens da utilização de containers no
gerenciamento das aplicações comparada a soluções tradicionais, como o uso de máquinas físicas ou virtuais.

AVALIAÇÃO DO TEMA:

REFERÊNCIAS
ARUNDEL, J.; DOMINGUS, J. DevOps nativo de nuvem com Kubernetes ‒ Como construir, implantar e escalar aplicações modernas na
nuvem. São Paulo: Novatec, 2019.

BLOKDYK, G. OpenShift ‒ A Complete Guide. Brisbane: Emereo Pty Ltd, 2019.

FARBER, R. Cuda: Application Design and Development. Amsterdam: Morgan Kaufmann Publishers, 2011.
FARCIC, V. The DevOps 2.1 Toolkit: Docker Swarm. Birmingham: Packt Publishing, 2017.

EXPLORE+
Para saber mais sobre os assuntos discutidos neste conteúdo, pesquise na internet e assista aos vídeos sobre:

Containers computacionais;

Kubernetes;

CUDA/NVIDIA;

DOCKER.

Amplie seus conhecimentos sobre Kubernetes no site edX da Linux Foundation, e sobre OpenShift, no site RedHat OpenShift.

CONTEUDISTA
Marcelo dos Santos Machado

 CURRÍCULO LATTES

Você também pode gostar