Hospedando Sua Própria AI — Parte 01

Claudio Lazaro
6 min readApr 11, 2024

--

Gerada em DALL.E

O que acha de hospedar seu próprio serviço de AI, uma para chamar de “sua”. Essa será uma sequência de posts onde faremos em uma pequena jornada em algumas tecnologias.

Motivação

Já a algum tempo e quero compartilhar soluções “home-lab” com cara de “corporate”, isso para democratizar a utilização de soluções atualmente utilizadas dentro de grandes empresas.

Para isso eu peguei um tema atual AI, e trouxe como caso de uso para nossa implementação.

Tecnologias Utilizadas

Para tornar este serviço uma realidade, escolhi um conjunto de tecnologias robustas e confiáveis:
Sistema Operacional: Linux Fedora 39, escolhi por sua estabilidade e já vir com podman e dnsmasq.

Resolução de Nomes (DNS): Dnsmasq, para uma gestão simplificada de DNS localmente.

Serviço loca de AI: Ollama, uma aplicação de AI promissora que oferece uma variedade de modelos de machine learning prontos para uso.

Interface Web: webui, proporcionando uma interface amigável para interagir com o serviço de AI.

Infraestrutura: Kubernetes (k3d), garantindo escalabilidade e facilidade de implantação em qualquer ambiente, além de ser muito leve.

Publicação Web: ngrok como ingressClass, facilitando o acesso remoto ao serviço através da internet.

Implementação

A implementação desse projeto envolve a integração dessas tecnologias para criar uma solução completa e funcional. O processo inclui configurar o Dnsmasq no Fedora 39 para resolver nomes localmente, implementar o serviço de AI Ollama com uma interface de usuário webui para facilitar a interação, a interface será “deployada” no Kubernetes (k3d) para assegurar uma implantação flexível e robusta. Além disso, utilizaremos ngrok como ingressClass para publicar o serviço na web, permitindo acesso de qualquer lugar.

Nessa arquitetura não vamos usar o serviço do Ollama no Kuberntes, isso porque perderíamos o “poder” de utiliza-lo no bash para outros fins.

Configurando o Dnsmasq no Fedora 39

O Dnsmasq é uma ferramenta leve que fornece serviços de DNS, DHCP, e TFTP, facilitando a resolução de nomes em redes locais. No Fedora 39, a configuração do Dnsmasq pode ser feita seguindo estes passos:

Update do Fedora

sudo dnf update --refresh -y

Configurando o systemd-resolve

Por padrão o Fedora usa o systemd-resolve como solução de DNS local, e não queremos tirar esse serviço do ar e nem ativar o NetworkManager que nativamente tem um plugin para uso do Dnsmasq, queremo manter o systemd-resolve junto com o Dnsmaq, porém vamos desativar a função de resolver e fazer o forward para o Dnsmasq.

Edite o arquivo resolved.conf:

sudo nano /etc/systemd/resolved.conf 

Edite as linhas:

DNS=127.0.0.1
Domains=~.
DNSStubListener=no

Salve o arquivo ( ctrl + o ) para sair (ctrl + x ).

Nesse ponto não vamos reiniciar o serviço systemd-resolve ainda, pois você não teria um serviço de DNS ativo. Quando aplicarmos isso fará o systemd-resolve liberar a porta 53 e remover o listener dele mesmo.

sudo ss -lntp |grep 53
Perceba que o systemd-resolve esta em execução.

Configurando o Dnsmasq

O Dnsmasq já vem instalado por padrão no Fedora 39, apenas garanta que seu sistema esta atualizado, e então siga em frente.

Verificando o status do serviço:

sudo systemctl status dnsmasq.service
Essa é a saída esperada, onde mostra o serviço desabilitado e sem execução.

Criando o arquivo de configuração:

sudo nano /etc/dnsmasq.d/00-dnsmasq.conf 

Adicione o conteúdo:

listen-address=127.0.0.1 
bind-interfaces
no-resolv

# External Dns Search
server=1.1.1.1
server=8.8.8.8

Salve o arquivo ( ctrl + o ) para sair (ctrl + x ).

Inicializando os serviços, faça na sequência abaixo:

sudo systemctl daemon-reload
sudo systemctl restart systemd-resolved.service
sudo systemctl enable --now dnsmasq

Check se o serviço esta rodando conforme esperado:

sudo ss -lntp |grep 53
Esse é o resultado esperado.

Um duble check nunca é demais, verifique quem esta resolvendo dns:

nslookup medium.com
O resultado esperado é esse, o answer pode mudar, as 2 primeiras linhas não.

