# Kong: uma introdução não tão breve

## Introdução da introdução

Kong é um API Gateway e Microservices Management Layer escalável, flexível e de alto desempenho. Ele funciona como uma porta de entrada para suas APIs, unindo diversas interfaces de microsserviços em uma única API. Kong oferece recursos essenciais, como roteamento, autenticação, rate-limiting, analytics e muito mais, através de plugins que são extremamente fáceis de serem instalados e operados.

Neste post, aprenderemos a usar o Kong usando Docker, uma forma fácil de empacotar, distribuir e gerenciar aplicações. Para nossa demonstração, criei um repositório contendo uma estrutura de arquivos e diretórios específicos, bem como um `Dockerfile` e um arquivo `docker-compose.yaml` que tornará a configuração do Kong uma brisa.

### Instalação

Clone o repositório: [https://github.com/fabiano-amaral/kong-api-gateway-quickstart](https://github.com/fabiano-amaral/kong-api-gateway-quickstart)

```bash
git clone https://github.com/fabiano-amaral/kong-api-gateway-quickstart.git
```

Navegue até a pasta do projeto:

```bash
cd kong-api-gateway-quickstart
```

Construa e levante os serviços com Docker Compose:

```yaml
docker-compose up --build -d
```

### Estrutura do Projeto

A estrutura do nosso projeto Kong em uma pasta de sua preferência é a seguinte:

```bash
.
├── certs
├── config
│   ├── plugins
│   │   ├── rate-limit.yaml
│   │   └── README.md
│   └── services
│       ├── example.yaml
│       └── README.md
├── docker-compose.yaml
├── Dockerfile
├── LICENSE.md
├── plugins.yaml
├── README.md
└── scripts
    ├── init-kong.sh
    └── README.md
```

### Dockerfile

Nosso Dockerfile começa com a imagem oficial do Kong 3 e prossegue copiando o arquivo `plugins.yaml` (esse arquivo criei para facilitar a adição de novos plugins a nossa imagem) para o contêiner e instala os plugins do Kong listados nesse arquivo usando `luarocks`. Além disso, o script [`init-kong.sh`](http://init-kong.sh) é copiado para o contêiner e definido como o ponto de entrada.

```dockerfile
# Usar a imagem oficial do Kong como base
FROM kong:3

COPY plugins.yaml /plugins.yaml

# Pode ser feio e difícil de entender uma primeira vez
# mas é funcional para add plugins
RUN yq e '.plugins[] | "luarocks install \(.name) \(.version)"' /plugins.yaml | sh

USER root
# Copiar o script para o contêiner e permissão
COPY ./scripts/init-kong.sh /init-kong.sh
RUN chmod +x /init-kong.sh
USER 1000

COPY ./config /etc/kong/config

# Definir o script como o ponto de entrada
ENTRYPOINT ["/init-kong.sh"]
```

O script `init-kong.sh` foi mais uma forma de transformar o desenvolvimento local mais próximo de um ambiente produtivo, onde você claramente não quer criar coisas no clickOps, então ele carrega os arquivos das pastas `config/plugins` e `config/services` e os configuram no control plane (repare que o data-plane não usa essa imagem customizada) do Kong.

```bash
#!/bin/sh

# Para plugins
for file in /etc/kong/config/plugins/*.yaml; do
  kong config db_import $file
done

# Para services
for file in /etc/kong/config/services/*.yaml; do
  kong config db_import $file
done

# Executar o comando original de inicialização do Kong
exec /docker-entrypoint.sh kong docker-start
```

### Docker Compose

O arquivo `docker-compose.yaml` define vários serviços, incluindo o banco de dados do Kong, o serviço *control plane* do Kong, o serviço *data plane* do Kong, um serviço para gerar certificados SSL e um serviço para lidar com migrações do Kong. A comunicação entre o control plane e o data plane é segura (uma exigência do modo hibrido do Kong), usando um certificado SSL gerado no contêiner `generate-certs`. Não vou entrar em detalhes nas configurações do arquivo, pois elas são bastante autoexplicativas.

```yaml
version: '3'

volumes:
  certs:

networks:
  kong-net:

services:
  # gera o certificado de comunicação entre data e control plane
  generate-certs:
    image: alpine
    command: sh -c "apk add openssl && openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp384r1) -keyout /tmp/cluster.key -out /tmp/cluster.crt   -days 1095 -subj "/CN=kong_clustering""
    volumes:
      - certs:/tmp

  kong-migrations:
    image: kong:3
    networks:
        - kong-net
    command: "kong migrations bootstrap"
    environment:
      - KONG_DATABASE=postgres
      - KONG_PG_HOST=kong-database
      - KONG_PG_USER=kong
      - KONG_PG_PASSWORD=kong
    volumes:
      - certs:/certs
    depends_on:
      kong-database:
        condition: service_healthy

  kong-control-plane:
    build: .
    networks:
        - kong-net
    healthcheck:
      test: ["CMD", "kong", "health"]
      interval: 5s
      timeout: 10s
      retries: 10
    environment:
      - KONG_ROLE=control_plane
      - KONG_DATABASE=postgres
      - KONG_PG_HOST=kong-database
      - KONG_PG_USER=kong
      - KONG_PG_PASSWORD=kong
      - KONG_ADMIN_LISTEN=0.0.0.0:8001
      - KONG_CLUSTER_CERT=certs/cluster.crt
      - KONG_CLUSTER_CERT_KEY=certs/cluster.key
      - KONG_ADMIN_GUI_URL=http://localhost:8002
      - KONG_CLUSTER_LISTEN=0.0.0.0:8005
      - KONG_ADMIN_GUI_LISTEN=0.0.0.0:8002
    volumes:
      - certs:/certs
      - ./scripts/init-kong.sh:/init-kong.sh
      - ./config:/etc/kong/config
    ports:
      - 8001:8001
      - 8002:8002
    depends_on:
      generate-certs:
        condition: service_completed_successfully
      kong-migrations:
        condition: service_completed_successfully

  kong-data-plane:
    image: kong:3
    networks:
        - kong-net
    environment:
      - KONG_ROLE=data_plane
      - KONG_DATABASE=off
      - KONG_CLUSTER_CONTROL_PLANE=kong-control-plane:8005
      - KONG_CLUSTER_CERT=certs/cluster.crt
      - KONG_CLUSTER_CERT_KEY=certs/cluster.key
    volumes:
      - certs:/certs
    ports:
      - 8000:8000
      - 8443:8443
    depends_on:
      kong-control-plane:
        condition: service_healthy

  kong-database:
    image: postgres:15-alpine
    networks:
        - kong-net
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "kong"]
      interval: 5s
      timeout: 5s
      retries: 5
    environment:
      POSTGRES_DB: kong
      POSTGRES_USER: kong
      POSTGRES_PASSWORD: kong
```

## Modelo híbrido com Kong

### O que é o modelo híbrido?

O modelo híbrido é um recurso do Kong que permite dividir suas instâncias em dois tipos de planos: Control Plane (CP) e Data Plane (DP).

* **Control Plane (CP)**: É responsável por todo o gerenciamento da sua infraestrutura Kong. Ele mantém a configuração, os plugins e quaisquer outros aspectos que afetem a lógica de roteamento, mas não lida diretamente com o tráfego da API.
    
* **Data Plane (DP)**: Este é o plano que efetivamente lida com o tráfego da API. Ele recebe todas as requisições e as roteia com base nas instruções fornecidas pelo Control Plane.
    

### Por que usar o Modelo Híbrido?

* **Escalabilidade**: Como o Data Plane e o Control Plane são desacoplados, você pode escalar cada um deles independentemente, de acordo com suas necessidades.
    
* **Segurança**: O Data Plane pode ser exposto à internet, enquanto o Control Plane pode ser mantido em uma rede segura.
    
* **Gerenciamento Centralizado**: Todas as configurações são armazenadas e gerenciadas no Control Plane, tornando mais fácil gerenciar múltiplas instâncias do Data Plane.
    

## Configuração

### Serviços e Rotas

#### Definição de Serviços

Para definir os serviços que o Kong deve gerenciar, você vai utilizar arquivos YAML dentro da pasta `config/services/`. Cada arquivo deve conter a configuração para um ou mais serviços que você deseja expor via Kong.

Por exemplo, o arquivo `config/services/example.yaml` pode ter o seguinte conteúdo:

```yaml
_format_version: "3.0"
_transform: false

services:
- name: meu-servico
  url: https://mockbin.org
```

Neste exemplo, um serviço chamado `meu-servico` é definido e aponta para a URL [`https://mockbin.org`](https://mockbin.org). Entenda o serviço como sua API que ficará atrás do API Gateway.

#### Definição de Rotas

As rotas associadas aos serviços são também configuradas dentro dos arquivos YAML em `config/services/`. Dentro de cada configuração de serviço, você pode definir múltiplas rotas.

Ajustando o exemplo anterior, o arquivo `config/services/example.yaml` poderia ser expandido para:

```yaml
_format_version: "3.0"
_transform: false

services:
- name: meu-servico
  url: https://mockbin.org
  routes:
  - name: rota-para-meu-servico
    paths:
    - "/meu-servico"
```

Aqui, uma rota chamada `rota-para-meu-servico` é adicionada ao serviço `meu-servico`. Qualquer requisição a Kong com o caminho `/meu-servico` será encaminhada para [`https://mockbin.org`](https://mockbin.org). Rode o projeto com `docker compose up` e acesse `http://localhost:8000/meu-servico` no navegador de sua preferência.

### Plugins

#### Instalação de Plugins

O arquivo `plugins.yaml` na raiz do projeto é utilizado especificamente para a instalação de novos plugins do Kong. Não é usado para ativar ou configurar esses plugins para serviços específicos. Neste arquivo, você deve listar todos os plugins que deseja instalar, bem como as suas versões. Exemplo:

```yaml
plugins:
  - name: "kong-plugin-rate-limiting"
    version: "2.0.0"
```

Ao construir sua imagem Docker com este arquivo na raiz, os plugins listados serão instalados.

#### Ativação e Configuração de Plugins

Para a ativação e configuração de plugins em serviços específicos, você deve utilizar os arquivos YAML dentro da pasta `config/plugins/`. Cada arquivo YAML nesse diretório deve conter as configurações para um ou mais plugins que você deseja ativar ou configurar.

Por exemplo, um arquivo `config/plugins/rate-limit.yaml` pode conter:

```yaml
_format_version: "3.0"
_transform: false

plugins:
- name: rate-limiting
  config:
    second: 5
```

Esses arquivos são usados para configurar como os plugins funcionarão em relação aos seus serviços, mas não para instalá-los. A instalação, como mencionado, é gerenciada pelo `plugins.yaml` na raiz do projeto. Existem vários plugins disponíveis no [hub da Kong](https://docs.konghq.com/hub/), alguns disponíveis apenas com licenças enterprise.

#### Resumo

* **Para instalar novos plugins**: Use o arquivo `plugins.yaml` na raiz do projeto.
    
* **Para configurar e ativar plugins em serviços específicos**: Use os arquivos dentro de `config/plugins/`.
    
* **Para definir serviços e suas respectivas rotas**: Use os arquivos dentro de `config/services/`.
    

Essa organização garante que a configuração do seu ambiente Kong seja modular, tornando mais fácil gerenciar serviços e plugins separadamente. E os arquivos da pasta `config` podem ser usados em conjunto com o [decK](https://docs.konghq.com/deck/latest/) para criar um fluxo de gitOps para deploy de novas configurações em ambiente produtivo, vale a pena explorar.

## Uso

### Administração

Uma vez que você tenha inicializado todos os serviços usando o Docker Compose, várias interfaces estarão disponíveis para interação e administração do Kong. A seguir estão as mais relevantes:

* **Kong Admin API**: Acessível via [`http://localhost:8001`](http://localhost:8001), esta é a API administrativa que você usará para todas as operações programáticas no Kong. Seja para adicionar novos serviços, rotas ou para ativar plugins, tudo pode ser feito aqui através de chamadas RESTful.
    
* **Kong Admin GUI**: Esta é a interface gráfica do usuário e pode ser acessada através de [`http://localhost:8002`](http://localhost:8002). A GUI oferece uma maneira mais visual e interativa para gerenciar os aspectos do seu gateway API. Ele é especialmente útil para visualizar o fluxo de tráfego, modificar configurações existentes ou adicionar novas funcionalidades de forma mais intuitiva.
    

Ambas as interfaces são destinadas a administradores e devem ser protegidas adequadamente em ambientes de produção. Se você está apenas começando, a Admin GUI pode ser um excelente ponto de partida para entender como tudo funciona. À medida que você se familiarizar com o sistema, é provável que passe a utilizar a Admin API para integrações mais avançadas e automações.

### Consumindo suas APIs públicadas no Kong

### **Proxy de API do Kong**

Após a inicialização bem-sucedida de todos os serviços, o Kong estará pronto para começar a rotear suas solicitações. O ponto de entrada para suas APIs é através do **Proxy de API do Kong**, que é acessível via [http://localhost:8000](http://localhost:8000). Todas as requisições a serem roteadas através do Kong serão enviadas para este endpoint.

O Proxy de API é onde a mágica realmente acontece. Quando uma requisição chega ao proxy, o Kong determina a que serviço a requisição pertence com base nas rotas que você definiu. Em seguida, ele aplica qualquer plugin que você tenha ativado para a rota, o serviço, ou globalmente, antes de encaminhar a requisição ao serviço upstream correspondente.

Aqui estão alguns exemplos de operações que você pode realizar através do Proxy de API:

* **Roteamento de Requisições**: Baseado nos caminhos de URL, métodos HTTP, e outros atributos da requisição, o Kong roteará a requisição para o serviço upstream correspondente.
    
* **Autenticação**: Se você ativou um plugin de autenticação, o Kong verificará as credenciais na requisição antes de permitir o acesso ao serviço upstream.
    
* **Rate Limiting**: Se você configurou o rate limiting, o Kong controlará a taxa de requisições para garantir que os limites configurados não sejam excedidos.
    
* **Logging**: Plugins de logging podem ser configurados para registrar as requisições e respostas para ajudar na análise e depuração.
    

Estas são apenas algumas das muitas funcionalidades que o Kong oferece para ajudar a gerenciar o tráfego de API e garantir que as requisições sejam processadas de forma segura e eficiente. Experimente enviar algumas requisições para [`http://localhost:8000`](http://localhost:8000) e observe como elas são roteadas e processadas com base na configuração do seu Kong.

### Conclusão

Com a configuração acima, você tem um ambiente Kong totalmente funcional, pronto para ser expandido com mais serviços, rotas e plugins conforme necessário. O uso do Docker e do Docker Compose facilita a configuração, a execução e o gerenciamento do Kong, tornando-o uma opção atraente para gerenciar suas APIs e microserviços.

Para mais informações e detalhes sobre como expandir e personalizar sua configuração do Kong, você pode referenciar a [documentação oficial do Kong](https://docs.konghq.com/). Se chegou até aqui, não esqueça de ativar as notificações e se inscrever no canal :hehe:

---
