Já subi uma aplicação para a AWS umas 3 vezes mas todas foram um processo muito manual usando o EC2, hoje pela primeira vez usei o kubernets para automatizar esse processo.
Kubernets (K8s)
O kubernets é um orquestadror de containers que fica responsável por transformar esses containers em pods e subir esses containers de forma mais automatizada para uma cloud como AWS ou GCP ou outras opções, porem ele não faz só isso, ele também tem o load balancer onde ele tenta distribuir as cargas para não deixar um pod sobrecarregado e também toda a parte de service discovery além de levantar pods novos sempre que os antigos caírem
Como usar o K8s
Primeiro vamos criar um arquivo do tipo yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Nesse arquivo inicial temos:
apiVersion
: Versão da api do k8s, nesse caso é a v1
kind
: qual o tipo do recurso a ser criado, nesse caso um pod
metadata
: dados complementares
-
name
: nome do pod -
labels
: label do pod então podemos depois filtrar por pods com a labelngnix
por exemplospec
: especificação do serviço -
containers
: qual o container dentro daquele pod com seu nome a sua imagem e a sua porta > Existem casos de termos mais de um pod em um container porem como regra geral geralmente temos um pod por container
Com isso temos já um pod, para testar esse pod podemos usar o kind que serve para rodar o kubernets localmente, no próprio site do kind eles ensinam como instalar em diversos sistemas operacionais. Depois de instalado podemos rodar o comando
kind create cluster --name={algo}
e entao o kind vai sugerir rodarmos o comando kubectl cluster-info --context kind-{algo}
mas para isso vamos precisar do kubectl depois de rodarmos o comando do kubectl conseguimos ver que o kubernets já está como ready
por padrão o kubernets tem o control-plane que gerencia tudo, e quem é gerenciado são as maquinas que ficam conectadas no control-plane. Para rodar um cluster kubernets é recomendado no minimo 3 maquinas
agora para conectar o pod precisamos rodar kubectl apply -f {nome_do_yml}
e com o kubectl get pods
ele vai retornar o pod rodando, e para conectar com o ngnix? temos que dar um port-forward com o comando kubectl port-forward pod/nginx 9090:80
onde 80 é a porta que declaramos no yml e o 9090 é a porta que disponibilizei no meu computador, então se eu for no meu localhost 9090 vou encontrar o nginx
ReplicaSet
Porem o kubernets ainda não está mantendo o pod online todo o tempo, se rodarmos o comando kubectl delete pod nginx
o pod vai ficar fora do ar. Para garantir que os pods estejam sempre online precisamos adicionar o Replica set, que fica gerenciando os pods e vendo se algum pod saiu do ar para ele criar um novo.
O yml do replicaSet ficou assim:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
spec:
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
onde ele é do tipo ReplicaSet e ele monitora todos os pods que a label é 'nginx', ele tem também um template igual ao pod que definimos no yaml anterior, para que ele saiba como vai ser o pod que ele vai criar.
Podemos ver que agora sempre que eu excluo um pod o replicaSet logo em seguida sobe um novo no lugar, além disso é possivel ver que já está salva a configuração que eu desejo manter apenas uma replica daquele pod.
Deployments
Se eu quiser mudar a versão da imagem que estou utilizando o replicaSet não vai fazer essa mudança de forma automática, para isso vou precisar matar o pod para quando subir novamente ele subir com a versão nova, o replicaSet só verifica se o pod caiu e quantos pods eu quero.
Agora imagine essa situação onde eu tenho por exemplo 100 replicas, eu teria que matar os pods para atualizar a versão da imagem. E para isso temos os deployments, que são responsaveis por cuidar dos replicasets.
O Deployment sempre que quisermos mudar a versão da imagem ele vai criar um novo replicaSet, então por exemplo, temos 10 pods na versão 1.0, queremos atualizar para a versão 1.1, o deployment cria um novo replicaset com a versão 1.1 e pedindo 10 pods, enquanto no da versão 1.0 ele pede por 0 pods, e se a versão 1.1 estiver quebrada e precisarmos voltar ele pede por 10 pods na versão 1.0 e 0 pods na versão 1.1
O yml do deployment é igual ao do replicaSet, só muda que no kind ao inves de ReplicaSet vai ser Deployment, porem todo o processo é mesmo, basta dar um apply que vai funcionar
Da para ver como ele fica alternando entre os replicaSets conforme a configuração muda
Rodando o kubernets com o meu servidor
Para isso criei um servidor bem basico em GO, tudo que ele faz é escrever hello world quando acessamos a porta 9090
package main
import "net/http"
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":9090", nil)
}
func hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World!"))
}
alem disso vou criar um arquivo docker
FROM golang:1.18 as builder
WORKDIR /app
COPY main.go .
COPY go.mod .
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o server main.go
FROM scratch
COPY --from=builder /app/server .
CMD [ "./server" ]
vou buildar esse arquivo docker build -t yansb/goserver:latest .
e se e eu rodar o comando docker run --rm -p 9090:9090 yansb/goserver:latest
já consigo acessar minha porta 9090 e ver o hello world, depois disso posso dar um push dessa imagem para o meu dockerhub, agora ja posso criar um novo yaml com o essa imagem e fazer esse novo deployment
Se eu der um port-forward e for na porta 9090 já consigo ver o meu hello world
Load balancer
Agora com diversas replicas dos pods (10 com o GO e 10 nginx) temos um problema, como K8s vai saber para qual pod mandar a pessoa que está acessando a aplicação
Vamos criar um yaml para o service:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Esse service vai pegar todos os pods com a label nginx e vai fazer o loadBalance baseado nessa seleção agora qualquer pessoa que internamente procurar pelo nginx-service ou pelo ip dele, vai chegar até um dos nginx.
O external ip está como pending pois meu computador não consegue gerar um IP externo, porem se estivesse rodando na aws, já poderíamos acessar esse ip externo e ter acesso ao ngnix
Tudo que fiz hoje com o kubernets está nesse repositório: https://github.com/Yansb/full-cycle-course/tree/master/kubernets
Top comments (0)