diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..7497a7c Binary files /dev/null and b/.DS_Store differ diff --git a/.github/workflows/pipeline-build-push.yml b/.github/workflows/pipeline-build-push.yml new file mode 100644 index 0000000..fac5427 --- /dev/null +++ b/.github/workflows/pipeline-build-push.yml @@ -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 diff --git a/.github/workflows/pipeline-provision.yml b/.github/workflows/pipeline-provision.yml new file mode 100644 index 0000000..403e4b2 --- /dev/null +++ b/.github/workflows/pipeline-provision.yml @@ -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 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b44637d --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/terraform/.terraform +/terraform/terraform.tfstate +/terraform/terraform.tfstate.backup +/terraform/teste.sh + +# **/.terraform/* +# terraform.tfstate +# terraform.tfstate.backup +# teste.sh \ No newline at end of file diff --git a/README.md b/README.md index 9e2060e..10b21a9 100644 --- a/README.md +++ b/README.md @@ -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. + + + +# 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. diff --git a/README2.md b/README2.md new file mode 100644 index 0000000..9e2060e --- /dev/null +++ b/README2.md @@ -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. diff --git a/projeto-fsharp/Dockerfile b/projeto-fsharp/Dockerfile new file mode 100644 index 0000000..9495e26 --- /dev/null +++ b/projeto-fsharp/Dockerfile @@ -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 \ No newline at end of file diff --git a/projeto-fsharp/Makefile b/projeto-fsharp/Makefile new file mode 100644 index 0000000..a745ebb --- /dev/null +++ b/projeto-fsharp/Makefile @@ -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 \ No newline at end of file diff --git a/projeto-fsharp/apply.sh b/projeto-fsharp/apply.sh new file mode 100755 index 0000000..1acf4b6 --- /dev/null +++ b/projeto-fsharp/apply.sh @@ -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 diff --git a/projeto-fsharp/docker-compose.yaml b/projeto-fsharp/docker-compose.yaml new file mode 100644 index 0000000..28b3089 --- /dev/null +++ b/projeto-fsharp/docker-compose.yaml @@ -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 \ No newline at end of file diff --git a/projeto-fsharp/k8s/deployment/deployment.yaml b/projeto-fsharp/k8s/deployment/deployment.yaml new file mode 100644 index 0000000..10acfab --- /dev/null +++ b/projeto-fsharp/k8s/deployment/deployment.yaml @@ -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 diff --git a/projeto-fsharp/k8s/ingress/deploy.yaml b/projeto-fsharp/k8s/ingress/deploy.yaml new file mode 100644 index 0000000..fff2001 --- /dev/null +++ b/projeto-fsharp/k8s/ingress/deploy.yaml @@ -0,0 +1,647 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + name: ingress-nginx +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx + namespace: ingress-nginx +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get +- apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update +- apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch +- apiGroups: + - coordination.k8s.io + resourceNames: + - ingress-nginx-leader + resources: + - leases + verbs: + - get + - update +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission + namespace: ingress-nginx +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx +rules: +- apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + - namespaces + verbs: + - list + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - nodes + verbs: + - get +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update +- apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission +rules: +- apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx + namespace: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx +subjects: +- kind: ServiceAccount + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission + namespace: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx-admission +subjects: +- kind: ServiceAccount + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx +subjects: +- kind: ServiceAccount + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx-admission +subjects: +- kind: ServiceAccount + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: v1 +data: + allow-snippet-annotations: "true" +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-controller + namespace: ingress-nginx +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-controller + namespace: ingress-nginx +spec: + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - appProtocol: http + name: http + port: 80 + protocol: TCP + targetPort: http + - appProtocol: https + name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + type: LoadBalancer +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-controller-admission + namespace: ingress-nginx +spec: + ports: + - appProtocol: https + name: https-webhook + port: 443 + targetPort: webhook + selector: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-controller + namespace: ingress-nginx +spec: + minReadySeconds: 0 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + strategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + spec: + containers: + - args: + - /nginx-ingress-controller + - --election-id=ingress-nginx-leader + - --controller-class=k8s.io/ingress-nginx + - --ingress-class=nginx + - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller + - --validating-webhook=:8443 + - --validating-webhook-certificate=/usr/local/certificates/cert + - --validating-webhook-key=/usr/local/certificates/key + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + image: registry.k8s.io/ingress-nginx/controller:v1.8.2@sha256:74834d3d25b336b62cabeb8bf7f1d788706e2cf1cfd64022de4137ade8881ff2 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /wait-shutdown + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: controller + ports: + - containerPort: 80 + name: http + protocol: TCP + - containerPort: 443 + name: https + protocol: TCP + - containerPort: 8443 + name: webhook + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 100m + memory: 90Mi + securityContext: + allowPrivilegeEscalation: true + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + runAsUser: 101 + volumeMounts: + - mountPath: /usr/local/certificates/ + name: webhook-cert + readOnly: true + dnsPolicy: ClusterFirst + nodeSelector: + kubernetes.io/os: linux + serviceAccountName: ingress-nginx + terminationGracePeriodSeconds: 300 + volumes: + - name: webhook-cert + secret: + secretName: ingress-nginx-admission +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission-create + namespace: ingress-nginx +spec: + template: + metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission-create + spec: + containers: + - args: + - create + - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name=ingress-nginx-admission + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b + imagePullPolicy: IfNotPresent + name: create + securityContext: + allowPrivilegeEscalation: false + nodeSelector: + kubernetes.io/os: linux + restartPolicy: OnFailure + securityContext: + fsGroup: 2000 + runAsNonRoot: true + runAsUser: 2000 + serviceAccountName: ingress-nginx-admission +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission-patch + namespace: ingress-nginx +spec: + template: + metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission-patch + spec: + containers: + - args: + - patch + - --webhook-name=ingress-nginx-admission + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name=ingress-nginx-admission + - --patch-failure-policy=Fail + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b + imagePullPolicy: IfNotPresent + name: patch + securityContext: + allowPrivilegeEscalation: false + nodeSelector: + kubernetes.io/os: linux + restartPolicy: OnFailure + securityContext: + fsGroup: 2000 + runAsNonRoot: true + runAsUser: 2000 + serviceAccountName: ingress-nginx-admission +--- +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: nginx +spec: + controller: k8s.io/ingress-nginx +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.8.2 + name: ingress-nginx-admission +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: ingress-nginx-controller-admission + namespace: ingress-nginx + path: /networking/v1/ingresses + failurePolicy: Fail + matchPolicy: Equivalent + name: validate.nginx.ingress.kubernetes.io + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + sideEffects: None \ No newline at end of file diff --git a/projeto-fsharp/k8s/ingress/ingress.yaml b/projeto-fsharp/k8s/ingress/ingress.yaml new file mode 100644 index 0000000..9b01faa --- /dev/null +++ b/projeto-fsharp/k8s/ingress/ingress.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: web-services-ingress + annotations: + nginx.ingress.kubernetes.io/use-regex: "true" + # nginx.ingress.kubernetes.io/rewrite-target: /$2 +spec: + ingressClassName: nginx #Irá ser injetado a regra dentro do ingress que contém essa classe. + rules: + # digitar esse dns o mesmo será redirecionado para esse service. + - host: "api-devops-challenge.demo.com" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: api-devops-challenge + port: + number: 80 \ No newline at end of file diff --git a/projeto-fsharp/k8s/kind/config.yaml b/projeto-fsharp/k8s/kind/config.yaml new file mode 100644 index 0000000..b4b0a1e --- /dev/null +++ b/projeto-fsharp/k8s/kind/config.yaml @@ -0,0 +1,25 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + listenAddress: "0.0.0.0" + protocol: TCP + - containerPort: 443 + hostPort: 443 + listenAddress: "0.0.0.0" + protocol: TCP + - containerPort: 8080 + hostPort: 8080 + listenAddress: "0.0.0.0" + protocol: TCP +- role: worker +- role: worker \ No newline at end of file diff --git a/projeto-fsharp/k8s/metallb/metallb.yaml b/projeto-fsharp/k8s/metallb/metallb.yaml new file mode 100644 index 0000000..7312a4e --- /dev/null +++ b/projeto-fsharp/k8s/metallb/metallb.yaml @@ -0,0 +1,18 @@ +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: private-subnet-pool + namespace: metallb-system +spec: + addresses: + - 172.18.0.240-172.18.0.250 + +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: private-subnet-advertisement + namespace: metallb-system +spec: + ipAddressPools: + - private-subnet-pool diff --git a/projeto-fsharp/k8s/metrics-server/components.yaml b/projeto-fsharp/k8s/metrics-server/components.yaml new file mode 100644 index 0000000..ce7ec2c --- /dev/null +++ b/projeto-fsharp/k8s/metrics-server/components.yaml @@ -0,0 +1,197 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + k8s-app: metrics-server + name: metrics-server + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + k8s-app: metrics-server + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" + name: system:aggregated-metrics-reader +rules: +- apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + k8s-app: metrics-server + name: system:metrics-server +rules: +- apiGroups: + - "" + resources: + - nodes/metrics + verbs: + - get +- apiGroups: + - "" + resources: + - pods + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + k8s-app: metrics-server + name: metrics-server-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + k8s-app: metrics-server + name: metrics-server:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + k8s-app: metrics-server + name: system:metrics-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:metrics-server +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + k8s-app: metrics-server + name: metrics-server + namespace: kube-system +spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: https + selector: + k8s-app: metrics-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + k8s-app: metrics-server + name: metrics-server + namespace: kube-system +spec: + selector: + matchLabels: + k8s-app: metrics-server + strategy: + rollingUpdate: + maxUnavailable: 0 + template: + metadata: + labels: + k8s-app: metrics-server + spec: + containers: + - args: + - --cert-dir=/tmp + - --secure-port=4443 + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --kubelet-insecure-tls + - --metric-resolution=15s + image: registry.k8s.io/metrics-server/metrics-server:v0.6.4 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /livez + port: https + scheme: HTTPS + periodSeconds: 10 + name: metrics-server + ports: + - containerPort: 4443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 10 + resources: + requests: + cpu: 100m + memory: 200Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + volumeMounts: + - mountPath: /tmp + name: tmp-dir + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + serviceAccountName: metrics-server + volumes: + - emptyDir: {} + name: tmp-dir +--- +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + labels: + k8s-app: metrics-server + name: v1beta1.metrics.k8s.io +spec: + group: metrics.k8s.io + groupPriorityMinimum: 100 + insecureSkipTLSVerify: true + service: + name: metrics-server + namespace: kube-system + version: v1beta1 + versionPriority: 100 diff --git a/projeto-fsharp/k8s/service/service.yaml b/projeto-fsharp/k8s/service/service.yaml new file mode 100644 index 0000000..7a60091 --- /dev/null +++ b/projeto-fsharp/k8s/service/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-devops-challenge +spec: + selector: + app: api-devops-challenge + ports: + - name: https + port: 80 + targetPort: 8085 + type: ClusterIP \ No newline at end of file diff --git a/terraform/.DS_Store b/terraform/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/terraform/.DS_Store differ diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..36858b6 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,21 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "3.80.0" + hashes = [ + "h1:B9BjHL/otNG7gG2jEPPCz554qbke3fXEH1kzlsg7pnU=", + "zh:11e3362a3d9ca9d6d57a3c863b26ddcb9e4366c6c99586a4149d2842976e998c", + "zh:3005446ee10379e5354b2388d788cad92068ff0988f50e49f6e8eeacdbd6e0a1", + "zh:45aa9f9d930e332fc68f2093232edf15ef0d087c9588317371838784382b9dbc", + "zh:4e1d57b6b909577b37e85117533eb0d6a2128e7ccfcf88e709ad890f86e67295", + "zh:5f777dbb7d72ab83a3a9b9412f8e341573fb34591c834fefa8fc7593e73232a2", + "zh:6fab9ea69a2177e29a0c0819f32c51245891fd19b807c4a3e2d4dd5c0a28b8fb", + "zh:77b1bdf671a83e17c82b30520312970109811c7725b61fcef69138244d7dd212", + "zh:8a1e8d9243f1149b7bcf7b8bda3cf5a1bcea6c709b55053fe7e8cd767dd5f632", + "zh:a7c1de65d5f1f241c4d3f30f24912cb9dc8315a1dc7d7bd0814cb4beb1e8f1fb", + "zh:b4385e7c84d708cd81647555dd12ade9fb128fd027eb59cd651f4cdcf98a437e", + "zh:d4ef3f5b126d5c9766300ffb6f1b3ed091484d46c742cfae2645261e749162e5", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..1321774 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,96 @@ +# main.tf + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "3.80.0" + } + } +} + +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "api-devops-challenge" { + name = var.resource_group_name + location = var.resource_group_location +} + +resource "azurerm_virtual_network" "vnet-api-devops-challenge" { + name = var.vnet_name + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.api-devops-challenge.location + resource_group_name = azurerm_resource_group.api-devops-challenge.name +} + +resource "azurerm_subnet" "subnet-api-devops-challenge" { + name = var.subnet_name + resource_group_name = azurerm_resource_group.api-devops-challenge.name + virtual_network_name = azurerm_virtual_network.vnet-api-devops-challenge.name + address_prefixes = ["10.0.1.0/24"] +} + +resource "azurerm_network_security_group" "nsg-api-devops-challenge" { + name = var.nsg_name + location = azurerm_resource_group.api-devops-challenge.location + resource_group_name = azurerm_resource_group.api-devops-challenge.name + + security_rule { + name = "SSH" + priority = 101 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "10.0.1.0/24" + } +} + +resource "azurerm_subnet_network_security_group_association" "subnet-nsg-association" { + subnet_id = azurerm_subnet.subnet-api-devops-challenge.id + network_security_group_id = azurerm_network_security_group.nsg-api-devops-challenge.id +} + +resource "azurerm_network_interface" "nic-api-devops-challenge" { + name = var.nic_name + location = azurerm_resource_group.api-devops-challenge.location + resource_group_name = azurerm_resource_group.api-devops-challenge.name + + ip_configuration { + name = "internal" + subnet_id = azurerm_subnet.subnet-api-devops-challenge.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_linux_virtual_machine" "vm-linux-api-devops-challenge" { + name = var.vm_name + resource_group_name = azurerm_resource_group.api-devops-challenge.name + location = azurerm_resource_group.api-devops-challenge.location + size = "Standard_B1s" # This size is within the free tier limits + admin_username = var.admin_username + + network_interface_ids = [azurerm_network_interface.nic-api-devops-challenge.id] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts-gen2" + version = "latest" + } + + admin_ssh_key { + username = var.admin_username + public_key = file(var.path_ssh_key) + } + +} diff --git a/terraform/ssh/vm-api-devops-challenge b/terraform/ssh/vm-api-devops-challenge new file mode 100644 index 0000000..3c5f0f8 --- /dev/null +++ b/terraform/ssh/vm-api-devops-challenge @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEA5K6BebIepP8LkPT6Q9CdXYcPQnQBGX/gN/svQg/iY+2z4gVw1qCO +34v58I+Xy0pfbFg95xReQREpjdpwupRkLACbrctCT4mgfUCWqku+jVfLLxhl0Ii/AkpSBT +RG3/ZEbrtN025oZPS5UY3tRKosJK94oIDJ3ZwdqtI0X4nJ99TGZBIm0h+Cl3u3EEkVbE4e +JC1EA9PhFASEOUGWX01/8JxlkIu9ccomjhZXE0gqp3QNzgqcONFvH9V0rgRztq4AXVtTW5 +Z7z6Z6a/Zo/TDethsLLjoso7TsRYvNBeKVjh2oXV5P8kRM+Ypr4TzpJeF6RpInAldfaxEQ +K5fDWsFQPwAAA9h6RRR+ekUUfgAAAAdzc2gtcnNhAAABAQDkroF5sh6k/wuQ9PpD0J1dhw +9CdAEZf+A3+y9CD+Jj7bPiBXDWoI7fi/nwj5fLSl9sWD3nFF5BESmN2nC6lGQsAJuty0JP +iaB9QJaqS76NV8svGGXQiL8CSlIFNEbf9kRuu03Tbmhk9LlRje1Eqiwkr3iggMndnB2q0j +Rficn31MZkEibSH4KXe7cQSRVsTh4kLUQD0+EUBIQ5QZZfTX/wnGWQi71xyiaOFlcTSCqn +dA3OCpw40W8f1XSuBHO2rgBdW1NblnvPpnpr9mj9MN62GwsuOiyjtOxFi80F4pWOHahdXk +/yREz5imvhPOkl4XpGkicCV19rERArl8NawVA/AAAAAwEAAQAAAQEA2U5uoPs/HaFzF0OE +Uk76SzcdrBNaPCYFJo1eAhPgGP930Y9EA+A9BHcagpuhLkA1X1qXMHBthL1PVIpAVzzN1/ +aX+VXOZJCu3ncy9Q7XO68y2EUB82EOyZlgSau8sfRuYR9CPGmNcGoRdEs/LeHb4tyP702T +BjDlDD+GH0drkkFmZ+HEhzO5VawNQur9BReFEzlSU02040s50+uEbLUusY3RP4If42h9Uc +wEaDKt5NJ3o21Mm3LDGjYvxoJds2qY5b/1gG5yLiSMatanMuiUvzA8rnfhoMQ1SvUTyUby +41NJfgFR1iz8crDYpvMa+VAgooLU9qZlZDR5OH3+aAts0QAAAIAqXBTC80dVla9RviJzZk +SDh94dF2u1Fuckx61qPBlL1+oFKSj93vmRQ/cxbYWajP1+WV0U4J6bGwy70UmfKzrhrfH1 +MyrE20gx2lS16C9x8iat5uRx8HXFtS+INkkagocVIN+6eFTfZRInUYWkO8B3DMaGWSySUs +sV0ossfwUV0wAAAIEA+F916Cepsi18DC3yBcIzUsImB4IsFHA0Vd53eu+QTzRO1a53ckKA +5c1JYAMTOBJ6D3K4hFfFGIqA6KanA75SreDB7NV8hE3VKdLlESalQ2+oXGRm6E46L0HcJS +7vAn9jJlwCwC4kKDi0uWpvTLVkOKujmRsh9762m9LZHeNgS9kAAACBAOu0Pv8qFlAaIYcA +k748Zq07c79ayfqRgPr4gIQ/1LB86hWwJ1hR+XlnuJqnlfzbRpLLGBVaIWcy4OwVfzOX87 ++huBkQn3ZbElS5M1aS44bjIVZaStZtrwi0E9RbUfRloaWzfXVzoqRwq+LY81B/SpevHg8w +m3Gikgyr8qWOfWXXAAAAIHZpdG9yZGFjb3N0YXNpbHZhQFZpdG9ycy1NQlAubGFuAQI= +-----END OPENSSH PRIVATE KEY----- diff --git a/terraform/ssh/vm-api-devops-challenge.pub b/terraform/ssh/vm-api-devops-challenge.pub new file mode 100644 index 0000000..20d19ba --- /dev/null +++ b/terraform/ssh/vm-api-devops-challenge.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDkroF5sh6k/wuQ9PpD0J1dhw9CdAEZf+A3+y9CD+Jj7bPiBXDWoI7fi/nwj5fLSl9sWD3nFF5BESmN2nC6lGQsAJuty0JPiaB9QJaqS76NV8svGGXQiL8CSlIFNEbf9kRuu03Tbmhk9LlRje1Eqiwkr3iggMndnB2q0jRficn31MZkEibSH4KXe7cQSRVsTh4kLUQD0+EUBIQ5QZZfTX/wnGWQi71xyiaOFlcTSCqndA3OCpw40W8f1XSuBHO2rgBdW1NblnvPpnpr9mj9MN62GwsuOiyjtOxFi80F4pWOHahdXk/yREz5imvhPOkl4XpGkicCV19rERArl8NawVA/ vitordacostasilva@Vitors-MBP.lan diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..a2d466a --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,57 @@ +variable "resource_group_name" { + description = "Name resource group" + default = "api-devops-challenge" + type = string +} + +variable "resource_group_location" { + description = "Location resource group" + default = "eastus" + type = string +} + +variable "vnet_name" { + description = "Name virtual network (VNet)" + default = "vnet-api-devops-challenge" + type = string +} + +variable "subnet_name" { + description = "Name the subnet" + default = "subnet-api-devops-challenge" + type = string + +} + +variable "nic_name" { + description = "Name network interface Card(NIC)" + default = "nic-vm-api-devops-challenge" + type = string +} + +variable "vm_name" { + description = "Name virtual machine" + default = "vm-linux-api-devops-challenge" + type = string +} + +variable "admin_username" { + description = "Username admin" + default = "devops-admin" + type = string + +} + +variable "path_ssh_key" { + description = "Path administrator's SSH public key" + default = "ssh/vm-api-devops-challenge.pub" + type = string + +} + +variable "nsg_name" { + description = "Name Network Security Group (NSG)" + default = "nsg-api-devops-challenge" + type = string +} +