Você está na página 1de 73

INSTITUTO FEDERAL DE SANTA CATARINA

VALMIR DA CRUZ DE MEDEIROS

Implantação de uma aplicação distribuída baseada em HTTP/2 para


balanceamento de carga, serviços distribuídos e proxy reverso para
sistemas Web

São José - SC

agosto/2019
IMPLANTAÇÃO DE UMA APLICAÇÃO DISTRIBUÍDA BASEADA EM HTTP/2
PARA BALANCEAMENTO DE CARGA, SERVIÇOS DISTRIBUÍDOS E PROXY
REVERSO PARA SISTEMAS WEB

Trabalho de conclusão de curso apresentado à Coorde-


nadoria do Curso Superior de Tecnologia em Sistemas
de Telecomunicações do campus São José do Insti-
tuto Federal de Santa Catarina para a obtenção do
diploma de Tecnólogo em Sistemas de Telecomunica-
ções.

Orientador: Ederson Torresini, Me.

São José - SC

agosto/2019
Valmir da Cruz de Medeiros
Implantação de uma aplicação distribuída baseada em HTTP/2 para balanceamento de carga,
serviços distribuídos e proxy reverso para sistemas Web/ Valmir da Cruz de Medeiros. – São José -
SC, agosto/2019-
71 p. : il. (algumas color.) ; 30 cm.

Orientador: Ederson Torresini, Me.

Monografia (Graduação) – Instituto Federal de Santa Catarina – IFSC


Campus São José
Superior de Tecnologia em Sistemas de Telecomunicações, agosto/2019.
1. Front-end. 2. Hypertext Transfer Protocol (HTTP)/2. 3. Kubernetes. I. Ederson Torresini,
Me. II. Instituto Federal de Santa Catarina. III. Campus São José. IV. Implantação de uma aplicação
distribuída baseada em HTTP/2 para balanceamento de carga, serviços distribuídos e proxy reverso
para sistemas WEB.
VALMIR DA CRUZ DE MEDEIROS

IMPLANTAÇÃO DE UMA APLICAÇÃO DISTRIBUÍDA BASEADA EM HTTP/2


PARA BALANCEAMENTO DE CARGA, SERVIÇOS DISTRIBUÍDOS E PROXY
REVERSO PARA SISTEMAS WEB

Este trabalho foi julgado adequado para obtenção do título de Tecnólogo em Sistemas de
Telecomunicações, pelo Instituto Federal de Educação, Ciência e Tecnologia de Santa Catarina, e
aprovado na sua forma final pela comissão avaliadora abaixo indicada.

São José - SC, 9 de agosto de 2019

Ederson Torresini, Me.


Orientador
IFSC

Prof. Tiago Semprebom, Dr. Eng.


IFSC

Humberto José de Sousa


Analista de TI
IFSC
AGRADECIMENTOS

Agradeço de forma geral a todos aqueles que contribuíram para que eu pudesse chegar a este
momento, onde defendo meu trabalho de conclusão de curso afim de obter minha graduação.

Agradeço em especial à minha tia, Marli dos Santos Medeiros, que sempre me apoiou e por quem
tenho muito respeito e gratidão por tudo na vida. Agradeço aos meus amigos Jailson Manoel Venera e
Jefferson Antônio, amigos que conheço de muitos anos e que também me deram força e me apoiaram,
apoio esse de fora das salas de aula mas igualmente importante.

Meu muito obrigado também vai aos amigos que tive o prazer de conhecer durante o curso, amigos
com quem superei desafios, compartilhei conhecimentos e momentos gratificantes, em especial, obrigado
Alfredo Luiz, Giovana Lopes de Oliveira e Joseane Bortoli.

Em paralelo também agradeço ao meu orientador Ederson Torresini, pela paciência e dedicação
ao me auxiliar na conclusão deste trabalho, obrigado pelo conhecimento que compartilhou comigo durante
estes anos em todas as oportunidades.

Por fim, obrigado ao Instituto Federal de Santa Catarina - Câmpus São José (IFSC-SJ), a todos
os funcionários que contribuem para que o trabalho não pare, em especial ao corpo docente com quem
pude aprender muito durante os anos que aqui passei.
RESUMO
A demanda de aplicações voltadas para a Web no IFSC-SJ vem crescendo consideravelmente nos últimos
anos, sendo necessário adequar a estrutura dos servidores para atendê-la. Deste modo, este trabalho
propõe a implantação de uma infraestrutura de nuvem privada de aplicações Web em contêineres que
centralize o gerenciamento por meio de um front-end que recebe todas as requisições dos clientes e gerencia
a comunicação com os servidores das aplicações Web, atuando também como um balanceador de carga
que dimensiona estas requisições entre os servidores disponíveis. A aplicação é baseada no novo protocolo
HTTP/2, que promete superioridade no desempenho em relação aos seus antecessores e economia de
recursos no servidor, diminuindo a influência da latência da rede no acesso ao conteúdo, além de reduzir o
número de conexões Transmission Control Protocol (TCP) para os servidores Web.

Palavras-chave: HTTP/2, balanceamento de carga, Web, front-end.


ABSTRACT
Demand for Web applications in IFSC-SJ has been growing considerably in recent years, considering this,
the servers structure needs to be adjusted. Thus, this work proposes the deployment of a containerized web
application private cloud infrastructure that centralizes management through a front end that receives all
requests from clients and intermediate the communication with Web application servers, acting as a load
balancer among the available servers. The application will be based on the new HTTP/2 protocol, which
provides superior performance over its predecessors and server resource savings, reducing the influence of
network latency on content access, and reducing the number of TCP connections in the web servers.

Keywords: HTTP/2, load balancer, Web, front-end.


LISTA DE ILUSTRAÇÕES

Figura 1 – Modelo de referência TCP/Internet Protocol (IP) conforme Kurose e Ross (2010). . . 21
Figura 2 – Handshake TCP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Figura 3 – Servidor estabelecendo valor para rwnd. . . . . . . . . . . . . . . . . . . . . . . . . . 23
Figura 4 – Fluxo de dados sobre uma nova conexão TCP. . . . . . . . . . . . . . . . . . . . . . . 23
Figura 5 – Fluxo de dados sobre uma conexão TCP já estabelecida. . . . . . . . . . . . . . . . . . 24
Figura 6 – Controle e prevenção de congestionamentos. . . . . . . . . . . . . . . . . . . . . . . . . 25
Figura 7 – Janela de congestionamento do TCP. . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Figura 8 – Handshake TLS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Figura 9 – Handshahe Transport Layer Security (TLS) com extensão Application-Layer Protocol
Negotiation (ALPN). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Figura 10 – Requisição HTTP/1.1 utilizando pipelining. . . . . . . . . . . . . . . . . . . . . . . . . 31
Figura 11 – Conexões paralelas em uma requisição HTTP. . . . . . . . . . . . . . . . . . . . . . . 31
Figura 12 – Segmentação de domínio no navegador. . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Figura 13 – Estrutura do quadro de HTTP/2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Figura 14 – Estrutura de camadas com o quandro HTTP/2 . . . . . . . . . . . . . . . . . . . . . . 33
Figura 15 – Stream HTTP/2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Figura 16 – Streams HTTP/2 multiplexados em uma única conexão TCP. . . . . . . . . . . . . . . 34
Figura 17 – Streams de push enviados pelo servidor. . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Figura 18 – Exemplo de um balanceador de carga. . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Figura 19 – Exemplo de um proxy reverso. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Figura 20 – Diagrama de um cluster Kubernetes. . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Figura 21 – Sintaxe da interface de comando Kubectl. . . . . . . . . . . . . . . . . . . . . . . . . . 37
Figura 22 – Dashboard Kubernetes: alocação de recursos. . . . . . . . . . . . . . . . . . . . . . . . 38
Figura 23 – Dashboard Kubernetes: Deployment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Figura 24 – Diagrama de um Cluster Kubernetes com uma aplicação em contêiner. . . . . . . . . 39
Figura 25 – Ilustração de um Ingress Controller. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Figura 26 – Ingress Controller com as instruções do Ingress. . . . . . . . . . . . . . . . . . . . . . 44
Figura 27 – Interface adicionada à Virtual Machine (VM) do Minikube. . . . . . . . . . . . . . . . 48
Figura 28 – Uso de CPU de um Pod com balanceamento de carga. . . . . . . . . . . . . . . . . . . 50
Figura 29 – Aplicações em back-end. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Figura 30 – Operações da interface de comando Kubectl. . . . . . . . . . . . . . . . . . . . . . . . 62
LISTA DE CÓDIGOS

Código 2.1 – Requisição HTTP/0.9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27


Código 2.2 – Requisição HTTP/1.0. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Código 2.3 – Requisição HTTP/1.1 com conexão persistente. . . . . . . . . . . . . . . . . . . . . . 29
Código 3.1 – Arquivo ingress.yaml. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Código 3.2 – Requisição HTTP/2 utilizando uma conexão Internet Protocol Version 4 (IPv4). . . . 46
Código 3.3 – Requisição HTTP/2 utilizando uma conexão Internet Protocol Version 6 (IPv6). . . . 47
Código 3.4 – Interface da VM Minikube com IPv6. . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Código 3.5 – Requisição HTTP/1.1 para mediawiki.dominio.com.br. . . . . . . . . . . . . . . . . 49
Código C.1 – Arquivo nginx-ingress-controller.yaml. . . . . . . . . . . . . . . . . . . . . . . . 63
Código D.1 – Arquivo nginx-backend.yaml. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Código E.1 – Arquivo apache-backend.yaml. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Código F.1 – Arquivo mediawiki.yaml. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
LISTA DE ABREVIATURAS E SIGLAS

ALPN Application-Layer Protocol Negotiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

API Application Programming Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

CERN European Organization for Nuclear Research . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19

cwnd Congestion Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23

GCP Google Cloud Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

HTML HyperText Markup Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

HTTP Hypertext Transfer Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2

HTTPS Hyper Text Transfer Protocol Secure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

HTTP-WG Hypertext Transfer Protocol Working Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

IETF Internet Engineering Task Force . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

IFSC-SJ Instituto Federal de Santa Catarina - Câmpus São José . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

IP Internet Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

IPv4 Internet Protocol Version 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13

IPv6 Internet Protocol Version 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13

MSS Maximum Segment Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

NAT Network Address Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

NCSA National Center of Supercomputing Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19


RFC Request for Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24

RSA Rivest–Shamir–Adleman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

RTT Round-trip Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

rwnd Receiver Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

SPDY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

SSL Secure Socket Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

TLS Transport Layer Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

TCP Transmission Control Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

URI Uniform Resource Identifie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

URL Uniform Resource Locator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

VM Virtual Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

W3C World Wide Web Consortium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

WWW Word Wide Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19


SUMÁRIO

1 INTRODUÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.1 Objetivo Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.1.1 Objetivos específicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.2 Organização do texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2 FUNDAMENTAÇÃO TEÓRICA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1 Camada de Transporte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.1 Conexão TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.2 Controle de fluxo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.1.3 Controle de congestionamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.1.4 Partida lenta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.5 Recuperação rápida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.2 Criptografia e segurança Transport Layer Security (TLS) . . . . . . . . . . . . . . . 25
2.2.1 Handshake TLS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2.2 Mecanismos de troca de chave criptográficas . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2.3 Application-Layer Protocol Negotiation (ALPN) . . . . . . . . . . . . . . . . . . . . . . . 27
2.3 HTTP/0.9 e HTTP/1.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.4 HTTP/1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.4.1 Conexões Persistentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.4.2 Pipelining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.4.3 Conexões Paralelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.5 HTTP/2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.5.1 Quadro HTTP/2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.5.2 Streams e Multiplexação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.5.3 Server Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.6 Balanceamento de carga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.7 Proxy reverso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.8 Kubernetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.8.1 Cluster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.8.2 Kubectl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.8.3 Pod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.8.4 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.8.5 Ingress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.8.6 Ingress Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3 DESENVOLVIMENTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1 Cenários de testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.2 Aplicação Front-end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.2.1 Configurações do Ingress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2.2 Habilitando TLS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.2.3 Suporte a IPv4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.2.4 Suporte a IPv6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.2.5 HTTP/2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.2.6 HTTP/1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.2.7 Balanceamento de carga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.3 Back-end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.3.1 nginx-backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.3.2 apache-backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.3.3 mediawiki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

4 CONCLUSÕES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.1 Trabalhos futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

REFERÊNCIAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

ANEXOS 57

ANEXO A – LISTA DE INGRESS CONTROLLERS ADICIONAIS. . . . . . . . . . 59

ANEXO B – OPERAÇÕES DA INTERFACE DE COMANDO KUBECTL. . . . . . . 61

ANEXO C – CONFIGURAÇÕES DO CONTROLADOR DE INGRESSO . . . . . . 63

ANEXO D – CONFIGURAÇÕES DA APLICAÇÃO NGINX-BACKEND . . . . . . . 67

