Gerenciando VMs pelo Terraform na Oracle Cloud
Estou escrevendo esse post para ajudar quem está começando na gerência servidores alocados pelo Terraform na Oracle Cloud.
Eu utilizo o Terraform Cloud para fazer o controle das versões do state da infraestrutura por isso vou começar mostrando as configurações necessárias de serem feitas no Terraform Cloud para poder executar a criação das máquinas.
No caso é necessário criar as variáveis de ambiente que são exibidas na imagem abaixo para o Terraform Cloud ter acesso na sua conta da OCI e poder criar os objetos.
Não vou entrar em detalhes de configuração do Terraform Cloud com o Gitlab e nos detalhes das configurações da Oracle Cloud para poder gerar essas variáveis, pois iria deixar muito longa a postagem.
Criação do Provider
Depois de toda a integração ter sido feita entre o Gitlab e o Terraform Cloud começamos pela com a criação do arquivo main.tf que basicamente vai definir o provider que vai ser utilizado, no caso o provider da oracle/oci.
Nesse exemplo eu optei por definir a variável compartment_ocid diretamente no arquivo, mas ela poderia ter sido definida juntamente com as outras variáveis diretamente no Terraform Cloud.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
variable "tenancy_ocid" {} variable "user_ocid" {} variable "fingerprint" {} variable "private_key" {} variable "region" {} variable "compartment_ocid" { default = "ocid1.compartment.oc1..aaaaaaaanh5ao3yobh4izf4ncdvc4kcirhvyofxxgsywqmhqo6fiua6c7c6a" } terraform { required_providers { oci = { source = "oracle/oci" version = "=4.104.0" } } } provider "oci" { tenancy_ocid = var.tenancy_ocid user_ocid = var.user_ocid fingerprint = var.fingerprint private_key = var.private_key region = var.region } |
Criação da VCN
Agora que o provider foi definido a primeira coisa que eu faço é criar a minha VCN, e as sub-redes que eu vou colocar as máquinas que irei criar. Nesse caso eu crio o arquivo vcn.tf conforme o conteúdo abaixo.
A VCN é criada utilizando o CIDR 10.1.0.0/16 e nessa VCN eu crio duas sub-redes, uma para colocar servidores de aplicação chamada subnet-app usando o bloco CIDR 10.1.0.0/24 e outra chamada subnet-bd para colocar servidores de Banco de Dados, essa usando o bloco CIDR 10.1.1.0/24.
Eu configuro o DHCP default da VCN que foi criada para definir que as máquinas incluídas nessa VCN irão pesquisar por padrão no domínio adonai.eti.br, também configuro a tabela de roteamento e o gateway padrão, basicamente apenas coloco um nome neles, sem alterações no funcionamento padrão.
A Security List padrão que é criada com a VCN eu libero todo o tráfego nela, tanto de entrada quanto de saída.
As regras de acesso eu irei fazer usando os Security Groups que são associados diretamente nas interfaces das máquinas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
resource "oci_core_vcn" "vcn-adonai" { cidr_block = "10.1.0.0/16" compartment_id = var.compartment_ocid display_name = "VCN Adonai" dns_label = "adonai" } resource "oci_core_default_security_list" "default-security-list" { manage_default_resource_id = oci_core_vcn.vcn-adonai.default_security_list_id display_name = "VCN Adonai- Security List" egress_security_rules { description = "Sai para a internet" protocol = "all" destination = "0.0.0.0/0" destination_type = "CIDR_BLOCK" } ingress_security_rules { description = "libera acesso aos servidores" protocol = "all" source = "0.0.0.0/0" source_type = "CIDR_BLOCK" } } resource "oci_core_default_dhcp_options" "default-dhcp-options" { manage_default_resource_id = oci_core_vcn.vcn-adonai.default_dhcp_options_id options { type = "DomainNameServer" server_type = "VcnLocalPlusInternet" } options { type = "SearchDomain" search_domain_names = [ "adonai.eti.br" ] } display_name = "VCN Adonai- DHCP" } resource "oci_core_default_route_table" "default-route-table" { manage_default_resource_id = oci_core_vcn.vcn-adonai.default_route_table_id display_name = "VCN Adonai- Route Table" route_rules { destination = "0.0.0.0/0" destination_type = "CIDR_BLOCK" network_entity_id = oci_core_internet_gateway.igw-01.id } } resource "oci_core_internet_gateway" "igw-01" { compartment_id = var.compartment_ocid display_name = "VCN Adonai- Internet Gateway" vcn_id = oci_core_vcn.vcn-adonai.id } resource "oci_core_subnet" "subnet-app" { cidr_block = "10.1.0.0/24" compartment_id = var.compartment_ocid vcn_id = oci_core_vcn.vcn-adonai.id display_name = "subnet-app" dns_label = "app" security_list_ids = [oci_core_vcn.vcn-adonai.default_security_list_id] } resource "oci_core_subnet" "subnet-bd" { cidr_block = "10.1.1.0/24" compartment_id = var.compartment_ocid vcn_id = oci_core_vcn.vcn-adonai.id display_name = "subnet-bd" dns_label = "bd" security_list_ids = [oci_core_vcn.vcn-adonai.default_security_list_id] } data "oci_identity_availability_domain" "ad" { compartment_id = var.tenancy_ocid ad_number = 1 } |
Criação da Instance app1
A criação da VM eu faço no arquivo app1.tf esse passo não tem muitas particularidades, uma coisa que eu faço diferente é selecionar a opção de não associar um IP público na criação da VM (assign_public_ip=false), pois eu vou criar esse IP público no proximo passo e fazer a associação de forma manual.
Desta forma posso manter o IP quando for preciso recriar a VM, apenas precisa vincular o IP que ja existe com a nova VM.
Na criação da máquina precisa informar a sua chave pública para incluir no servidor que vai ser criado, sem isso não tem como logar no servidor após a sua criação.
Na criação da Instance eu já estou vinculando na interface dela dois Security Groups, um que vai liberar o acesso nas portas 80 e 443 e outro que vai liberar o acesso na porta 22.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
resource "oci_core_instance" "app1" { availability_domain = data.oci_identity_availability_domain.ad.name compartment_id = var.compartment_ocid display_name = "app1.adonai.eti.br" shape = "VM.Standard.E2.1.Micro" shape_config { ocpus = 1 memory_in_gbs = 1 } create_vnic_details { subnet_id = oci_core_subnet.subnet-app.id display_name = "vnic-app1" private_ip = "10.1.0.10" assign_public_ip = false assign_private_dns_record = true hostname_label = "app1" nsg_ids = [ oci_core_network_security_group.sg-webserver.id, oci_core_network_security_group.sg-sshserver.id ] } source_details { source_type = "image" source_id = "ocid1.image.oc1.ca-montreal-1.aaaaaaaa5cmqq5n5ld6djxw3xikonpvjtzsjrwnjfnlvevyjhnouwhlksxqa" boot_volume_size_in_gbs = "50" } metadata = { ssh_authorized_keys = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMjjFh/3OCG4V5Lwgmg5tKUGY8sZTOdQGWfHu0D+vSVI app1.adonai" } timeouts { create = "5m" } } output "instance_private_ip_app1" { value = [oci_core_instance.app1.private_ip] } |
Criação do IP Público
Como falei no passo anterior, agora vou criar o IP Público que vai ser vinculado com a VM que estou criando, no arquivo app1-public-ip.tf é criado o IP e ele é associado a primeira interface de rede que está vinculada a instancia app1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
resource "oci_core_public_ip" "ip-app1" { compartment_id = var.compartment_ocid display_name = "IP app1" lifetime = "RESERVED" private_ip_id = data.oci_core_private_ips.private_ips1.private_ips[0]["id"] } data "oci_core_vnic_attachments" "instance_vnics" { compartment_id = var.compartment_ocid availability_domain = data.oci_identity_availability_domain.ad.name instance_id = oci_core_instance.app1.id } data "oci_core_vnic" "instance_vnic1" { vnic_id = data.oci_core_vnic_attachments.instance_vnics.vnic_attachments[0]["vnic_id"] } data "oci_core_private_ips" "private_ips1" { vnic_id = data.oci_core_vnic.instance_vnic1.id } output "instance_public_ip_app1" { value = [oci_core_public_ip.ip-app1.ip_address] } |
Criação dos Security Groups para acesso http, https e ssh
Nessa etapa eu crio dois Security Groups, eu prefiro criar dois arquivos separados, um chamado sg-webserver.tf e o outro sg-sshserver.tf para facilitar a manutenção e a organização do código.
Primeiro é criado um security group com o nome de sg-webserver e duas security rules uma regra liberando o acesso na porta 80 e outra liberando o acesso na porta 443.
O segundo security group é criado com apenas uma security rule que vai liberar o acesso na porta 22.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
resource "oci_core_network_security_group" "sg-webserver" { compartment_id = var.compartment_ocid vcn_id = oci_core_vcn.vcn-adonai.id display_name = "sg-webserver" } resource "oci_core_network_security_group_security_rule" "rl-libera-http" { network_security_group_id = oci_core_network_security_group.sg-webserver.id direction = "INGRESS" protocol = "6" description = "Permite acesso http" source = "0.0.0.0/0" source_type = "CIDR_BLOCK" tcp_options { destination_port_range { min = 80 max = 80 } } } resource "oci_core_network_security_group_security_rule" "rl-libera-https"{ network_security_group_id = oci_core_network_security_group.sg-webserver.id direction = "INGRESS" protocol = "6" description = "Permite acesso https" source = "0.0.0.0/0" source_type = "CIDR_BLOCK" tcp_options { destination_port_range { min = 443 max = 443 } } } ################################################################################## resource "oci_core_network_security_group" "sg-sshserver" { compartment_id = var.compartment_ocid vcn_id = oci_core_vcn.vcn-iokah.id display_name = "sg-libera-acesso-ssh" } resource "oci_core_network_security_group_security_rule" "rl-libera-porta-9922"{ network_security_group_id = oci_core_network_security_group.sg-sshserver.id direction = "INGRESS" protocol = "6" description = "Permite acesso ssh na porta 9922" source = "0.0.0.0/0" source_type = "CIDR_BLOCK" tcp_options { destination_port_range { min = 22 max = 22 } } } |
Conclusão
Com a criação de todos esses objetos voce vai conseguir alocar um servidor totalmente configurado na Oracle Cloud, criando uma VCN para controlar o acesso e segmentar os seus servidores, com regras de firewall para permitir o acesso a cada máquina que for criada e com a reserva de um IP fixo que voce não vai perder a cada vez que precisar recriar a máquina.
Os arquivos que estou colocando aqui no post também estão publicados no meu repositório no Gitlab nesse endereço: https://gitlab.com/publicos-adonai/terraform-oracle-cloud
Se deseja ver outros posts sobre Infra-as-code acesse esse link: https://www.adonai.eti.br/category/infra-as-code/
Outros posts sobre Oracle Cloud acessem aqui: https://www.adonai.eti.br/category/oracle-cloud/