Instalando o Kubernetes com k3d

O k3d é uma ferramenta que facilita a execução do K3s (uma distribuição leve do Kubernetes) em contêineres, ideal para ambientes de desenvolvimento.

Instalando kubectl, ferramenta para interagir com o cluster:

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
Saída do processo de download.
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl --help
Essa saída e bem longa, aqui esta somente o início.

⚠️: Se estiver executando em máquina virtual, vamos usar o docker, tem uma nota de IMPORTANTE — DOCKER um pouco mais abaixo.

Agora vamos configurar o Podman, que é o container runtime que vamos usar para executar nossa infraestrutura de Kubernetes:

Primeiro vamos habilitar o ip forward e o pool de sub-net que o podman vai ser executado, essa configuração não é obrigatório, mais eu aconselho para garantir que você não tenha overlap caso use vpn por exemplo, e caso queira executar algum container com a função de “gateway”.

Edite o arquivo containers.conf:

sudo nano /usr/share/containers/containers.conf

Edite as configurações a seguir, use (ctrl +q ) para buscar por “default_sysctls” e deixe conforme abaixo:

default_sysctls = [
"net.ipv4.ping_group_range=0 0","net.ipv4.ip_forward=1"
]

Agora busque por “default_subnet”, deixe conforme sugerido:

default_subnet = "172.80.0.0/16"

# DefaultSubnetPools is a list of subnets and size which are used to
# allocate subnets automatically for podman network create.
# It will iterate through the list and will pick the first free subnet
# with the given size. This is only used for ipv4 subnets, ipv6 subnets
# are always assigned randomly.
#
default_subnet_pools = [
{"base" = "172.80.0.0/16", "size" = 24},
{"base" = "172.90.0.0/16", "size" = 24},
# {"base" = "10.92.0.0/14", "size" = 24},
# {"base" = "10.96.0.0/11", "size" = 24},
# {"base" = "10.128.0.0/9", "size" = 24},
]


Não altere mais nada, a não ser que você saiba o que esta fazendo.

Salve o arquivo ( ctrl + o ) para sair (ctrl + x ).

Execute os comando seguinte na sequência:

sudo systemctl enable --now podman.socket
sudo dnf install podman-docker -y
sudo systemctl status podman.socket
Saída esperada.

Pronto finalizamos a fundação, agora vamos de fato instalar o k3d, que é o nosso Kubernetes (k3s).

Instalação do k3d, observe que estamos usando TAG=V5.6.0

curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | TAG=v5.6.0 bash 
Saída esperada, esse processo é muito rápido.

Agora vamos subir nosso cluster, e nesse ponto vamos fazer algumas mudanças no nosso ambiente.

Uma das mudança é remover o ingressClass padrão do k3d, que é o traefik e vamos instalar dois outros ngix e ngrok.

Outra mudança é adicionar um loadBalancer externo, como se fosse em um cenário corporativo.

Esse é o comando para configurar nosso cluster:

sudo k3d cluster create mediumlab --api-port 6550 -p "8081:80@loadbalancer" --agents 2 --k3s-arg "--disable=traefik@server:0"
Esse é o output esperado, podendo mudar o seu network gateway.

NOTA: IMPORTANTE — DOCKER

Caso você tenha dificuldade de executar o k3d no podman, isso provavelmente esta acontecendo porque você esta rodando em uma maquina virtual, então nesse caso utilize o docker para prosseguir, remova o pacote “podman-docker” e instale normalmente o docker.

No docker se você quiser configurar as sub-nets preferenciais edite o arquivo: /etc/docker/daemon.json

sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.json
#Adicionar no arquivo daemon.json
{
"default-address-pools":
[
{"base":"172.80.0.0/16","size":24},
{"base":"172.90.0.0/16","size":24}
]
}

Execute os comandos abaixo em sequência:

mkdir -p ~/.kube
sudo cp /root/.kube/config ~/.kube/
sudo chown $USER:$USER ~/.kube/config
kubectl cluster-info
Essa é a saída esperada, se tudo estiver correto :)

Nesse ponto você já tem um cluster de kubernetes (k3s), rodando localmente dentro de um contêiner, coisa louca não :), ou seja você vai rodar seus workload de container em um cluster que também é um container … veja com o comando

sudo podman ps -a 
ou
sudo docker ps -a

Veja que você tem um cluster composto por : 1 server (master), 2 agentes, e 1 load balancer.

Vamos finalizar essa parte 01 por enquanto, pois ainda temos muito trabalho pela frente e se você já chegou ate aqui, meus parabéns !!

Parte 02

--

--