ANEXO E – CONFIGURAÇÕES DA APLICAÇÃO APACHE-BACKEND . . . . . . 69

ANEXO F – CONFIGURAÇÕES DA APLICAÇÃO MEDIAWIKI . . . . . . . . . . 71


19

1 INTRODUÇÃO

Em 1989, Tim Berners-Lee, na época engenheiro de software da European Organization for


Nuclear Research (CERN), apresentou uma proposta para o que se tornaria a Web, essa proposta visava
resolver um problema identificado por Berners-Lee que era a dificuldade que os cientistas encontravam
para compartilhar informações entre diferentes computadores com diferentes aplicativos (World Wide
Web Foundation, 2018). O documento apresentado tinha o título “Gestão da informação: Uma proposta”
(World Wide Web Foundation, 2018). Sua proposta foi rejeitada inicialmente, mas seu chefe permitiu que
o projeto fosse iniciado em setembro de 1990. A partir daí, Berners-Lee escreveu as três tecnologias que até
hoje são a base para a Web: HyperText Markup Language (HTML), Uniform Resource Identifie (URI) e
Hypertext Transfer Protocol (HTTP), além de criar o primeiro navegador de páginas Web, que foi chamado
de WorldWideWeb.app (World Wide Web Foundation, 2018).

Impulsionados pela criação do WorldWideWeb.app vieram uma nova geração de aplicativos


conhecida como Navegadores Web, dentre eles estava o NCSA Mosaic, criação de Marc L. Andreessen
e Eric J. Bina no National Center of Supercomputing Applications (NCSA) (Board of Trustees of the
University of Illinois, 2019). O NCSA Mosaic possuía interface gráfica e ícones, a inovação de apresentar
imagens na página da Web e suporte aos sistemas mais populares, PC e Mac, o que expandia seu alcance
(MIT, 2019). O NCSA Mosaic foi liberado gratuitamente para download, o que representou um sucesso,
fazendo com que o projeto logo fosse transferido para o setor privado por seus idealizadores, com a criação
da Mosaic Communications que mais tarde veio a se chamar Netscape (MIT, 2019).

A Web já era quase uma realidade, e agora precisava de padrões e diretrizes. No ano seguinte
a criação do Mosaic veio a fundação do World Wide Web Consortium (W3C), um consórcio formado
por empresas, instituições e especialistas convidados e que cria grupos de trabalho para desenvolverem
padrões para Web (W3C, 2019).

Os primeiros navegadores Web utilizaram como base a primeira versão do protocolo HTTP,
conhecido como HTTP/0.9 (BERNERS-LEE, 1991), um protocolo simples que funcionava sobre TCP
e tinha requisições e respostas simples: cada requisição representava uma conexão TCP ao servidor
(BERNERS-LEE, 1991). Em pouco tempo, isso não era mais suficiente para atender a demanda dos
usuários da Word Wide Web (WWW). Vieram então seus sucessores HTTP/1.0 e HTTP/1.1, onde este
último permaneceu operacional por 20 anos, mas a demanda da Web exigiu novamente uma atualização, e
a versão 1.1 já não era suficiente sem o emprego de várias ferramentas para melhorar seu desempenho.

O IFSC-SJ tem acompanhado a evolução da Web de um modo geral. De fato, muitas das aplicações
estão migrando para a Web: desde impressão até ferramentas de ensino, isso para beneficiar-se de vantagens
como uso de dispositivos estáticos e móveis, diferentes tamanhos de telas e resoluções; ou seja, na medida do
possível independência dos recursos do usuário final. Na prática, uma plataforma em comum e facilmente
encontrada nos dispositivos terminais.

Deste modo, será preciso otimizar o processamento e o acesso ao conteúdo, tanto no servidor
quanto no cliente, e por isso a proposta da utilização de um protocolo que propõe melhoria de desempenho
e economia de recursos na utilização das aplicações Web: o HTTP/2.
20 Capítulo 1. Introdução

1.1 Objetivo Geral

Este trabalho propõe a implantação de uma aplicação que utiliza o protocolo HTTP/2 e seus
novos recursos para melhorar o desempenho e a experiência com aplicações Web, atuais e futuras, do
IFSC-SJ, tanto para o cliente quanto para o servidor. A aplicação deverá funcionar como um front-end
para intermediar as conexões e sessões HTTP entre os usuários e os servidores da estrutura do IFSC-SJ.
Deverá também manter o suporte ao protocolo HTTP/1.1 para atender os servidores e clientes que ainda
utilizam esses em suas aplicações. O servidor front-end contará ainda com suporte na Camada de Rede
aos protocolos IPv4 e IPv6 tendo em vista que a versão 4 do IP ainda é muito utilizada, inclusive dentro
do câmpus.

1.1.1 Objetivos específicos

• Escolher uma aplicação que utilize contêiner e que contemple a proposta de front-end deste docu-
mento.

• Validar, através de testes unitários e aprestação dos resultados a viabilidade da proposta e se a


aplicação escolhida atende aos requisitos.

• A aplicação front-end deverá ter suporte aos itens a seguir:

– Balanceamento de carga.
– Gerenciamento centralizado.
– HTTP/1.1 e HTTP/2.
– Hyper Text Transfer Protocol Secure (HTTPS).
– IPv4 e IPv6.
– Proxy reverso.

1.2 Organização do texto

O texto está organizado em 4 capítulos. No Capítulo 1 há a Introdução e objetivos. No


Capítulo 2 temos a fundamentação teórica apresentando o protocolo HTTP/2 e suas melhorias, e um
comparativo com as versões anteriores. Já no Capítulo 3 temos o desenvolvimento, onde são apresentadas
as ferramentas e aplicações escolhidas para realizar os testes, os testes realizados, parâmetros e resultados.
E, por fim, no Capítulo 4 as conclusões do trabalho.
21

2 FUNDAMENTAÇÃO TEÓRICA

Neste capítulo são abordadas as tecnologias que dão base a esta proposta. Serão apresentados
conceitos sobre o Hypertext Transfer Protocol (HTTP), com um comparativo da evolução de suas versões
em aplicações Web e sobre balanceamento de carga, com foco nos protocolos que fazem parte do objeto de
estudo deste trabalho.

2.1 Camada de Transporte

A Camada de Transporte é responsável por encapsular as informações da aplicação e entregá-las


à camada inferior para que possam ser propagadas na Internet e vice-versa. Localizada entre as camadas
de Aplicação e de Internet do modelo de referência TCP/IP (Figura 1), a Camada de Transporte fornece
comunicação entre aplicações executando em diferentes hospedeiros (KUROSE; ROSS, 2010).

Figura 1 – Modelo de referência TCP/IP conforme Kurose e Ross (2010).

Fonte – Elaborado pelo autor.

O protocolo HTTP utiliza a Camada de Transporte para enviar e receber suas requisições e
informações. O padrão HTTP não prevê a obrigatoriedade de um protocolo da Camada de Transporte
específico (GRIGORIK, 2013), porém as conexões do HTTP trabalham basicamente sobre TCP devido a
sua garantia de entrega. O TCP faz o trabalho de garantir que os pacotes com as informações da aplicação
sejam entregues com segurança, tratando eventuais falhas de um canal não confiável, eliminando assim a
necessidade de implementações complexas de comunicação de rede nas aplicações (GRIGORIK, 2013).
Neste trabalho estamos considerando a versão 4 do TCP (POSTEL, 1981).

2.1.1 Conexão TCP

Uma conexão TCP é sempre inciada através de um three-way handshake (“aperto de mão de
três vias”) entre um cliente e um servidor (Figura 2). O cliente envia um pacote ao servidor com uma
mensagem SYN contendo um número de sequência gerado aleatoriamente ao servidor (x=rand()), que
aloca buffer em seu sistema para receber os dados da aplicação e o responde com uma mensagem SYN
ACK incrementando o valor de sequência recebido em (x+1) e encaminhando seu próprio identificador de
sequência, também gerado aleatoriamente (y=rand()), assim que o cliente recebe a mensagem enviada
pelo servidor, retorna um pacote com uma mensagem de confirmação ACK, incrementando o identificador
de sequência enviado pelo servidor (y+1) e enviando os dados da aplicação. Assim, a conexão TCP está
22 Capítulo 2. Fundamentação teórica

completa e tanto o servidor quanto o cliente estão prontos para trocar os dados recebidos da aplicação
(GRIGORIK, 2013).

É importante observar que o estabelecimento de uma conexão TCP tem um custo de tempo
diretamente ligado à latência da rede. No caso da Figura 2 a latência está estabelecida em 56 milissegundos,
então esse é o tempo Round-trip Time (RTT), desconsiderando o tempo de processamento do pacote no
servidor, que o handshake levará para ser completado. Como o protocolo HTTP trabalha sobre TCP, o
tempo que a aplicação demorará para receber a primeira informação enviada do servidor será, no melhor
caso, o dobro da latência da rede (2 * RTT ou 112 ms).

Figura 2 – Handshake TCP.

Fonte – Grigorik (2013).

2.1.2 Controle de fluxo

O mecanismo de controle de fluxo evita que o remetente, em uma conexão TCP sature o receptor
com um fluxo de dados que ele pode não conseguir processar, compatibiliza a velocidade que o remetente
transmite com a que o receptor consegue ler (KUROSE; ROSS, 2010).

O controle de fluxo funciona com a troca de informações entre o cliente e o servidor, ambos
anunciam seus valores de Receiver Window (rwnd) (“Janela de Recebimento”) de acordo com o
tamanho do buffer de recepção TCP de cada um, e os comunicam através de pacotes com mensagens ACK
durante a conexão. A Figura 3 ilustra o envio de um valor para rwnd pelo servidor para que o cliente
ajuste seu fluxo de dados.

2.1.3 Controle de congestionamento

O controle de congestionamento do TCP é utilizado para dimensionar a largura de banda da


rede entre o cliente e o servidor, no início ou durante a conexão. O objetivo é evitar o descarte de pacotes
por gargalos em equipamentos da rede e a necessidade de retransmissão e armazenamento dos pacotes
subsequentes em buffer até que os perdidos sejam recuperados pelo TCP, já que o controle de fluxo
(subseção 2.1.2) somente evita que o remetente sature o receptor, mas nada faz quanto ao possível gargalo
que poderia haver na rede nas camadas por baixo da conexão TCP. O congestionamento é detectado
quando através do esgotamento de um temporizador ou recebimento de quatro reconhecimentos para dado
segmento TCP (um ACK original e três duplicados) o remetente percebe a perda de um datagrama entre
remetente e destinatário (KUROSE; ROSS, 2014).
2.1. Camada de Transporte 23

Figura 3 – Servidor estabelecendo valor para rwnd.

Fonte – Grigorik (2013).

2.1.4 Partida lenta


Quando uma conexão TCP é estabelecida o protocolo não sabe qual a capacidade da rede, sua
única referência são as informações de rwnd trocadas entre cliente e servidor, mas o TCP não pode
utilizar esta referência para iniciar um fluxo de transmissão de dados, pois se o valor do fluxo do receptor
for superior à capacidade da rede, algum equipamento terá em algum momento seu buffer saturado e
pacotes serão descartados. Então o TCP negocia uma variável chamada Congestion Window (cwnd)
(“Janela de Congestionamento”). Grigorik (2013) define cwnd como: Limite do lado do remetente sobre a
quantidade de fluxo de dados que ele pode manter antes de receber uma confirmação ACK do cliente.

Figura 4 – Fluxo de dados sobre uma nova conexão TCP.

Fonte – Grigorik (2013).

Originalmente o valor inicial de cwnd foi definido como uma vez o valor do Maximum Segment
24 Capítulo 2. Fundamentação teórica

Size (MSS) (1 * MSS), em 1999 a Request for Comments (RFC) 2581 (ALLMAN; PAXSON; STEVENS,
1999) atualizou este valor para quatro vezes o valor de MSS (4 * MSS) e a RFC 6928 (CHU et al., 2013),
em 2013, propôs o tamanho inicial para cwnd como dez vezes o valor do MSS (10 * MSS = 14600 bytes),
onde todo o fluxo de dados será iniciado com esse valor e o remetente incrementará cwnd em uma vez
o MSS a cada pacote ACK de confirmação recebido do cliente, dessa forma o TCP consegue aumentar o
fluxo de dados de acordo com a confirmação de que os pacotes estão sendo entregues ao destinatário
(GRIGORIK, 2013). Mesmo que a largura de banda entre cliente e servidor seja muito superior ao valor
inicial da janela, está taxa somente será alcançada após idas e voltas suficientes para alcançar o máximo
valor de throughput da rede (GRIGORIK, 2013). O limite para cwnd sempre será o congestionamento da
rede ou o valor de rwnd.

