Deploy manual no Kubernetes usando pipeline do GitLab com ARM64
Uso um Raspberry Pi p/ rodar Kubernetes em single node p/ experimentar algumas coisas com Kubernetes, e o problema sempre foi criar as imagens p/ a arquitetura do Raspberry Pi (ARM64). Encontrei no GitLab a facilidade que procurava p/ rodar meus projetos experimentais usando a arquitetura ARM64.
1. Como fazer o GitLab criar as imagens OCI(Docker) p/ arquitetura ARM64?
1image: golang:1.17
2stages:
3 - test
4 - build
5test:
6 stage: test
7 script:
8 - go test -v ./...
9build:
10 stage: build
11 image: jdrouet/docker-with-buildx:stable
12 services:
13 - docker:dind
14 variables:
15 IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
16 DOCKER_HOST: tcp://docker:2375
17 DOCKER_DRIVER: overlay2
18 script:
19 - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
20 - docker buildx create --use
21 - docker buildx build --platform linux/arm64/v8 -t $IMAGE_TAG . --push
1.1 Quebrando o .gitlab-ci.yml em pedacos (image)
1image: golang:1.17
Define que nossa pipeline vai rodar usando a imagem golang:1.17 , ela é necessária p/ que nosso teste rode.
1.2 Quebrando o .gitlab-ci.yml em pedacos (stages)
1stages:
2 - test
3 - build
Define os estágios da pipeline.
1.3 Quebrando o .gitlab-ci.yml em pedacos (test)
1test:
2 stage: test
3 script:
4 - go test -v ./...
Nesse estágio os testes são executados.
1.4 Quebrando o .gitlab-ci.yml em pedacos (build)
1build:
2 stage: build
3 image: jdrouet/docker-with-buildx:stable
O estágio de build usa a imagem acima que basicamente instala o buildx na imagem, p/ que possamos usar o buildx posteriormente (essa imagem esta desatualizada, pretendo fazer um fork e atualiza-la).
1 services:
2 - docker:dind
`dind` significa Docker in Docker, e é uma maneira que o GitLab disponibiliza p/ os casos em que há necessidade de rodar o build da pipeline usando uma imagem específica.
1variables:
2 IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
3 DOCKER_HOST: tcp://docker:2375
4 DOCKER_DRIVER: overlay2
Nesse ponto são definidas algumas variáveis que serão posteriormente utilizadas. IMAGE_TAG irá definir o nome da imagem que está sendo criada, os valor vem de outras variáveis de ambiente previamente definidas CI_REGISTRY_IMAGE e CI_COMMIT_REF_SLUG.
DOCKER_HOST é uma valor hardcoded que indica onde o Docker que está executando e ouvindo novas requisições, é este host que irá fazer o trabalho de executar nossa imagem e rodar alguns comandos que serão descritos no próximo passo abaixo.
DOCKER_DRIVER define qual driver de disco que deve ser usado, por padrão o vfs é utilizado, nessa variável de ambiente o GitLab prefere que seja usado o driver overlay2. Aqui tem uma explicação muito boa do porque.
1script:
2 - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
3 - docker buildx create --use
4 - docker buildx build --platform linux/arm64/v8 -t $IMAGE_TAG . --push
O script é onde podemos executar "coisas" dentro do nosso container no momento da criação da nossa nova imagem. Em resumo, o que está sendo feito é locar no seu Registro de imagem, que é onde suas imagens ficam hospedadas e posteriormente seu Kubernetes(por exemplo) pode fazer download da imagem que você está solicitando p/ rodar o seu serviço. Em seguida uma instância p/ criação de imagem isolada é criada e finalmente a imagem é criada e enviada p/ o seu registro de container(onde seu container fica armazenado p/ download posterior).
Agora com os comandos p/ ficar mais claro:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY faz login no seu registro de container.
- docker buildx create --use cria uma instância isolada p/ criação da imagem
- docker buildx build --platform linux/arm64/v8 -t $IMAGE_TAG . --push faz a criação da imagem, p/ a plataforma ARM64 (plataforma do RaspberryPi, MacOS M1 e outros), e o --push envia a imagem p/ o registro de container.
obs: a imagem jdrouet/docker-with-buildx:stable está desatualizada, lembre-se de usar uma versão mais recente ou criar uma fork e utilizar a sua própria imagem se for utiliza-la p/ o seu projeto real.
# Deploy p/ o Kubernetes
Agora que nossa imagem está criada e pronta, podemos usa-la e fazer deploy no Kubernetes. Configurar o custer Kuberntes está fora do escopo desse artigo, mas indico o K3S se for criar o cluster usando Raspberry Pi.
Com o seu cluster funcionando, o manifesto(especificação de deploy) do Kubernetes pode seguir esse caminho p/ utilizar a imagem que está em nosso registro de container.
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: go-nome-do-seu-projeto
5spec:
6 replicas: 1
7 selector:
8 matchLabels:
9 name: go-nome-do-seu-projeto
10 template:
11 metadata:
12 labels:
13 name: go-nome-do-seu-projeto
14 spec:
15 containers:
16 - name: go-nome-do-seu-projeto
17 image: registry.gitlab.com/jacquin-home/go-nome-do-seu-projeto:main
18 imagePullPolicy: Always
19 ports:
20 - containerPort: 7001
21 imagePullSecrets:
22 - name: gitlab-auth
O que há de mais relevante no manifesto é:
image: registry.gitlab.com/jacquin-home/go-migrate-best-practices:main
que está definindo onde está localizada sua imagem. E também:
imagePullSecrets: - name: gitlab-auth
Que usa este local p/ localizar as credenciais de autenticação p/ que possa acessar o seu registro de imagens privado (GitLab).