Skip to content

vitorcs api-devops-challenge #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
6478317
feat: Add Dockerfile, docker-compose.yaml and Makefile
Nov 11, 2023
8ef8deb
pipeline.yml
vitor-csilva Nov 11, 2023
5e5f26a
fix: Bug git actions
Nov 11, 2023
daa4491
fix: Bug 2 git actions
Nov 11, 2023
bf42f05
fix: Define docker platform git actions
Nov 11, 2023
eedd940
fix: Define docker platform git actions 2
Nov 11, 2023
5ab1f44
fix: Return docker platform amd64 git actions
Nov 11, 2023
97c7221
feat: Create pipeline-arm.yml
vitor-csilva Nov 11, 2023
52d5edf
fix: Change Docker platform pipeline-arm.yml
Nov 11, 2023
4fc2992
fix: Change Dockerfile
Nov 11, 2023
6776756
fix: Change pipeline-arm.yaml
Nov 11, 2023
59c6b71
fix: Change 3 pipeline-arm.yml
Nov 11, 2023
5f7ecfa
fix: Change 4 pipeline-arm.yml
Nov 11, 2023
8750909
fix: Change 5 pipeline-arm.yml
Nov 11, 2023
84ffd49
fix: Change 6 pipeline-arm.yml
Nov 11, 2023
012aa63
fix: Change 6 pipeline-arm.yml
Nov 11, 2023
2671bcc
fix: Change 7 pipeline-arm.yml
Nov 11, 2023
4f26d49
fix: Change 8 pipeline-arm.yml
Nov 11, 2023
1cc36fd
fix: Change 9 pipeline-arm.yml
Nov 11, 2023
c729c4d
fix: Change 10 pipeline-arm.yml
Nov 11, 2023
f7e2300
fix: Change 11 pipeline-arm.yml
Nov 11, 2023
a6d69bb
fix: Change 12 pipeline-arm.yml
Nov 11, 2023
7cd4d46
fix: Change 13 pipeline-arm.yml
Nov 11, 2023
cb59510
fix: Change 14 pipeline-arm.yml
Nov 11, 2023
68cab10
fix: Change 15 pipeline-arm.yml
Nov 11, 2023
f2340ac
fix: Change 16 pipeline-arm.yml
Nov 11, 2023
0045927
fix: Change 17 pipeline-arm.yml
Nov 11, 2023
c7528fb
fix: Change 18 pipeline-arm.yml
Nov 11, 2023
2506520
fix: Change 19 pipeline-arm.yml
Nov 11, 2023
381e41e
fix: Change 20 pipeline-arm.yml
Nov 11, 2023
cb7752a
fix: Change 21 pipeline-arm.yml
Nov 11, 2023
9e7990d
fix: Change 22 pipeline-arm.yml
Nov 11, 2023
8598e6b
fix: Change 23 pipeline-arm.yml
Nov 11, 2023
88336e9
fix: Change 24 pipeline-arm.yml
Nov 11, 2023
cec148c
fix: Change 25 pipeline-arm.yml
Nov 11, 2023
0784554
fix: Change 26 pipeline-arm.yml
Nov 11, 2023
04f7f2d
fix: Change 27 pipeline-arm.yml
Nov 11, 2023
e76d948
fix: Change 28 pipeline-arm.yml
Nov 11, 2023
dc64fff
fix: Change 29 pipeline-arm.yml
Nov 11, 2023
a6e73b0
fix: Change 30 pipeline.yml
Nov 11, 2023
2d1a7db
feat: Add manifests deployment and service kubernetes
Nov 11, 2023
3b43e26
feat: Add Ingress
Nov 12, 2023
43a05d8
feat: Add readness and liveness Probe
Nov 12, 2023
a959083
feat: Add Requests and Limits deployment
Nov 12, 2023
73f739f
feat: Add metrics-server
Nov 12, 2023
3d84fbc
feat: Add hpa in deployment
Nov 12, 2023
6b87637
feat: Add new resources in hpa
Nov 12, 2023
cf9ae74
feat: Add k8s manifests
Nov 12, 2023
f7fb093
fix: apply.sh k8s
Nov 13, 2023
1345602
fix: backup files
Nov 13, 2023
4f8cfa1
Merge branch 'develop' into feature/task-devops
Nov 13, 2023
6d34738
feat: Add pipeline-provision
Nov 13, 2023
b9cd9eb
feat: Add Revision 1
Nov 13, 2023
1447b26
feat: Add Revision 2
Nov 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
45 changes: 45 additions & 0 deletions .github/workflows/pipeline-build-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This is a basic workflow to help you get started with Actions
name: Build and Push Project

on:
push:
branches: [ "master","develop" ]
paths:
- 'projeto-fsharp/Dockerfile'
- 'projeto-fsharp/**'