A Figura 4 ilustra uma requisição HTTP sobre uma conexão TCP. Pode-se verificar o fluxo de
dados sendo aumentado de acordo com as confirmações de recebimento por parte do servidor e o tempo
necessário até que os dados solicitados sejam completamente transferidos ao cliente. Comparando agora
com a Figura 5, que ilustra a mesma requisição sobre a mesma conexão TCP já estabelecida e com o valor
de cwnd em 65535 bytes é possível perceber a redução de tempo.

Figura 5 – Fluxo de dados sobre uma conexão TCP já estabelecida.

Fonte – Grigorik (2013).

Na Figura 6 podemos ver um gráfico com os valores de cwnd começando com dez vezes o valor
de MSS e crescendo exponencialmente de acordo com a confirmação do recebimento das informações por
parte do servidor. O gráfico também ilustra a queda do valor de cwnd quando há uma perda de pacotes,
interrompendo o crescimento exponencial, o que faz com que o multiplicador retorne ao último valor onde
obteve êxito (40 * MSS) e o crescimento exponencial recomece dese valor.

2.1.5 Recuperação rápida

Quando um evento de perda é detectado no remetente através do recebimento de três ACKs


duplicados ao invés do esgotamento temporal o comportamento do TCP não precisa ser tão drástico, para
este tipo de evento é utilizado o mecanismo de recuperação rápida. A recuperação rápida modifica o ponto
de reinício da transmissão e evita o reinício da partida lenta (KUROSE; ROSS, 2014).

Uma versão antiga do TCP conhecida como TCP Tahoe reduzia diretamente o valor de cwnd
para 1 * MSS fazendo com que se inicia-se a fase de partida lenta após um evento de perda, sendo por
esgotamento ou por recebimento de ACKs duplicados. Uma versão mais recente do protocolo, conhecida
2.2. Criptografia e segurança Transport Layer Security (TLS) 25

Figura 6 – Controle e prevenção de congestionamentos.

Fonte – Grigorik (2013).

como TCP Reno incluiu a recuperação rápida. Com a recuperação rápida, ao detectar um evento de perda
por triplo ACK duplicado o TCP reduz o valor da variável de estado do limiar de partida lenta (ssthresh)
para 0,5 * cwnd e ajusta o valor de cwnd para 6 * MSS (o valor de ssthresh).

A Figura 7 apresenta um comparativo de ambas as versões do protocolo TCP, na imagem um


evento de perda por ACKs é detectado na rodada 8, a partir dai é evidenciada a diferença entre as versões.
A TCP Tahoe reduz o valor de cwnd para 1 * MSS reiniciando o processo de partida lenta com o aumento
exponencial da janela de congestionamento. Já o TCP Reno reduz o valor de cwnd para 6 * MSS ficando
igual ou acima do valor de ssthresh e evitando o reinicio da partida lenta.

Figura 7 – Janela de congestionamento do TCP.

Fonte – Junior (2017).

2.2 Criptografia e segurança Transport Layer Security (TLS)

O precursor do TLS foi o protocolo Secure Socket Layer (SSL), que foi desenvolvido para
habilitar segurança em transações de comércio eletrônico na Web, transações que precisavam proteger os
dados pessoais dos clientes e ter garantia de autenticação para uma transação segura. O protocolo foi
implementado na Camada de Aplicação imediatamente acima do TCP, permitindo que protocolos acima,
26 Capítulo 2. Fundamentação teórica

como o HTTP, permaneçam inalterados enquanto fornecem segurança na comunicação através da rede
(GRIGORIK, 2013).

Inicialmente, com o SSL, houve um esforço do Internet Engineering Task Force (IETF) para
documentá-lo, o que culminou na RFC 6101 (FREIER; KARLTON; KOCHER, 2011) para fins históricos.
Ao longo do tempo, diversas falhas críticas de segurança foram encontradas no SSL, mesmo em sua última
versão (3.0).

Sobre o TLS, sua primeira versão, a 1.0, foi publicada na RFC 2246 (DIERKS; ALLEN, 1999).
Apesar de o TLS ter surgido do SSL, os protocolos não são interoperáveis. Para este documento, será
considerado apenas o protocolo TLS.

2.2.1 Handshake TLS


Uma sessão TLS é iniciada através de um processo conhecido como handshake TLS, que a exemplo
da conexão TCP exige a troca de informações entre cliente e servidor. Este é o processo que define o
estabelecimento de um canal confiável entre cliente e servidor para troca de informações criptografadas.
O processo de um handshake TLS e seus passos sobre uma conexão TCP estão ilustrados na Figura 8.
O cliente incia a negociação com a mensagem ClientHello com a versão do protocolo TLS e uma lista
de CipherSuites (algoritmos de criptografia) suportados, além de outras opções do TLS que desejar
utilizar (GRIGORIK, 2013). O servidor responde com uma mensagem ServerHello escolhendo a versão
do TLS, decidindo um CipherSuite da lista fornecida pelo cliente e anexando seu certificado (GRIGORIK,
2013). Em seguida o cliente inicia a troca de chaves Rivest–Shamir–Adleman (RSA) (HOUSLEY, 1999)
e Diffie-Hellman (RESCORLA, 1999). O servidor recebe, processa e checa os parâmetros de troca de
chaves enviados pelo cliente e retorna um Finished (GRIGORIK, 2013).

Figura 8 – Handshake TLS.

Fonte – Friedl et al. (2014).

Hoje o uso de TLS para conexões HTTP seguras, HTTPS, se tornou essencial, mas o processo
de handshake TLS implica negociações com pedidos e respostas que aumentam os valores de RTT. O
protocolo permite o uso de extensões como o TLS False Start e abbreviated handshake, que quando
combinados podem oferecer um handshake TLS de 1-RTT (GRIGORIK, 2013).

2.2.2 Mecanismos de troca de chave criptográficas


O protocolo TLS utiliza RSA (HOUSLEY, 1999) e Diffie-Hellman (RESCORLA, 1999) como
mecanismos de troca chaves para o handshake TLS. O mecanismo RSA é o mais utilizado nas implementações
TLS, porém tem uma fraqueza crítica: o mesmo par de chaves pública-privada é usado tanto para autenticar
2.3. HTTP/0.9 e HTTP/1.0 27

o servidor quanto para criptografar a chave de sessão simétrica enviada para o servidor. Como resultado,
se um atacante ganhar acesso à chave privada do servidor e ouvir a troca, então eles podem decifrar a
sessão inteira. E mesmo que um invasor não tenha acesso à chave privada no momento, ele ainda pode
gravar a sessão criptografada e desencriptá-la mais tarde, assim que obter a chave privada (GRIGORIK,
2013).

Já o mecanismo Diffie-Hellman não permite que a chave simétrica compartilhada deixe o cliente
ou o servidor, o segredo não é compartilhado durante o handshake TLS, dificultando assim a ação de
invasores. Segundo (GRIGORIK, 2013), razões comerciais e históricas são responsáveis pela escolha do
RSA ao invés da chave Diffie-Hellman em aplicações TLS.

2.2.3 Application-Layer Protocol Negotiation (ALPN)


Conforme (FRIEDL et al., 2014) o ALPN é uma extensão do protocolo TLS e foi desenvolvido
para atender as negociações do protocolo HTTP/2, porém o ALPN pode atender a outros protocolos
arbitrários da Camada de Aplicação.

Figura 9 – Handshahe TLS com extensão ALPN.

Fonte – Friedl et al. (2014).

O ALPN possibilita que a aplicação utilize o handshake TLS para realizar as negociações do
protocolo da Camada de Aplicação, evitando assim a adesão de mais RTTs à conexão. A Figura 9
exemplifica o handshake TLS com a inclusão da extensão ALPN. O cliente adiciona ALPN extension
& list of protocols na mensagem ClientHello contendo uma lista de protocolos de aplicativos
suportados, o servidor verifica a lista e retorna um ALPN extension & selected protocol indicando
o protocolo selecionado como parte da mensagem ServerHello (GRIGORIK, 2013). Após concluído
o handshake TLS o cliente e o servidor já podem trocar mensagem através do protocolo negociado
(GRIGORIK, 2013).

2.3 HTTP/0.9 e HTTP/1.0

Conforme apresentado no Capítulo 1, o HTTP/0.9 foi a primeira versão do protocolo HTTP


sendo um protocolo simples que continha um único método GET (Código 2.1) e recebia como resposta
somente dados em HTML. Era necessária a abertura de uma conexão TCP para cada requisição seguida
de resposta (ver subseção 2.1.1).

Código 2.1 – Requisição HTTP/0.9.


1 GET /about/
2
28 Capítulo 2. Fundamentação teórica

3 (hypertext response)
4 (connection closed)

Fonte – Grigorik (2013).

O aperfeiçoamento da versão do HTTP/0.9 levou à publicação da RFC 1945 (BERNERS-LEE;


FIELDING; NIELSEN, 1996) e a versão HTTP/1.0 do protocolo. Esta RFC não define um padrão da
Internet, tinha caráter informativo e o objetivo de documentar as melhores práticas e padrões para o
HTTP que surgiram na época.

O HTTP/1.0 também trabalha instanciando uma conexão TCP para cada requisição, que também
era encerrada logo após a resposta do servidor. Esta versão do protocolo introduziu novas possibilidades
ao HTTP e a Web, como a opção de requisitar imagens, não mais ficando restrito ao HTML e novos
cabeçalhos. A versão 1.0 trouxe ideias que são utilizadas até hoje: cabeçalhos, códigos de resposta,
redirecionamentos, erros, pedidos condicionais, codificação de conteúdo (compressão) e mais métodos de
requisição (LUDIN; GARZA, 2017). O Código 2.2 exemplifica uma requisição HTTP/1.0 com algumas das
novidades do protocolo, como o código de resposta HTTP 200 OK (linha 9) que indica que uma requisição
foi bem sucedida.

Código 2.2 – Requisição HTTP/1.0.


5 GET /rfc/rfc1945.txt HTTP/1.0
6 User-Agent: CERN-LineMode/2.15 libwww/2.17b3
7 Accept: */*
8
9 HTTP/1.0 200 OK
10 Content-Type: text/plain
11 Content-Length: 137582
12 Expires: Thu, 01 Dec 1997 16:00:00 GMT
13 Last-Modified: Wed, 1 May 1996 12:45:26 GMT
14 Server: Apache 0.84
15
16 (plain-text response)
17 (connection closed)

Fonte – Grigorik (2013).

A versão 1.0 trouxe muitos avanços ao HTTP, porém ainda tinha uma forma ineficiente de
administrar as conexões TCP, que sempre eram fechadas após as respostas do servidor. Todas as vezes
que uma requisição era realizada era necessário um novo processo de hanshake TCP e adição de RTT à
conexão (abordamos as conexões na seção 2.1). A versão 1.1 (seção 2.4) propôs ferramentas para resolver
este problema.

2.4 HTTP/1.1

Diversas melhorias foram incorporadas ao protocolo original, como por exemplo o uso de conexões
persistentes, culminando a revisão da HTTP na versão oficial 1.1.

2.4.1 Conexões Persistentes


A melhoria das conexões persistentes foi adicionada ao protocolo HTTP na versão 1.1 com o
proposito de melhorar o gerenciamento das conexões TCP e garantir mais eficiência das conexões já
estabelecidas. Antes das conexões persistentes, uma conexão TCP separada era aberta para cada Uniform
Resource Locator (URL), aumentando a carga em servidores HTTP (FIELDING et al., 1999).
2.4. HTTP/1.1 29

A primeira documentação do HTTP/1.1, a RFC 2068 (FIELDING et al., 1997), trouxe as


especificações de uma ferramenta chamada Keep-Alive, que logo ficou obsoleta pela publicação da
RFC 2616. O HTTP/1.1 eliminou o suporte para conexões Keep-Alive, substituindo-as por um design
melhorado chamado conexões persistentes. Os objetivos das conexões persistentes são os mesmos que os
das conexões Keep-Alive, mas os mecanismos se comportam melhor (GOURLEY et al., 2002).

As conexões persistentes mantêm as conexões TCP abertas ao invés de encerrá-las após a resposta
de uma requisição HTTP ao servidor, permitindo que outras requisições sejam enviadas na mesma conexão.
Com essa possibilidade, requisições seguintes não precisam enfrentar um novo processo de handshake TCP
e as penalidades de um processo de partida lenta (abordamos o handshake e a partida lenta do TCP na
seção 2.1).

O HTTP/1.1 assume que todas as conexões são persistentes, a não ser que se indique o contrário, e
para encerrar uma conexão persistente é preciso informar no cabeçalho a intenção de encerrar a conexão. Na
Código 2.3 podemos ver um exemplo de requisição HTTP/1.1 utilizando o recurso de conexão persistente e,
nas linhas 29 e 61 respectivamente, as informações de cabeçalho indicando a persistência e o encerramento
da conexão.

Código 2.3 – Requisição HTTP/1.1 com conexão persistente.


18 GET /index.html HTTP/1.1
19 Host: website.org
20 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
21 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
22 Accept-Encoding: gzip,deflate,sdch
23 Accept-Language: en-US,en;q=0.8
24 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
25 Cookie: __qca=P0-800083390... (snip)
26
27 HTTP/1.1 200 OK
28 Server: nginx/1.0.11
29 Connection: keep-alive
30 Content-Type: text/html; charset=utf-8
31 Via: HTTP/1.1 GWA
32 Date: Wed, 25 Jul 2012 20:23:35 GMT
33 Expires: Wed, 25 Jul 2012 20:23:35 GMT
34 Cache-Control: max-age=0, no-cache
35 Transfer-Encoding: chunked
36
37 100
38 <!doctype html>
39 (snip)
40
41 100
42 (snip)
43
44 0
45
46 GET /favicon.ico HTTP/1.1
47 Host: www.website.org
48 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
49 Accept: */*
50 Referer: http://website.org/
51 Connection: close
52 Accept-Encoding: gzip,deflate,sdch
53 Accept-Language: en-US,en;q=0.8
54 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
30 Capítulo 2. Fundamentação teórica

55 Cookie: __qca=P0-800083390... (snip)


56
57 HTTP/1.1 200 OK
58 Server: nginx/1.0.11
59 Content-Type: image/x-icon
60 Content-Length: 3638
61 Connection: close
62 Last-Modified: Thu, 19 Jul 2012 17:51:44 GMT
63 Cache-Control: max-age=315360000
64 Accept-Ranges: bytes
65 Via: HTTP/1.1 GWA
66 Date: Sat, 21 Jul 2012 21:35:22 GMT
67 Expires: Thu, 31 Dec 2037 23:55:55 GMT
68 Etag: W/PSA-GAu26oXbDi
69
70 (icon data)
71 (connection closed)

Fonte – Grigorik (2013).

2.4.2 Pipelining
Uma outra funcionalidade introduzida no HTTP/1.1 foi o pipelining, um recurso que otimiza o
desempenho do HTTP sobre conexões persistentes. As requisições HTTP precisavam de uma resposta
do servidor para cada solicitação enviada, o cliente realiza a requisição e o servidor responde, e após, o
cliente na mesma conexão poderia encaminhar uma nova requisição.

O pipelining propôs que o cliente enviasse mais de uma requisição por vez, e aguardasse o servidor
processá-las e respondê-las, porém essas respostas precisavam chegar na ordem em que foram enviadas.
Mesmo que uma requisição secundária fosse processada primeiro no servidor, está deveria ficar armazenada
em buffer até que a primária fosse respondida.

A Figura 10 apresenta o processo de requisição de dois métodos simultâneos utilizando o pipelining,


podemos observar que o processo de uma ida e volta foi subtraído reduzindo o tempo de RTT total.

Apesar do recurso melhorar o desempenho, esta otimização apresenta muitas implicações sutis e
ilustra uma limitação importante dos protocolos HTTP/1.x: serialização rigorosa das respostas. HTTP/1.x
não permite que dados de múltiplas respostas sejam intercalados (multiplexados) na mesma conexão,
forçando cada resposta a ser devolvida completamente antes que os bytes para a próxima possam ser
transferidos. Devido a estas e outras complicações, e a falta de orientação no padrão HTTP/1.1 para esses
casos, a adoção de pipeline HTTP permaneceu muito limitada, apesar de muitos benefícios. Hoje, alguns
navegadores suportam pipelining, geralmente como uma opção de configuração avançada, mas a maioria a
dos navegadores desabilitou (GRIGORIK, 2013).

2.4.3 Conexões Paralelas


HTTP/1.1 trouxe também o uso de múltiplas conexões simultâneas, que melhoraram a utilização
dos recursos de banda permitindo que as requisições fossem encaminhadas em paralelo através de múltiplos
fluxos TCP, na maioria dos navegadores atuais até seis por host. As conexões em paralelo possibilitaram
que recursos de uma mesma página, por exemplo, fossem requisitados simultaneamente (Figura 11)
reduzindo os atrasos causados pela espera das respostas para cada requisição.

O número de seis conexões simultâneas foi definido como um meio termo para não extrapolar as
despesas gerais com recursos que navegadores e servidores precisariam para atender múltiplos fluxos TCP
2.5. HTTP/2 31

Figura 10 – Requisição HTTP/1.1 utilizando pipelining.

Fonte – Grigorik (2013).

Figura 11 – Conexões paralelas em uma requisição HTTP.

Fonte – GOURLEY et al. (2002)

simultâneos. Mas para algumas aplicações Web isso não era suficiente, o que fez com que se começasse a
utilizar um recurso chamado sharding. O sharding de domínio (Figura 12) consistia basicamente em dividir
o conteúdo em diversos subdomínio com hostnames diferentes, como o navegador limita o número de
conexões simultâneas por nome de host, o número de conexões utilizado para cada aplicação era ampliado.

Na prática, o sharding de domínio é frequentemente usado em excesso, resultando em


dezenas de fluxos TCP subutilizados, muitos deles nunca escapando da partida lenta
do TCP e, no pior dos casos, diminuindo a experiência do usuário. Além disso, os
custos são ainda maiores quando o HTTPS deve ser usado, devido às passagens de
rede adicionais realizadas pelo handshake TLS. (GRIGORIK, 2013).

2.5 HTTP/2

Antes de iniciar a discussão sobre o HTTP/2 é necessário citar o SPDY, um protocolo criado
em 2009 por Mike Belshe e Roberto Peon, do Google, e que tinha como objetivo reduzir os impactos da
latência no carregamento de páginas Web explorando algumas das limitações do HTTP/1.1. O SPDY
estabeleceu as bases para o HTTP/2 e foi responsável por provar algumas de suas características principais,
como multiplexação, enquadramento e compactação de cabeçalho, entre outros (LUDIN; GARZA, 2017).
32 Capítulo 2. Fundamentação teórica

Figura 12 – Segmentação de domínio no navegador.

Fonte – Elaborado pelo autor.

A proposta do HTTP/2 começou com o grupo de trabalho Hypertext Transfer Protocol Working
Group (HTTP-WG) que iniciou um esforço para aproveitar os resultados alcançados pelo protocolo
proprietário (SPDY) e lançar um padrão oficial que seria a versão 2 do HTTP. Então em maio de 2015
foi lançada a RFC 7540 (BELSHE; PEON; THOMSON, 2015) que regulamentou oficialmente o protocolo
HTTP/2. Esta especificação descreve uma expressão otimizada da semântica do (HTTP), conhecido como
HTTP versão 2 (HTTP/2), que permite um uso mais eficiente de recursos de rede e uma percepção
reduzida de latência ao introduzir a compressão de campo de cabeçalho e permitir trocas múltiplas e
simultâneas na mesma conexão.

O HTTP/2 não altera conceitos da aplicação como métodos, códigos de status, URIs e campos
de cabeçalhos. O HTTP/2 altera como os dados são formatados e transportados (GRIGORIK, 2013).
Falaremos sobre as principais implementações de HTTP/2 nas próximas seções.

2.5.1 Quadro HTTP/2

O HTTP/2 utiliza um quadro para trocar informações da aplicação entre o cliente e o servidor, a
(Figura 13) ilustra o formato do quadro com seus campos e com o tamanho de cada um deles em bits.

Figura 13 – Estrutura do quadro de HTTP/2.

Fonte – Belshe, Peon e Thomson (2015)

Todas as mensagens HTTP são codificadas em um formato binário, fragmentadas em quadros


de cabeçalhos e dados e encapsuladas em um quadro binário (Figura 14), o que facilita a leitura por
máquinas e permite que o protocolo multiplexe as mensagens em uma mesma conexão TCP (veremos
2.5. HTTP/2 33

multiplexação na subseção 2.5.2).

Figura 14 – Estrutura de camadas com o quandro HTTP/2

Fonte – Grigorik (2013).

2.5.2 Streams e Multiplexação


Segundo (BELSHE; PEON; THOMSON, 2015, tradução nossa) “Um ‘stream’ é uma sequência
bidirecional independente de quadros trocados entre o cliente e o servidor dentro de uma conexão HTTP/2 ”.

A troca de mensagens sob o enquadramento binário de HTTP/2 acontece sobre streams (fluxos).
Cada vez que um cliente deseja realizar uma requisição é aberto um fluxo, que é identificado através do
campo Stream Identifier no quadro de HTTP/2. Este campo existe devido a capacidade de HTTP/2
abrir múltiplos fluxos e enviá-los na mesma conexão TCP através de multiplexação. A Figura 15 ilustra o
cliente enviando uma requisição ao servidor que em seguida o responde em vários quadros, o enquadramento
binário (visto na subseção 2.5.1) dividiu a resposta em um quandro com as informações de cabeçalho
(HEADERS) e fragmentou os dados reais da solicitação em cabeçalhos de dados (DATA).

Figura 15 – Stream HTTP/2.

Fonte – Ludin e Garza (2017).

Através do enquadramento binário a implementação de HTTP/2 também trouxe a possibilidade


de multiplexar os fluxos de dados e definir prioridade, de acordo com necessidade da aplicação, para cada
um deles. A multiplexação de streams acabou com a necessidade do HTTP abrir múltiplas conexões TCP
simultâneas, agora ao invés enfrentar todo o processo do handshake TCP mais processo de partida lenta, e
no caso de uma conexão HTTPS também o handshake TLS, a aplicação cria um novo fluxo, explorando os
34 Capítulo 2. Fundamentação teórica

ganhos de utilizar uma conexão já aberta (abordamos conexões TCP e handshake TLS na subseção 2.1.1
e na subseção 2.2.1). A Figura 16 ilustra os vários fluxos de HTTP/2 em uma mesma conexão.

A maioria das transferências HTTP são curtas e rápidas, enquanto o TCP é otimizado para
transferências de dados em longo prazo. Ao reutilizar a mesma conexão HTTP/2 é capaz de fazer um
uso mais eficiente de cada conexão TCP, e também reduzir significativamente a sobrecarga do protocolo.
Além disso, o uso de menos conexões reduz a memória e o processamento ao longo do caminho de conexão,
o que reduz os custos operacionais e melhora a utilização e a capacidade da rede (GRIGORIK, 2013).

Figura 16 – Streams HTTP/2 multiplexados em uma única conexão TCP.

Fonte – Grigorik (2013).

2.5.3 Server Push

A funcionalidade server push, introduzida em HTTP/2, permite ao servidor, de forma pró-ativa,


enviar um objeto ao cache do cliente antes mesmo de ser solicitado. Quando o servidor vai encaminhar
uma resposta a uma requisição do cliente, ele pode gerar um fluxo adicional e enviar um objeto que já se
espere que o cliente irá solicitar, assim quando o cliente requisitar esse conteúdo, o mesmo já estará em
cache.

Figura 17 – Streams de push enviados pelo servidor.

Fonte – Grigorik (2013).

A Figura 17 apresenta o servidor encaminhando streams com resposta a requisição de um cliente


e dois streams extras (4 e 2) com dados a serem armazenados em cache. Os fluxos iniciados pelo servidor
utilizam um quadro chamado PUSH_PROMISE, que sinaliza a intenção do servidor de enviar estes objetos
ao cliente.
2.6. Balanceamento de carga 35

2.6 Balanceamento de carga

Segundo (SHARMA; SINGH; SHARMA, 2008, tradução nossa) “O balanceamento de carga é o


processo de melhorar o desempenho de um sistema paralelo ou distribuído através da redistribuição de
carga entre os processadores”.

O balanceamento de carga trata de forma eficiente à distribuição do tráfego de entrada para um


grupo de servidores back-end, ou comumente conhecidos como server farm (fazenda de servidores) como
ilustra a Figura 18. É responsável por gerenciar as conexões e requisições vindas de clientes de forma a
maximizar a velocidade e garantir que nenhum servidor fique sobrecarregado.

Um balanceador de carga eficiente também permite a adição e remoção de servidores dimensio-


nando e redirecionando o tráfego a medida que existem mais ou menos servidores disponíveis para atender
a demanda de requisições (NGINX, Inc., 2017). Alguns dos benefícios de utilizar um balanceador de carga
são: redundância, escalabilidade, otimização de recursos e segurança (SARANYA; MAHESWARI, 2015).

Figura 18 – Exemplo de um balanceador de carga.

Fonte – Elaborado pelo autor.

O balanceador de carga utiliza algoritmos de balanceamento para distribuição do tráfego entre os


servidores, segundo (SARANYA; MAHESWARI, 2015) os algoritmos de balanceamento de carga estão
divididos em dois tipos: estáticos e dinâmicos.

• Algoritmos estáticos: Não consideram o estado atual do sistema, distribuem o tráfego de forma
uniforme entre os servidores disponíveis.