env:
REGISTRY: ghcr.io

jobs:
build-and-push-image:
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in no GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v5
with:
context: projeto-fsharp
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/vitor-csilva/api-devops-challenge:latest
40 changes: 40 additions & 0 deletions .github/workflows/pipeline-provision.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: 'Provision Azure'

on:
push:
branches: [ "master","develop" ]
paths:
- terraform/**

jobs:
terraform:
name: 'Terraform'
runs-on: ubuntu-latest
defaults:
run:
working-directory: terraform

permissions:
contents: read
packages: write

steps:
- name: Checkout Repository
uses: actions/checkout@v3

- name: Setup Terraform
uses: hashicorp/setup-terraform@v2

- name: Azure Login
uses: Azure/login@v1.4.6
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: Terraform Init
run: terraform init

- name: Terraform Plan
run: terraform plan

- name: Terraform Apply
run: terraform apply -auto-approve
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/terraform/.terraform
/terraform/terraform.tfstate
/terraform/terraform.tfstate.backup
/terraform/teste.sh

# **/.terraform/*
# terraform.tfstate
# terraform.tfstate.backup
# teste.sh
115 changes: 93 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,101 @@
# Datapi DevOps Challenge
# Documentação Devops Challenge

Para melhor entendermos o seu nível técnico, nós preparamos este desafio como parte do nosso processo de contratação. Por isso, tenha em mente que não é necessário cumprir com todos os pontos mencionados, nem cumpri-los em uma ordem específica.
## Sobre

O importante é entregar o que você conseguir fazer, com a devida documentação.
Toda a construção do projeto foi utilizado o conceito de namespace, por questões de organização e também por motivos de controle sobre o acesso.

# Desafios
Como apoio na organização dos códigos e branches foi utilizada a extensão `Git-Flow`.

Segue abaixo uma lista de desafios abrangendo várias áreas de responsabilidade para um DevOps no time do Datapi. Nossa sugestão é tentar seguir cada item na ordem apresentada, porém você está livre para atuar nos pontos que quiser e tiver mais familiaridade.
# Requisitos para utilização do script

- Instanciar uma VM numa cloud provider. Recomendação: Microsoft Azure.
- Criar a configuração dessa VM usando uma ferramenta de IaC (Infrastructure as Code). Recomendação: Terraform.
- Criar um job de CI (Continuous Integration) para aplicar a configuração da ferramenta de provisionamento. Recomendação: GitHub Actions.
- Adicionar um Dockerfile à aplicação disponibilizada na pasta `projeto-fsharp/` para containerizar o mesmo. Note que foi utilizada a linguagem F# (.NET) para escrever a aplicação. Para facilitar o entendimento do projeto, adicionamos um README.md com instruções de teste e uso do mesmo localmente. Você deverá ser capaz de traduzir essas instruções para a criação do Dockerfile.
- Criar um job de CI para enviar a imagem gerada para um Docker Registry. Recomendação: GitHub Container Registry.
- Criar os manifestos YAML para hospedar a aplicação usando Kubernetes. Nesse ponto os testes podem ser realizados apenas localmente, porém devem ser apresentados os arquivos YAML criados.
* Utilizar IaC para configurar o Kubernetes. Recomendação: Terraform.
* Configurar a hospedagem a partir do registry gerado na tarefa anterior.
* Caso possua mais familiaridade, sinta-se motivado a customizar mais as configurações (secrets, ingress, etc.).
- Adicionar um README ao projeto detalhando o processo e justificando as decisões tomadas. Recomendação: Markdown. Todos os refinamentos adicionados nos tópicos mencionados anteriormente, e demais ideias que possam melhorar o projeto serão considerados na avaliação da solução.
Segue todos os requisitos necessários para utilização do script:

Faça um fork e envie um PR com a sua solução, o tempo de entrega é de no máximo 4 dias e será contabilizado a partir da data do fork.
- 1- Realizar a Instalação do Docker.

## Será avaliado:
- 2- Realizar a instalação do Make(Ferramenta utilizada para automatizar o processo de contrução de imagens docker).

- % do que foi entregue em relação ao que foi pedido.
- Qualidade dos aquivos Terraform.
- Boas práticas de infra e uso do Kubernetes.
- Corretude das tarefas.
- Uso eficiente em relação ao custo de máquina.
Segue os passos para instalação em sistemas Linux(Ubuntu e Debian):
```
$ sudo apt-get update
$ sudo apt-get install make

```

# Dockerfile

O `dockerfile` na qual está localizado na raiz do projeto `projeto-fsharp` foi desenvolvido utilizando boas práticas como Multi-stage builds, priorizando sempre a redução do tamanho da imagem e garantindo que as layers sejam executadas de forma performática.
Imagens utilizadas:
- Builder: mcr.microsoft.com/dotnet/sdk:6.0.413
- Runtime: mcr.microsoft.com/dotnet/aspnet:6.0.0

Apesar do formato yaml ser bem legível, foi documentado o `Dockerfile.yaml` a partir de comentários todos os passos realizados e a definição de cada passo.

<!-- ![Alt text](./doc/dockerfile.png "Dockerfile") -->

# Ambiente de Desenvolvimento

Foi criado para o projeto um ambiente de desenvolvimento para execução e testes da API.

Para o ambiente de desenvolvimento utilizamos o `Make` que é uma ferramenta utilizada para automações de processos sendo muito útil para ambiente de desenvolvimento aumentando a produtividade e eficiência, sendo assim todo o processo de build da imagem, run e compose build foram utilizando essa ferramenta.

## docker-compose.yaml

O `docker-compose.yaml` na qual está localizado na raiz do projeto foi construido com todas as instruções necessárias para execução e testes da API, dessa forma proporcionou uma melhor eficiencia no desenvolvimento.

## Utilização do Script

Atualmente existem 3 funcionalidades disponíveis para utilização do script, sendo elas:
1-build:
O comando `build` executa a construção da imagem a partir das instruções que estão presentes no `Dockerfile.yaml` incluindo o nome da imagem sendo `api-devops-challenge:latest`.
A partir do diretório raiz do projeto execute o comando abaixo:
```
$ make build
```

2-run:
O comando `run` executa a imagem `api-devops-challenge:latest` gerada a partir do comando de build visto anteriormente.
A partir do diretório raiz do projeto execute o comando abaixo:

```
$ make run
```

3-compose:
O comando `compose` ele é o responsável por subir todo o projeto e pronto para ser utilizado.
Este comando executa a construção da imagem a partir das instruções que estão presentes no `Dockerfile.yaml`, e faz o export das portas necessárias para acesso a aplicação.
A partir do diretório raiz do projeto execute o comando abaixo:

```
$ make compose
```

# k8s

A ferramenta utilizada para simulação do ambiente kubernetes foi o `kind` onde foi criado 1 control-plane e 2 data-planes para o nosso cluster, todas essas definições foram feitas no arquivo `config.yaml` disponível no diretório `/k8s/kind/config.yaml`.

Todos os manifestos utilizados para deploy no cluster k8s como deployment, service, ingress e etc estão disponíveis e que podem ser acessado a partir do caminho `/k8s`.

Contamos também com a automação desenvolvida a partir do script `apply.sh` localizado também na raiz do projeto na qual ele é o responsável por realizar toda a criação do cluster, fazer as aplicações dos manifestos e deixar tudo pronto para o usuário.
Dessa forma faz com que todo o ambiente fique disponível com apenas a execução do mesmo:
(necessário ser executado a partir do diretório raiz do projeto)

```
$ ./apply.sh

```

# Pipeline CI/CD Git Hub Actions

Foram criados 2 workflows sendo eles:

- `pipeline-build-push.yml`

Pipeline responsável por fazer toda a automação build, gerar versão\tag, realizar o push da imagem para o repositório do `ghcr.io`.

```
Obs: A imagem gerada é compatível com processadores x86(linux/amd64) e ARM(linux/arm64) e ambos estão disponíveis no repositório do `ghcr.io`.
```

- `pipeline-provision.yml`

Pipeline responsável por fazer o provisionamento da infra infraestrutura na Azure Cloud.
30 changes: 30 additions & 0 deletions README2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Datapi DevOps Challenge

Para melhor entendermos o seu nível técnico, nós preparamos este desafio como parte do nosso processo de contratação. Por isso, tenha em mente que não é necessário cumprir com todos os pontos mencionados, nem cumpri-los em uma ordem específica.

O importante é entregar o que você conseguir fazer, com a devida documentação.

# Desafios

Segue abaixo uma lista de desafios abrangendo várias áreas de responsabilidade para um DevOps no time do Datapi. Nossa sugestão é tentar seguir cada item na ordem apresentada, porém você está livre para atuar nos pontos que quiser e tiver mais familiaridade.

- Instanciar uma VM numa cloud provider. Recomendação: Microsoft Azure.
- Criar a configuração dessa VM usando uma ferramenta de IaC (Infrastructure as Code). Recomendação: Terraform.
- Criar um job de CI (Continuous Integration) para aplicar a configuração da ferramenta de provisionamento. Recomendação: GitHub Actions.
- Adicionar um Dockerfile à aplicação disponibilizada na pasta `projeto-fsharp/` para containerizar o mesmo. Note que foi utilizada a linguagem F# (.NET) para escrever a aplicação. Para facilitar o entendimento do projeto, adicionamos um README.md com instruções de teste e uso do mesmo localmente. Você deverá ser capaz de traduzir essas instruções para a criação do Dockerfile.
- Criar um job de CI para enviar a imagem gerada para um Docker Registry. Recomendação: GitHub Container Registry.
- Criar os manifestos YAML para hospedar a aplicação usando Kubernetes. Nesse ponto os testes podem ser realizados apenas localmente, porém devem ser apresentados os arquivos YAML criados.
* Utilizar IaC para configurar o Kubernetes. Recomendação: Terraform.
* Configurar a hospedagem a partir do registry gerado na tarefa anterior.
* Caso possua mais familiaridade, sinta-se motivado a customizar mais as configurações (secrets, ingress, etc.).
- Adicionar um README ao projeto detalhando o processo e justificando as decisões tomadas. Recomendação: Markdown. Todos os refinamentos adicionados nos tópicos mencionados anteriormente, e demais ideias que possam melhorar o projeto serão considerados na avaliação da solução.

Faça um fork e envie um PR com a sua solução, o tempo de entrega é de no máximo 4 dias e será contabilizado a partir da data do fork.

## Será avaliado:

- % do que foi entregue em relação ao que foi pedido.
- Qualidade dos aquivos Terraform.
- Boas práticas de infra e uso do Kubernetes.
- Corretude das tarefas.
- Uso eficiente em relação ao custo de máquina.
15 changes: 15 additions & 0 deletions projeto-fsharp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0.413 AS builder
#Criando um diretório específico dentro do container para melhor organização
WORKDIR /api
COPY . .
#Restaurando os pacotes necessários para executar o projeto e Buildando.
RUN ./restore.sh && \
dotnet fake run build.fsx -t "Build"

#Iniciando Server. (Multi-stage)
FROM mcr.microsoft.com/dotnet/aspnet:6.0.0 AS runtime
WORKDIR /api
EXPOSE 8085
COPY --from=builder /api/src/Server/out /api
#Comando para iniciar o servidor
CMD ./Server
10 changes: 10 additions & 0 deletions projeto-fsharp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
build:
@docker build -t api-devops-challenge:latest .

run:
@docker run -d -p 8085:8085 --name api-devops-challenge api-devops-challenge:latest

compose:
# export DOCKER_DEFAULT_PLATFORM=linux/arm64
@docker compose build
@docker compose up
34 changes: 34 additions & 0 deletions projeto-fsharp/apply.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash

function _create_cluster () {
kind create cluster \
--config ./k8s/kind/config.yaml \
--name api-devops-challenge

_apply_manifests
_clean
}

function _clean () {
rm -f get-docker.sh
}

function _apply_manifests () {
export KUBECONFIG=$HOME/.kube/config
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml
sleep 60
kubectl apply -f ./k8s/metallb/metallb.yaml
kubectl apply -f ./k8s/metrics-server/components.yaml
sleep 10
kubectl apply -f ./k8s/deployment/deployment.yaml
kubectl apply -f ./k8s/service/service.yaml
kubectl apply -f ./k8s/ingress/deploy.yaml
sleep 360
echo -e "\n---> Caso oocorra problema ao aplicar o ingress, aguarde mais alguns minutos e tente rodar executar novamente de forma mannual: \n"
echo -e "Command:kubectl apply -f ./k8s/ingress/ingress.yaml"
echo -e "\nAplicando ingress:\n"
kubectl apply -f ./k8s/ingress/ingress.yaml
}

#Create Clustes and apply manifests
[ ! -z "`kind version`" ] && _create_cluster
10 changes: 10 additions & 0 deletions projeto-fsharp/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: "3.8"

services:
api-devops-challenge:
# image: vitorcostasilva/api-devops-challenge:1.0
build:
context: .
container_name: api-devops-challenge
ports:
- 8085:8085
60 changes: 60 additions & 0 deletions projeto-fsharp/k8s/deployment/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-devops-challenge-hpa
spec:
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageValue: 100Mi
minReplicas: 3
maxReplicas: 6
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-devops-challenge

---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: api-devops-challenge
name: api-devops-challenge
spec:
replicas: 1
selector:
matchLabels:
app: api-devops-challenge
template:
metadata:
labels:
app: api-devops-challenge
spec:
containers:
- image: ghcr.io/vitor-csilva/api-devops-challenge:latest
name: api-devops-challenge
readinessProbe:
httpGet:
path: "/endpoint/get/hello"
port: 8085
livenessProbe:
httpGet:
path: "/endpoint/get/hello"
port: 8085
resources:
requests:
cpu: 50m
memory: 512M
limits:
cpu: 100m
memory: 1G
Loading