• Algoritmos dinâmicos: Pesquisam os servidores com a menor demanda para equilibrar o tráfego,
consideram o estado atual do sistema. Acabam gerando um tráfego adicional na rede pela constante
comunicação para monitorar o estado dos servidores.

Alguns dos algoritmos mais utilizados em computação em nuvem, segundo Kashyap e Viradiya
(2014), são: Round-Robin, Opportunistic, Min-Min, Max-Min, The two phase scheduling, Honeybee
Foraging, Biased Random Sampling e Active Clustering.
36 Capítulo 2. Fundamentação teórica

2.7 Proxy reverso

O proxy reverso atua como um front-end ficando na borda da rede e recebendo as conexões dos
clientes e encaminhando-as a servidores da back-end que possam atendê-las. O proxy reverso pode também
receber todas as requisições direcionadas a uma server farm através de um único endereço de IP, o que
gera segurança eliminando o contato direto com os servidores reais das aplicações e permite concentrar
recursos como gerência da rede e armazenamento de cache (NGINX, Inc., 2017).

Um servidor proxy pode prover recursos para o administrador da rede controlar os acessos
dos usuários aos servidores internos, os usuários acessam somente as URLs associadas a este servidor.
O administrador configura regras no proxy para que as requisições HTTP vindas da Internet sejam
encaminhadas ao servidor interno adequado (IBM Knowledge Center, 2019).

A Figura 19 ilustra o funcionamento de um proxy reverso. Os clientes requisitam uma página Web
que está localizada dentro dos servidores de aplicação, atrás servidor proxy. Cada cliente deseja acessar
um conteúdo diferente, por isso cada um requisita uma URL distinta, o servidor então é responsável por
associar cada URL com a aplicação correta e encaminhar as requisições ao respectivo servidor na back-end.

Figura 19 – Exemplo de um proxy reverso.

Fonte – Elaborado pelo autor.

2.8 Kubernetes

O Kubernetes é um software de código aberto utilizado para automatizar o gerenciamento de


aplicações em contêineres. Seus serviços, suporte e ferramenta estão amplamente disponíveis (The Linux
Fundation, 2019).

2.8.1 Cluster
O Kubernetes gerencia um cluster formado de um ou mais computadores para operarem como
uma só unidade. As aplicações são implantadas em contêineres dentro de um cluster sem vínculo com
máquinas individuais (The Linux Foundation, 2019c). A Figura 20 ilustra um cluster Kubernetes básico.

• Mestre: O Mestre (“Master”) é responsável por gerenciar o cluster, atualizar os aplicativos, manter
o estado das aplicações e executar as alterações solicitadas pelo usuário. É o Mestre que decide o
2.8. Kubernetes 37


Figura 20 – Diagrama de um cluster Kubernetes.

Fonte – The Linux Foundation (2019c).

que é executado dentro de todos os nós. Ao adicionar uma aplicação no Kubernetes o usuário envia
comandos ao Mestre para iniciar os contêineres do aplicativo (The Linux Foundation, 2019c).

• Nós: Um nó é uma VM ou máquina física onde ficarão os contêineres com as aplicações dentro do
cluster. Os nós se comunicam com o mestre através da Application Programming Interface (API)
(“Interface de programação de aplicativos”) do Kubernetes (The Linux Fundation, 2019).

2.8.2 Kubectl

O Kubectl é uma interface de linha de comando do Kubernetes para executar comandos em


clusters, utilizamos esta ferramenta para implantar aplicativos, verificar logs e gerenciar os recursos de um
cluster. Esta interação é realizada através da API do Kubernetes (The Linux Fundation, 2019).

A Figura 21 exemplifica a sintaxe de um comando simples da ferramenta. No Apêndice B podemos


encontrar uma lista com as operações que a interface suporta.

Figura 21 – Sintaxe da interface de comando Kubectl.

Fonte – The Linux Fundation (2019)

O Kubernetes também possui um Dashboard (“Painel de Controle”) que conta com uma interface
de administração Web (Figura 22 e Figura 23). Através do Dashboard também é possível interagir com a
API do Kubernetes para gerenciar os clusters.
38 Capítulo 2. Fundamentação teórica

Figura 22 – Dashboard Kubernetes: alocação de recursos.

Fonte – The Linux Fundation (2019).

Figura 23 – Dashboard Kubernetes: Deployment.

Fonte – The Linux Fundation (2019).

2.8.3 Pod

De acordo com a documentação de conceitos do (Google Cloud, 2019b) os pods são os menores e
mais básicos objetos implantáveis no Kubernetes. Um pod representa uma única instância de um processo
em execução no seu cluster.

Os Pods executam os contêineres das aplicações, podendo haver mais de um contêiner sendo
executado pelo mesmo Pod. Quando isso acontece, os contêineres funcionam como uma só entidade
compartilhando os recursos daquele Pod. Entre os recursos que são compartilhados estão os de rede e
armazenamento (The Linux Fundation, 2019).
2.8. Kubernetes 39

• Rede: Os Pods possuem endereços de rede exclusivos. Os contêineres de um mesmo Pod comparti-
lham este endereço assim como as portas de rede (Google Cloud, 2019b).

• Armazenamento: É possível criar volumes de armazenamento e compartilhá-los entre os contêineres


de uma Pod (Google Cloud, 2019b).

Os Pods são executados dentro dos Nós em um cluster, após criado permanece no Nó até que
seja excluído, removido ou até que o Nó falhe.

2.8.4 Deployment

Os Deployments (“Implantações”) representam um conjunto de vários Pods. Eles executam


réplicas das aplicações e substituem automaticamente todas as instâncias que falham ou não respondem
(Google Cloud, 2019a). O Deployment instrui o Kubernetes em como criar as instâncias de uma aplicação,
quantas réplicas criar e em como atualizá-las via ReplicaSet. Após criadas as instâncias, o Kubernetes
ReplicaSet é responsável por monitorá-las, para que se um nó, onde uma das instâncias estiver, for excluído
ou desativado uma nova instância seja criada em um outro nó (The Linux Fundation, 2019).

Figura 24 – Diagrama de um Cluster Kubernetes com uma aplicação em contêiner.

Fonte – The Linux Fundation (2019).

Ao criar um Deployment é preciso especificar a imagem do contêiner e o número de réplicas da


aplicação a ser criada. A Figura 24 ilustra um cluster já com um Deployment realizado. Um contêiner
com a aplicação já está rodando dentro de um dos nós do cluster.

2.8.5 Ingress

O Kubernetes possui um recurso chamado Ingress (“Entrada”). O recurso Ingress oferece:


balanceamento de carga, permite expor as rotas HTTP e HTTPS de fora de um cluster Kubernetes para
os contêineres com as aplicações, serviços URLs que sejam acessíveis externamente, terminar conexões
SSL e TLS e hospedagem virtual baseada em nome (The Linux Foundation, 2019a).
40 Capítulo 2. Fundamentação teórica

O recurso Ingress recebe os parâmetros de configurações para instruir o Ingress Controller em


como deve operar, através do Ingress definimos como o tráfego HTTP e HTTPS será roteado para alcançar
os serviços dentro do cluster, para as aplicações em back-end.

Existe mais de um tipo de Ingress, abaixo são citados e ilustrados os três tipos declarados na
documentação de (The Linux Foundation, 2019a).

• Single Service Ingress (Tabela 1): Expõe um único serviço, o tráfego HTTP é roteado para um
único serviço no back-end.

Host IP Serviço:Porta
dominio.com.br/servico1 192.0.2.100 servico1:80

Tabela 1 – Single Service Ingress.

Fonte – Elaborado pelo autor.

• Simple fanout (Tabela 2): O tráfego de um único IP é roteado para mais de um serviço baseando-se
no URI HTTP solicitado.

Host IP Serviço:Porta
dominio.com.br/servico1 192.0.2.100 servico1:80
dominio.com.br/servico2 192.0.2.100 servico2:80
dominio.com.br/servico3 192.0.2.100 servico3:80

Tabela 2 – Simple fanout.

Fonte – Elaborado pelo autor.

• Name based virtual hosting (Tabela 3): Neste tipo de Ingress o tráfego HTTP é roteado através
de nomes de hosts distintos utilizando o mesmo endereço de IP.

Host IP Serviço:Porta
servico1.dominio.com.br 192.0.2.100 servico1:80
servico2.dominio.com.br 192.0.2.100 servico2:80
servico3.dominio.com.br 192.0.2.100 servico3:80

Tabela 3 – Name based virtual hosting.

Fonte – Elaborado pelo autor.

2.8.6 Ingress Controller


Um Ingress Controller (“Controlador de Ingresso”) é responsável por cumprir as funcionalidades
do Ingress, em nosso cenário é a aplicação que será responsável por realizar o balanceamento de carga
e operar como front-end e proxy reverso recebendo as conexões externas e roteando o tráfego HTTP e
HTTPS para dentro do cluster, a Figura 25 ilustra o comportamento de um Ingress Controller atuando
como front-end e roteando as requisições HTTP dos usuários para as aplicações internas do cluster.

É possível encontrar uma lista de aplicações Ingress Controller (Anexo A), porém atualmente
o Kubernetes somente suporta e mantém como um projeto os controladores GCE e NGINX (The Linux
Foundation, 2019b).
2.8. Kubernetes 41

Figura 25 – Ilustração de um Ingress Controller.

Fonte – NGINX, Inc. (2018).


43

3 DESENVOLVIMENTO

Dentre as ferramentas utilizadas no mercado foi escolhido o controlador de ingresso kubernetes


Ingress Nginx como aplicação para o cenário proposto. O kubernetes Ingress Nginx será utilizado
como ferramenta para atuar como front-end, proxy reverso e balanceador de carga.

O NGINX Ingress Controller foi escolhido por atender aos requisitos da proposta deste trabalho,
ter grande escala de utilização e principalmente por possuir suporte e manutenção pelo orquestrador de
contêineres Kubernetes, que atualmente somente mantém suporte para mais uma aplicação.

3.1 Cenários de testes

Para testar os recursos propostos pela aplicação implantada foi necessário a criação de um cenário
para simular um ambiente de produção. Neste cenário foram realizados os testes para validar o suporte da
solução para os recursos listados abaixo.

• Suporte a HTTP/1.1 e HTTP/2.

• IPv4 e IPv6.

• HTTPS.

• Balanceamento de carga.

• Proxy reverso.

Para criar os cenários de testes, com um cluster Kubernetes, foi utilizado o Google Cloud
Platform (GCP)1 , que é uma plataforma de computação em nuvem do Google onde é possível alocar
recursos de maquinas virtuais e endereços de IP para desenvolvimento de aplicações. O GCP é uma
solução paga, mas atualmente o Google oferece um crédito de U$$ 300 válidos por até 12 meses para
testar a plataforma. O crédito é consumido de acordo com os recursos que o usuário utilizar da plataforma.

Neste trabalho o GCP foi utilizado para criar um cluster Kubernetes2 com dois nós. Neste cluster
foram criadas três aplicações back-end mais o Ingress Controller como front-end para realização dos testes.

Também foi utilizado o Minikube, que é uma ferramenta que possibilita montar um cluster de
Kubernetes com um único nó dentro de uma VM (“Maquina Virtual”) (The Linux Fundation, 2019).

A versão do Minikube utilizada para a criação do cenário e realização dos testes foi a: 0.22.2.
A VM do Minikube foi virtualizada através do software VirtualBox na versão 5.1.38, instalado sobre
um sistema operacional Ubuntu 16.04 e Kubernetes versão 1.7.

3.2 Aplicação Front-end

Nesta seção são abordadas as principais configurações para o funcionamento do NGINX Ingress
Controller como front-end. São apresentados também os testes realizados para demostrar que a aplicação
cumpre as funcionalidades operacionais propostas neste trabalho. Abaixo são apresentados os principais
1 Disponível em https://cloud.google.com
2 A versão do cluster Kubernetes utilizada foi a 1.14.6-gke.1
44 Capítulo 3. Desenvolvimento

parâmetros de configuração da aplicação front-end. No Anexo C é possível encontrar o código com as


configurações completas.

• Versão da API: apps/v1.

• Nome da aplicação: nginx-ingress-controller.

• Número de réplicas: 1.

• Imagem: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0.

• Portas expostas da aplicação: 80 e 443.

3.2.1 Configurações do Ingress


Para o cenário criado neste trabalho foi utilizado o Ingress do tipo Name Based Virtual Hosting
(“Hospedagem virtual baseada em nome”). Este tipo permite utilizar vários nomes de hosts (“hospedeiros”)
com um único endereço de IP e rotear o tráfego HTTP para diversos serviços em suas respectivas portas. A
Figura 26 ilustra o comportamento do NGINX Ingress Controller com as instruções do recurso Ingress.

Figura 26 – Ingress Controller com as instruções do Ingress.

Fonte – Elaborado pelo autor.

O Código 3.1 apresenta as configurações do recurso Ingress. Para este cenário as configurações
foram realizadas em um único arquivo ingress.yaml, mas pode-se criar um recurso separado com
instruções especificas para cada aplicação.

• apiVersion: Versão da API do Kubernetes.

• kind: Indica que é uma configuração do tipo Ingress.

• annotations: recebe instruções para personalizar os parâmetros do Ingress Controller para configu-
rações diferentes das padrões da imagem utilizada.
3.2. Aplicação Front-end 45

• tls: configura os certificados para os respectivos hosts.

• rules: aqui estão as regras do balanceamento de carga, de acordo com a URL requisitada o tráfego
HTTP será roteado para um dos serviços da back-end na porta configurada.

Código 3.1 – Arquivo ingress.yaml.


72 apiVersion: extensions/v1beta1
73 kind: Ingress
74 metadata:
75 name: ingress
76 annotations:
77 ingress.kubernetes.io/rewrite-target: / # URI de destino em que o tráfego deve ser
redirecionado
78 ingress.kubernetes.io/ssl-redirect: "true" # Define o valor de redirecionamentos (301) de
forma global para HTTPS se o servidor tiver um certificado TLS.
79 spec:
80 tls:
81 - hosts:
82 - nginx-backend.dominio.com.br
83 secretName: tls-nginx-backend-ipv6
84 - hosts:
85 - apache-backend.dominio.com.br
86 secretName: tls-apache-backend
87 - hosts:
88 - mediawiki.dominio.com.br
89 secretName: tls-mediawiki
90 rules:
91 # Requisições para "nginx-backend.dominio.com.br/" serão redirecionadas para a aplicação "nginx-
backend" na porta 80.
92 - host: nginx-backend.dominio.com.br
93 http:
94 paths:
95 - path: /*
96 backend:
97 serviceName: nginx-backend
98 servicePort: 80
99 - host: apache-backend.dominio.com.br
100 http:
101 paths:
102 - path: /*
103 backend:
104 serviceName: apache-backend
105 servicePort: 80
106 - host: mediawiki.dominio.com.br
107 http:
108 paths:
109 - path: /*
110 backend:
111 serviceName: mediawiki
112 servicePort: 80

Fonte – Elaborado pelo autor.

Uma documentação completa dos recursos de personalização do Ingress Controller, como: suporte
a Websocket, alterações na versão do HTTP utilizada na comunicação entre controlador e back-end, limite
do número de conexões simultâneas por IP e por IP a cada segundo, entre muitas outras que o controlador
permite (Kubernetes Community, 2019).
46 Capítulo 3. Desenvolvimento

3.2.2 Habilitando TLS


A suporte a TLS no controlador de ingresso NGINX já vem habilitado por padrão se o servidor
tiver um certificado TLS definido, como apresentado nas linhas 83, 86 e 89, por exemplo, do Código 3.1.
Para os testes desta proposta foram gerados certificados autoassinados através do aplicativo OpenSSL
v1.0.2g (OpenSSL Software Foundation, 2018).

3.2.3 Suporte a IPv4


O front-end deverá possuir suporte para receber requisições através de conexões IPv4 e IPv6. A
aplicação front-end receberá todas as requisições externas e intermediará a comunicação com as aplicações
que estarão em back-end e acessíveis somente dentro do cluster Kubernetes.

Os resultados obtidos e apresentados no Código 3.2 mostram uma requisição HTTP/2 utilizando
o método GET para uma das aplicações encontradas no back-end, um servidor Apache.

A linha 116 do Código 3.2 mostra o endereço remoto juntamente com a porta TCP para onde foi
enviada a requisição HTTP com HTTPS através do protocolo IPv4.

Nas linhas 133 e 134 respectivamente, podemos observar a confirmação da resposta e a identificação
do servidor que respondeu a requisição. A informação requisitada, a página Web, teve como origem o
servidor encontrado no back-end, dentro do cluster, redirecionada através das configurações do Ingress,
mas a negociação foi realizada com a aplicação front-end, o Ingress Controller.

Para o teste apresentado no Código 3.2 foi utilizada a ferramenta Programador Web do navegador
de internet Firefox v68.0 (linha 122).

Código 3.2 – Requisição HTTP/2 utilizando uma conexão IPv4.


113 General
114 Request URL:https://apache-backend.dominio.com.br/
115 Request method:GET
116 Remote address:192.168.99.100:443
117 Status code: 200 OK
118 Version:HTTP/2.0
119
120 Request Headers
121 Host: apache-backend.dominio.com.br
122 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
123 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
124 Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
125 Accept-Encoding: gzip, deflate, br
126 DNT: 1
127 Connection: keep-alive
128 Upgrade-Insecure-Requests: 1
129 Pragma: no-cache
130 Cache-Control: no-cache
131
132 Response Headers
133 HTTP/2.0 200 OK
134 server: nginx/1.13.4
135 date: Thu, 01 Aug 2019 02:42:47 GMT
136 content-type: text/html
137 content-length: 45
138 last-modified: Mon, 11 Jun 2007 18:53:14 GMT
139 etag: "2d-432a5e4a73a80"
140 accept-ranges: bytes
141 strict-transport-security: max-age=15724800; includeSubDomains;
3.2. Aplicação Front-end 47

142 X-Firefox-Spdy: h2

Fonte – Elaborado pelo autor.

3.2.4 Suporte a IPv6


Nesta seção temos os resultados da requisição HTTP/2 com HTTPS agora utilizando uma conexão
com o protocolo IPv6, o Código 3.3 apresenta os cabeçalhos da requisição. Na linha 146 podemos observar
o endereço remoto já no formato atual do protocolo IP.

Para o teste apresentado no Código 3.3 foi utilizada a ferramenta Programador Web do navegador
de internet Firefox v68.0 (linha 152).

Código 3.3 – Requisição HTTP/2 utilizando uma conexão IPv6.


143 General
144 Request URL:https://mediawiki.dominio.com.br/
145 Request method:GET
146 Remote address:[2001:db8::100]:443
147 Status code: 200 OK
148 Version:HTTP/2.0
149
150 Request Headers
151 Host: mediawiki.dominio.com.br
152 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
153 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
154 Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
155 Accept-Encoding: gzip, deflate, br
156 DNT: 1
157 Connection: keep-alive
158 Cookie: mw_installer_session=fd40fd87ba893bfff4b2c65ab35261ea
159 Upgrade-Insecure-Requests: 1
160 Pragma: no-cache
161 Cache-Control: no-cache
162 TE: Trailers
163
164 Response Headers
165 HTTP/2.0 200 OK
166 server: nginx/1.13.4
167 date: Thu, 01 Aug 2019 02:55:26 GMT
168 content-type: text/html; charset=UTF-8
169 content-length: 409
170 x-powered-by: PHP/7.2.20
171 x-content-type-options: nosniff
172 expires: Thu, 19 Nov 1981 08:52:00 GMT
173 cache-control: no-store, no-cache, must-revalidate
174 pragma: no-cache
175 vary: Accept-Encoding
176 content-encoding: gzip
177 strict-transport-security: max-age=15724800; includeSubDomains;
178 X-Firefox-Spdy: h2

Fonte – Elaborado pelo autor.

Como a ferramenta Minikube cria uma rede local que fica atrás de um Network Address Translation
(NAT) (“Tradução do Endereço da Rede”) e a alteração desta interface ocasionou a falha de comunicação
da máquina real com a interface de linha de comando Kubectl, foi preciso adicionar uma terceira interface
48 Capítulo 3. Desenvolvimento

na VM da aplicação, além das duas criadas pela própria ferramenta, e configurá-la em bridge para
comunicação com a rede local do notebook utilizado para realização dos testes (Figura 27).

Figura 27 – Interface adicionada à VM do Minikube.

Fonte – Elaborado pelo autor.

Na interface criada manualmente, que foi identificada na VM do Minikube como eth2, foi fixado
manualmente o endereço IPv6 “2001:db8::100/64” para os testes com a versão 6 do protocolo IP.

O Código 3.4 apresenta o comando “ip” (linha 179), utilizado para adicionar o endereços IPv6 à
interface “eth2”, e o comando “ipconfig” (linha 180) para visualização das informações da interface.

Código 3.4 – Interface da VM Minikube com IPv6.


179 $ sudo ip -6 addr add 2001:db8::100/64 dev eth2
180 $ ifconfig eth2
181 eth2 Link encap:Ethernet HWaddr 08:00:27:04:75:DF
182 inet addr:192.168.90.200 Bcast:192.168.90.255 Mask:255.255.255.0
183 inet6 addr: fe80::a00:27ff:fe04:75df/64 Scope:Link
184 inet6 addr: 2001:db8::100/64 Scope:Global
185 inet6 addr: 2001:db8::a00:27ff:fe04:75df/64 Scope:Global
186 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
187 RX packets:5443 errors:0 dropped:0 overruns:0 frame:0
188 TX packets:1911 errors:0 dropped:0 overruns:0 carrier:0
189 collisions:0 txqueuelen:1000
190 RX bytes:463866 (452.9 KiB) TX bytes:448512 (438.0 KiB)
191 Interrupt:17 Base address:0xd060

Fonte – Elaborado pelo autor.

3.2.5 HTTP/2

No Código 3.2 realizamos um GET para testar a comunicação de uma conexão IPv4. No mesmo
código, na linha 133, podemos verificar que o servidor front-end respondeu à requisição validando a
comunicação através do protocolo HTTP/2. O mesmo aconteceu com o protocolo IPv6 no Código 3.3
(linha 165).
3.2. Aplicação Front-end 49

3.2.6 HTTP/1.1
É apresentado abaixo, no Código 3.5, uma requisição HTTP/1.1 (linha 214) para a URL3 . Para
a realização desste teste foi utilizada a aplicação curl4 . Foram utilizados os parâmetros -v (verbose)
para detalhar o cabeçalho da requisição e -K (insecure ) para permitir conexões sem certificado SSL.

Código 3.5 – Requisição HTTP/1.1 para mediawiki.dominio.com.br.


192 $ curl https://mediawiki.dominio.com.br -v --http1.1 -k
193
194 * Rebuilt URL to: https://mediawiki.dominio.com.br/
195 * Trying 2001:db8::100...
196 * Connected to mediawiki.dominio.com.br (2001:db8::100) port 443 (#0)
197 * found 148 certificates in /etc/ssl/certs/ca-certificates.crt
198 * found 597 certificates in /etc/ssl/certs
199 * ALPN, offering http/1.1
200 * SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
201 * server certificate verification SKIPPED
202 * server certificate status verification SKIPPED
203 * common name: mediawiki.dominio.com.br (matched)
204 * server certificate expiration date OK
205 * server certificate activation date OK
206 * certificate public key: RSA
207 * certificate version: #3
208 * subject: CN=mediawiki.dominio.com.br,O=192.168.99.100
209 * start date: Wed, 31 Jul 2019 04:59:41 GMT
210 * expire date: Thu, 30 Jul 2020 04:59:41 GMT
211 * issuer: CN=mediawiki.dominio.com.br,O=192.168.99.100
212 * compression: NULL
213 * ALPN, server accepted to use http/1.1
214 > GET / HTTP/1.1
215 > Host: mediawiki.dominio.com.br
216 > User-Agent: curl/7.47.0
217 > Accept: */*
218 >
219 < HTTP/1.1 200 OK
220 < Server: nginx/1.13.4
221 < Date: Fri, 02 Aug 2019 12:24:06 GMT
222 < Content-Type: text/html; charset=UTF-8
223 < Content-Length: 599
224 < Connection: keep-alive
225 < X-Powered-By: PHP/7.2.20
226 < X-Content-Type-Options: nosniff
227 < Set-Cookie: mw_installer_session=31d94cb099d26d08332b3202f6d608cb; path=/
228 < Expires: Thu, 19 Nov 1981 08:52:00 GMT
229 < Cache-Control: no-store, no-cache, must-revalidate
230 < Pragma: no-cache
231 < Vary: Accept-Encoding
232 < Strict-Transport-Security: max-age=15724800; includeSubDomains;

Fonte – Elaborado pelo autor.

3.2.7 Balanceamento de carga


O balanceamento de carga foi testado gerando sobre uma das aplicações do back-end várias
requisições HTTP para que o processamento das réplicas da aplicação subissem e assim fosse perceptível
3 https://mediawiki.dominio.com
4 v7.47.0
50 Capítulo 3. Desenvolvimento

a diferença de consumo de recursos quando o número de réplicas fosse reduzido a uma.

A Figura 28 apresenta um gráfico dividido em duas partes, 1 e 2. A parte 1 apresenta o consumo


de CPU de uma das réplicas de uma aplicação da back-end enquanto existia outra réplica (totalizando
duas) balanceando o consumo das requisições. A parte 2 mostra o aumento de consumo após a segunda
réplica ser removida do sistema, é possível perceber que a réplica restante assume toda a carga da que foi
removida.

Figura 28 – Uso de CPU de um Pod com balanceamento de carga.

Fonte – Dashboard do GCP.

Para gerar dos requisições foi criado um Shell script que através da aplicação curl realizava
requisições para a URL desejada. O script foi executado varias vezes simultaneamente até gerar um trafego
que download de requisições de aproximadamente 1 Mbps durante o período de monitoramento do gráfico
apresentado na Figura 28. O código do script está exposto a abaixo.

#!/bin/bash
echo “curl repetido 100 vezes”
for i in {100..0};
do
curl https://35.247.226.228/nginx-backend -kv
done

Fonte – Elaborado pelo autor.

3.3 Back-end

Para simular o cenário da proposta foram colocadas três aplicações em back-end Figura 29. Na
sequência serão apresentadas as configurações e especificações de cada aplicação.

A comunicação para os serviços no back-end acontece através de conexões com o protocolo IPv4
e por padrão através de HTTP/1.1.

3.3.1 nginx-backend
A primeira aplicação ilustrada pela Figura 29 é um servidor Web NGINX. As principais configurações
são descritas abaixo, o código completo com as configurações foi adicionado ao Anexo D.

• Aplicação: Servidor Web.


3.3. Back-end 51

Figura 29 – Aplicações em back-end.

Fonte – Elaborado pelo autor.

• Nome da aplicação: nginx-backend.

• Imagem: nginx.

• Porta do contêiner: 80.

– Protocolo: TCP.

3.3.2 apache-backend
A segunda aplicação também é um servidor Web muito conhecido, o Apache. O código completo
com as configurações foi adicionado ao Anexo E.

• Aplicação: Servidor Web.

• Nome da aplicação: apache-backend.

• Imagem: httpd:alpine.

• Porta do contêiner: 80 para HTTP e 443 para HTTPS.

– Protocolo: TCP.

3.3.3 mediawiki
As principais configurações são descritas abaixo, o código completo com as configurações foi
adicionado ao Anexo F.

• Aplicação: Servidor Web Mediawiki.

• Nome da aplicação: mediawiki.

• Imagem: mediawiki:stable.
52 Capítulo 3. Desenvolvimento

• Porta do contêiner: 80.

– Protocolo: TCP.
53

4 CONCLUSÕES

Este trabalho propôs a implantação de uma aplicação que utilizasse o protocolo HTTP/2 e seus
novos recursos para melhorar o desempenho e a experiência com aplicações Web do IFSC-SJ. A aplicação
deveria utilizar contêiner e funcionar como um front-end intermediando as conexões entre os usuários e os
servidores da estrutura do câmpus.

A principal aplicação estudada neste trabalho foi o controlador de ingresso NGINX Ingress
Controller, foram realizados testes e configurados parâmetros para que o controlador operasse de forma
a atender aos requisitos da proposta. A aplicação com suas configurações, em sua maioria padrão, já
atendeu a maioria dos requisitos: balanceamento de carga, suporte a IPv4 e IPv6, suporte a HTTP/1.1
para aplicações legadas, HTTP/2 para melhorar o acesso ao conteúdo e o processamento e gerenciamento
centralizado. Isso é justificado pois o cenário proposto é um cenário onde a aplicação é projetada para
atuar. As dificuldade ficaram sobre como configurar o Ingress para realizar o balanceamento de carga,
roteamento HTTP e o proxy reverso.

Dentro da proposta da aplicação com gerência centralizada, é também desejado o suporte a cache
no front-end, que até a conclusão deste trabalho o NGINX Ingress Controller não possuía suporte na
versão estável (testada e homologada). A alternativa seria o desenvolvimento manual, faria com que
possivelmente passasse pelos testes automatizados do orquestrador Kubernetes. Porém, devido ao tempo
hábil para a conclusão do trabalho optou-se por propor como sugestão de trabalho futuro a implementação
desta funcionalidade.

No desenvolvimento, os cenários para a realização dos testes foram criados sobre as plataformas
GCP e Minikube. Ambos mostraram-se de fácil instalação e operação, porém como a ampla documentação
é para máquinas reais o fato de o Minikube criar uma rede local com NAT acabou trazendo dificuldades
ao adaptar os tutoriais no que se refere aos redirecionamentos de porta para os serviços no cluster.
Foram criadas aplicações Web em back-end (nginx-backend, apache-backend e mediawiki) e uma
aplicação front-end (Nginx Ingress Controller) para representarem a estrutura da proposta. Em
seguida, configurou-se o Ingress com as instruções do proxy reverso para que a aplicação front-end receba
as requisições dos usuários e às encaminhe para o serviço correspondente de cada URL. Em todas as
aplicações foram configuradas a quantidade de réplicas para o balanceamento de carga, selecionadas as
imagens dos contêineres e configuradas as portas de cada serviço.

Os primeiros testes realizados foram para o suporte aos protocolos IPv4 e IPv6. A aplicação
front-end funcionou com exito para ambos os testes, porém nos testes deste trabalho as conexões IPv6
ficaram entre os usuários e o front-end, as conexões internas do cluster utilizaram a versão 4 do protocolo.
Sugeriu-se como trabalho futuro uma implementação com suporte total a IPv6 dentro e fora do cluster.

Testou-se também o suporte aos protocolos HTTP/1.1 e HTTP/2 com HTTPs, todos com exito.
Aqui é possível salientar a possibilidade de exigir conexões criptografadas a todas as requisições recebidas
pelo front-end mesmo que a aplicação em back-end não ofereça suporte.

Por ultimo, validamos o balanceamento de carga monitorando o processamento de um dos Pods


de uma das aplicações em back-end enquanto recebia requisições HTTP. O gráfico apresentou o nível de
processamento subindo após a remoção da segunda replica que dividia a carga de processamento com a
que estava sendo monitorada.

A aplicação não foi testada no IFSC-SJ, pois não havia estrutura na nuvem de teste no momento
54 Capítulo 4. Conclusões

do desenvolvimento. Os testes para evidenciar o real ganho de desempenho de HTTP/2 também exigiriam
uma aplicação Web de grande porte (um site completo), o que também optou-se por não realizar devido
ao tempo disponível para a conclusão do trabalho.

Como maior contribuição da proposta desta implementação fica a possibilidade de utilizar um


front-end com um único endereço de IP, o que permite a possibilidade de utilizar um certificado unificado
para todas as URLs com o mesmo domínio do câmpus1 economizando recursos financeiros, já que as
certificações geram custo.

4.1 Trabalhos futuros

Como trabalhos futuros, primeiramente a validação em uma topologia semelhante a apresentada


neste documento com suporte total ao protocolo IPv6 nos servidores e Ingress Controllers.

Além disso, é interessante o estudo de tráfego para construir uma solução de cache associada ao
front-end para as diversas aplicações de back-end, uma vez que estas possuem suas próprias especificidades,
como por exemplo tipos de arquivos e seus respectivos tempos de vida, entre outros.

1 *.sj.ifsc.edu.br
55

REFERÊNCIAS

ALLMAN, M.; PAXSON, V.; STEVENS, W. TCP Congestion Control. [S.l.], 1999. Citado na página 24.

BELSHE, M.; PEON, R.; THOMSON, M. Hypertext Transfer Protocol Version 2 (HTTP/2). [S.l.], 2015.
<http://www.rfc-editor.org/rfc/rfc7540.txt>. Disponível em: <http://www.rfc-editor.org/rfc/rfc7540.
txt>. Citado 2 vezes nas páginas 32 e 33.

BERNERS-LEE, T. The original http as defined in 1991. In: . [s.n.], 1991. Disponível em:
<https://www.w3.org/Protocols/HTTP/AsImplemented.html>. Acesso em: 21 de nov. 2017. Citado na
página 19.

BERNERS-LEE, T.; FIELDING, R. T.; NIELSEN, H. F. Hypertext Transfer Protocol –


HTTP/1.0. [S.l.], 1996. <http://www.rfc-editor.org/rfc/rfc1945.txt>. Disponível em: <http:
//www.rfc-editor.org/rfc/rfc1945.txt>. Citado na página 28.

Board of Trustees of the University of Illinois. Ncsa mosaic. In: . ILLINOIS - NATIONAL CENTER FOR
SUPERCOMPUTING APPLICATIONS, 2019. Disponível em: <http://www.ncsa.illinois.edu/enabling/
mosaic>. Acesso em: 12 de ago. 2019. Citado na página 19.

CHU, J. et al. Increasing TCP’s Initial Window. [S.l.], 2013. <http://www.rfc-editor.org/rfc/rfc6928.txt>.


Disponível em: <http://www.rfc-editor.org/rfc/rfc6928.txt>. Citado na página 24.

DIERKS, T.; ALLEN, C. The TLS Protocol Version 1.0. [S.l.], 1999. <http://www.rfc-editor.org/rfc/
rfc2246.txt>. Disponível em: <http://www.rfc-editor.org/rfc/rfc2246.txt>. Citado na página 26.

FIELDING, R. et al. Hypertext Transfer Protocol – HTTP/1.1. [S.l.], 1997. Citado na página 29.

FIELDING, R. T. et al. Hypertext Transfer Protocol – HTTP/1.1. [S.l.], 1999. <http:


//www.rfc-editor.org/rfc/rfc2616.txt>. Disponível em: <http://www.rfc-editor.org/rfc/rfc2616.txt>.
Citado na página 28.

FREIER, A.; KARLTON, P.; KOCHER, P. The Secure Sockets Layer (SSL) Protocol
Version 3.0. [S.l.], 2011. <http://www.rfc-editor.org/rfc/rfc6101.txt>. Disponível em: <http:
//www.rfc-editor.org/rfc/rfc6101.txt>. Citado na página 26.

FRIEDL, S. et al. Application-Layer Protocol Negotiation Extension. [S.l.], 2014. Disponível em:
<https://tools.ietf.org/html/rfc7301>. Acesso em: 21 de nov. 2017. Citado 2 vezes nas páginas 26 e 27.

Google Cloud. Implantação. In: . Google Cloud, 2019. Disponível em: <https://cloud.google.com/
kubernetes-engine/docs/concepts/deployment>. Citado na página 39.

Google Cloud. Pod. In: . Google Cloud, 2019. Disponível em: <https://cloud.google.com/
kubernetes-engine/docs/concepts/pod>. Citado 2 vezes nas páginas 38 e 39.

GOURLEY, D. et al. HTTP: The Definitive Guide. [S.l.]: O’Reilly Media, 2002. Citado 2 vezes nas
páginas 29 e 31.

GRIGORIK, I. High-Performance Browser Networking. O’Reilly Media, 2013. 383 p. Disponível em:
<https://hpbn.co/>. Acesso em: 28 de nov. 2017. Citado 13 vezes nas páginas 21, 22, 23, 24, 25, 26, 27,
28, 30, 31, 32, 33 e 34.

HOUSLEY, R. Cryptographic Message Syntax. [S.l.], 1999. Citado na página 26.

IBM Knowledge Center. O que É um servidor proxy reverso? In: . IBM Knowledge Center, 2019.
Disponível em: <https://www.ibm.com/support/knowledgecenter/pt-br/SSKTXQ_9.0.0/admin/config/
st_adm_port_rvprxy_overview_c.html>. Citado na página 36.

JUNIOR, B. Redes de computadores. In: . [S.l.]: Universidade Federal de Mato Grosso do Sul, 2017.
Citado na página 25.
56 Referências

KASHYAP, D.; VIRADIYA, J. A survey of various load balancing algorithms in cloud computing.
INTERNATIONAL JOURNAL OF SCIENTIFIC TECHNOLOGY RESEARCH, v. 2, n. 11, 2014.
Citado na página 35.
Kubernetes Community. Nginx ingress controller. In: . MKDocs, 2019. Disponível em:
<https://kubernetes.github.io/ingress-nginx/>. Citado na página 45.
KUROSE, J. F.; ROSS, K. W. Redes de Computadores e a Internet: Uma abordagem top-down. 5. ed.
[S.l.]: Pearson, 2010. Citado 3 vezes nas páginas 11, 21 e 22.
KUROSE, J. F.; ROSS, K. W. Redes de Computadores e a Internet: Uma abordagem top-down. 6. ed.
[S.l.]: Pearson, 2014. Citado 2 vezes nas páginas 22 e 24.
LUDIN, S.; GARZA, J. Learning HTTP/2 : A practical guide for beginners. [S.l.]: O’Reilly Media, 2017.
156 p. Citado 3 vezes nas páginas 28, 31 e 33.
MIT. Internet browser technology. In: . Lemelson-MIT Program, 2019. Disponível em:
<https://lemelson.mit.edu/resources/marc-andreeson-and-eric-bina>. Acesso em: 12 de ago. 2019.
Citado na página 19.
NGINX, Inc. What is a reverse proxy vs. load balancer? In: . NGINX, INC., 2017. Disponível em:
<https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/>. Citado 2 vezes nas
páginas 35 e 36.
NGINX, Inc. Nginx ingress controller for kubernetes. In: . NGINX, INC., 2018. Disponível em:
<https://www.nginx.com/products/nginx/kubernetes-ingress-controller#resources>. Citado na página
41.
OpenSSL Software Foundation. Openssl cryptography and ssl/tls toolkit. In: . OpenSSL Software
Foundation, 2018. Disponível em: <https://www.openssl.org/>. Citado na página 46.
POSTEL, J. Transmission Control Protocol. [S.l.], 1981. <http://www.rfc-editor.org/rfc/rfc793.txt>.
Disponível em: <http://www.rfc-editor.org/rfc/rfc793.txt>. Citado na página 21.
RESCORLA, E. Diffie-Hellman Key Agreement Method. [S.l.], 1999. <http://www.rfc-editor.org/rfc/
rfc2631.txt>. Disponível em: <http://www.rfc-editor.org/rfc/rfc2631.txt>. Citado na página 26.
SARANYA, D.; MAHESWARI, L. S. Load balancing algorithms in cloud computing: A review.
International Journal of Advanced Research in Computer Science and Software Engineering, v. 5, n. 7,
2015. Citado na página 35.
SHARMA, S.; SINGH, S.; SHARMA, M. Performance analysis of load balancing algorithms. World
Academy of Science, Engineering and Technology, v. 2, n. 2, 2008. Citado na página 35.
The Linux Foundation. Ingress. In: . The Linux Fundation, 2019. Disponível em: <https:
//kubernetes.io/docs/concepts/services-networking/ingress/>. Citado 2 vezes nas páginas 39 e 40.
The Linux Foundation. Ingress controllers. In: . The Linux Fundation, 2019. Disponível em:
<https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/>. Citado na página 40.
The Linux Foundation. Using minikube to create a cluster. In: . The Linux Fundation, 2019. Disponível
em: <https://kubernetes.io/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro/>. Citado 2
vezes nas páginas 36 e 37.
The Linux Fundation. Orquestração de contêiner pronto para produção. In: . The Linux Fundation, 2019.
Disponível em: <https://kubernetes.io/pt/>. Citado 7 vezes nas páginas 36, 37, 38, 39, 43, 59 e 62.
W3C. Facts about w3c. In: . W3C, 2019. Disponível em: <https://www.w3.org/Consortium/facts.html>.
Acesso em: 12 de ago. 2019. Citado na página 19.
World Wide Web Foundation. History of the web. In: . World Wide Web Foundation Editor, 2018.
Disponível em: <https://webfoundation.org/about/vision/history-of-the-web/>. Acesso em: 12 de ago.
2019. Citado na página 19.
Anexos
59

ANEXO A – LISTA DE INGRESS CONTROLLERS


ADICIONAIS.

• Ambassador.

• Voyager.

• Contour.

• Citrix.

• F5 BIG-IP Controller for Kubernetes .

• Gloo.

• HAProxy.

• Istio.

• Kong.

• NGINX.

• Traefik.
Fonte – The Linux Fundation (2019).
61

ANEXO B – OPERAÇÕES DA INTERFACE DE


COMANDO KUBECTL.
62 ANEXO B. Operações da interface de comando Kubectl.

Figura 30 – Operações da interface de comando Kubectl.

Fonte – The Linux Fundation (2019).


63

ANEXO C – CONFIGURAÇÕES DO
CONTROLADOR DE INGRESSO

Código C.1 – Arquivo nginx-ingress-controller.yaml.


233 apiVersion: apps/v1
234 kind: Deployment
235 metadata:
236 annotations:
237 deployment.kubernetes.io/revision: "1"
238 kubectl.kubernetes.io/last-applied-configuration: |
239 {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app.
kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx"},"name":"nginx-
ingress-controller","namespace":"ingress-nginx"},"spec":{"replicas":1,"selector":{"matchLabels
":{"app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx"}},"
template":{"metadata":{"annotations":{"prometheus.io/port":"10254","prometheus.io/scrape":"true
"},"labels":{"app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx
"}},"spec":{"containers":[{"args":["/nginx-ingress-controller","--configmap=$(POD_NAMESPACE)/
nginx-configuration","--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services","--udp-services-
configmap=$(POD_NAMESPACE)/udp-services","--publish-service=$(POD_NAMESPACE)/ingress-nginx","--
annotations-prefix=nginx.ingress.kubernetes.io"],"env":[{"name":"POD_NAME","valueFrom":{"fieldRef
":{"fieldPath":"metadata.name"}}},{"name":"POD_NAMESPACE","valueFrom":{"fieldRef":{"fieldPath":"
metadata.namespace"}}}],"image":"quay.io/kubernetes-ingress-controller/nginx-ingress-controller
:0.25.0","livenessProbe":{"failureThreshold":3,"httpGet":{"path":"/healthz","port":10254,"scheme
":"HTTP"},"initialDelaySeconds":10,"periodSeconds":10,"successThreshold":1,"timeoutSeconds":10},"
name":"nginx-ingress-controller","ports":[{"containerPort":80,"name":"http"},{"containerPort
":443,"name":"https"}],"readinessProbe":{"failureThreshold":3,"httpGet":{"path":"/healthz","port
":10254,"scheme":"HTTP"},"periodSeconds":10,"successThreshold":1,"timeoutSeconds":10},"
securityContext":{"allowPrivilegeEscalation":true,"capabilities":{"add":["NET_BIND_SERVICE"],"
drop":["ALL"]},"runAsUser":33}}],"serviceAccountName":"nginx-ingress-serviceaccount"}}}}
240 creationTimestamp: "2019-08-13T16:07:21Z"
241 generation: 1
242 labels:
243 app.kubernetes.io/name: ingress-nginx
244 app.kubernetes.io/part-of: ingress-nginx
245 name: nginx-ingress-controller
246 namespace: ingress-nginx
247 resourceVersion: "12736072"
248 selfLink: /apis/apps/v1/namespaces/ingress-nginx/deployments/nginx-ingress-controller
249 uid: 6e65249f-bde4-11e9-8198-42010a9e016b
250 spec:
251 progressDeadlineSeconds: 600
252 replicas: 1
253 revisionHistoryLimit: 10
254 selector:
255 matchLabels:
256 app.kubernetes.io/name: ingress-nginx
257 app.kubernetes.io/part-of: ingress-nginx
258 strategy:
259 rollingUpdate:
260 maxSurge: 25%
261 maxUnavailable: 25%
262 type: RollingUpdate
263 template:
64 ANEXO C. Configurações do Controlador de Ingresso

264 metadata:
265 annotations:
266 prometheus.io/port: "10254"
267 prometheus.io/scrape: "true"
268 creationTimestamp: null
269 labels:
270 app.kubernetes.io/name: ingress-nginx
271 app.kubernetes.io/part-of: ingress-nginx
272 spec:
273 containers:
274 - args:
275 - /nginx-ingress-controller
276 - --configmap=$(POD_NAMESPACE)/nginx-configuration
277 - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
278 - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
279 - --publish-service=$(POD_NAMESPACE)/ingress-nginx
280 - --annotations-prefix=nginx.ingress.kubernetes.io
281 env:
282 - name: POD_NAME
283 valueFrom:
284 fieldRef:
285 apiVersion: v1
286 fieldPath: metadata.name
287 - name: POD_NAMESPACE
288 valueFrom:
289 fieldRef:
290 apiVersion: v1
291 fieldPath: metadata.namespace
292 image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0
293 imagePullPolicy: IfNotPresent
294 livenessProbe:
295 failureThreshold: 3
296 httpGet:
297 path: /healthz
298 port: 10254
299 scheme: HTTP
300 initialDelaySeconds: 10
301 periodSeconds: 10
302 successThreshold: 1
303 timeoutSeconds: 10
304 name: nginx-ingress-controller
305 ports:
306 - containerPort: 80
307 name: http
308 protocol: TCP
309 - containerPort: 443
310 name: https
311 protocol: TCP
312 readinessProbe:
313 failureThreshold: 3
314 httpGet:
315 path: /healthz
316 port: 10254
317 scheme: HTTP
318 periodSeconds: 10
319 successThreshold: 1
320 timeoutSeconds: 10
321 resources: {}
322 securityContext:
65

323 allowPrivilegeEscalation: true


324 capabilities:
325 add:
326 - NET_BIND_SERVICE
327 drop:
328 - ALL
329 runAsUser: 33
330 terminationMessagePath: /dev/termination-log
331 terminationMessagePolicy: File
332 dnsPolicy: ClusterFirst
333 restartPolicy: Always
334 schedulerName: default-scheduler
335 securityContext: {}
336 serviceAccount: nginx-ingress-serviceaccount
337 serviceAccountName: nginx-ingress-serviceaccount
338 terminationGracePeriodSeconds: 30
339 status:
340 availableReplicas: 1
341 conditions:
342 - lastTransitionTime: "2019-08-13T16:07:21Z"
343 lastUpdateTime: "2019-08-13T16:07:34Z"
344 message: ReplicaSet "nginx-ingress-controller-748cd7b559" has successfully progressed.
345 reason: NewReplicaSetAvailable
346 status: "True"
347 type: Progressing
348 - lastTransitionTime: "2019-09-25T06:43:59Z"
349 lastUpdateTime: "2019-09-25T06:43:59Z"
350 message: Deployment has minimum availability.
351 reason: MinimumReplicasAvailable
352 status: "True"
353 type: Available
354 observedGeneration: 1
355 readyReplicas: 1
356 replicas: 1
357 updatedReplicas: 1

Fonte – Elaborado pelo autor.


67

ANEXO D – CONFIGURAÇÕES DA APLICAÇÃO


NGINX-BACKEND

Código D.1 – Arquivo nginx-backend.yaml.


358 apiVersion: extensions/v1beta1
359 kind: Deployment
360 metadata:
361 name: nginx-backend
362 spec:
363 selector:
364 matchLabels:
365 app: nginx-backend
366 tier: backend
367 track: stable
368 replicas: 1
369 template:
370 metadata:
371 labels:
372 app: nginx-backend
373 tier: backend
374 track: stable
375 spec:
376 containers:
377 - name: nginx-backend
378 image: "nginx"
379 ports:
380 - name: http
381 containerPort: 80
382 protocol: TCP
383 ---
384 kind: Service
385 apiVersion: v1
386 metadata:
387 name: nginx-backend
388 spec:
389 selector:
390 app: nginx-backend
391 tier: backend
392 ports:
393 - name: http
394 port: 80
395 targetPort: 80
396 protocol: TCP

Fonte – Elaborado pelo autor.


69

ANEXO E – CONFIGURAÇÕES DA APLICAÇÃO


APACHE-BACKEND

Código E.1 – Arquivo apache-backend.yaml.


397 apiVersion: extensions/v1beta1
398 kind: Deployment
399 metadata:
400 name: apache-backend
401 spec:
402 selector:
403 matchLabels:
404 app: apache-backend
405 tier: backend
406 track: stable
407 replicas: 1
408 template:
409 metadata:
410 labels:
411 app: apache-backend
412 tier: backend
413 track: stable
414 spec:
415 containers:
416 - name: apache-backend
417 image: "httpd:alpine"
418 ports:
419 - name: http
420 containerPort: 80
421 - name: https
422 containerPort: 443
423 ---
424 kind: Service
425 apiVersion: v1
426 metadata:
427 name: apache-backend
428 spec:
429 selector:
430 app: apache-backend
431 tier: backend
432 ports:
433 - name: http
434 port: 80
435 targetPort: 80
436 protocol: TCP
437 - name: https
438 port: 443
439 targetPort: 443
440 protocol: TCP

Fonte – Elaborado pelo autor.


71

ANEXO F – CONFIGURAÇÕES DA APLICAÇÃO


MEDIAWIKI

Código F.1 – Arquivo mediawiki.yaml.


441 apiVersion: apps/v1beta1
442 kind: Deployment
443 metadata:
444 name: mediawiki
445 spec:
446 selector:
447 matchLabels:
448 app: mediawiki
449 tier: backend
450 track: stable
451 replicas: 1
452 template:
453 metadata:
454 labels:
455 app: mediawiki
456 tier: backend
457 track: stable
458 spec:
459 containers:
460 - name: mediawiki
461 image: "mediawiki:stable"
462 ports:
463 - name: http
464 containerPort: 80
465
466 ---
467 kind: Service
468 apiVersion: v1
469 metadata:
470 name: mediawiki
471 spec:
472 selector:
473 app: mediawiki
474 tier: backend
475 ports:
476 - protocol: TCP
477 port: 80
478 targetPort: http

Fonte – Elaborado pelo autor.

Você também pode gostar