From 83be482e89c7291397cdf77efc9823c3f861780e Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Sun, 5 Sep 2021 20:26:27 +0200 Subject: Added oracle cloud article --- .../miscellaneous/getting_started_oci_free_tier.md | 201 +++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 content/blog/miscellaneous/getting_started_oci_free_tier.md (limited to 'content/blog') diff --git a/content/blog/miscellaneous/getting_started_oci_free_tier.md b/content/blog/miscellaneous/getting_started_oci_free_tier.md new file mode 100644 index 0000000..c629339 --- /dev/null +++ b/content/blog/miscellaneous/getting_started_oci_free_tier.md @@ -0,0 +1,201 @@ +--- +title: Getting started with Oracle Cloud Infrastructure +description: Oracle Cloud Infrastructure's always free tier is very generous +date: 2021-09-05 +tags: + - terraform +--- + +## Introduction + +Oracle Cloud Infrastructure provides quite a generous always free tier for you to use and test their cloud... or host some light services. But getting started was a little difficult with many pieces missing or incomplete in the examples, especially how to configure ipv6 on your instances. + +The documentation is very good and exhaustive but information was scattered : the following should help you get started right after you create your oracle cloud infrastructure's account. + +## Create your API access + +In order to terraform your infrastructure, you are going to need to generate an api access which is composed of a key and several other things : +- Open the web console, click the top left menu and select `Identity & Security` then `Users`. +- Click your account +- Scroll to bottom left and select `API Keys` +- click `Add an api key` +- Select `Generic API Key Pair`, download the private key file then click `Add` +- Copy the information displayed for the next phase + +## Terraform + +### Provider configuration + +Here is the relevant snippet from my `providers.tf` file : +```hcl +variable "oracle_tenancy_ocid" {} +variable "oracle_user_ocid" {} +variable "oracle_fingerprint" {} +provider "oci" { + tenancy_ocid = var.oracle_tenancy_ocid + user_ocid = var.oracle_user_ocid + fingerprint = var.oracle_fingerprint + private_key_path = "../tf-common/oracle_key.pem" + region = "eu-amsterdam-1" +} +variable "oracle_amd64_instances_names" {} +``` + +This goes along with a `terraform.tfvars` file that you should fill with the api access information you saved up earlier : +```hcl +oracle_tenancy_ocid = "XXXXX" +oracle_user_ocid = "YYYYY" +oracle_fingerprint = "ZZZZZ" + +oracle_amd64_instances_names = ["dalinar", "kaladin"] +``` + +The last bit is how I name the two free instances I want to create, pick anything you like. + +### Networking + +Here is how to bootstrap a vcn and the associated objects for direct internet access. For simplicity I will leave the access lists opened, firewall rules really are a pain to write with terraform... I plan to keep on using iptables or shorewall on the hosts for now. +```hcl +resource "oci_core_vcn" "adyxax" { + compartment_id = var.oracle_tenancy_ocid + cidr_blocks = ["10.0.0.0/16"] + display_name = "adyxax" + dns_label = "adyxax" + is_ipv6enabled = true +} +resource "oci_core_internet_gateway" "gw" { + compartment_id = var.oracle_tenancy_ocid + vcn_id = oci_core_vcn.adyxax.id + enabled = true + display_name = "gw" +} +resource "oci_core_route_table" "default-via-gw" { + compartment_id = var.oracle_tenancy_ocid + vcn_id = oci_core_vcn.adyxax.id + display_name = "default-via-gw" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.gw.id + } + route_rules { + destination = "::/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.gw.id + } +} +# protocol - Specify either all or an IPv4 protocol number : ICMP ("1"), TCP ("6"), UDP ("17"), and ICMPv6 ("58").ยท +resource "oci_core_security_list" "allow-all" { + compartment_id = var.oracle_tenancy_ocid + vcn_id = oci_core_vcn.adyxax.id + display_name = "allow-all" + + egress_security_rules { + protocol = "all" + destination = "0.0.0.0/0" + } + + ingress_security_rules { + protocol = "all" + source = "0.0.0.0/0" + } + + egress_security_rules { + protocol = "all" + destination = "::/0" + } + + ingress_security_rules { + protocol = "all" + source = "::/0" + } +} +resource "oci_core_subnet" "adyxax-production" { + cidr_block = cidrsubnet(oci_core_vcn.adyxax.cidr_blocks[0], 8, 0) + compartment_id = var.oracle_tenancy_ocid + vcn_id = oci_core_vcn.adyxax.id + + display_name = "production" + dns_label = "production" + ipv6cidr_block = cidrsubnet(oci_core_vcn.adyxax.ipv6cidr_blocks[0], 8, 0) + security_list_ids = [oci_core_security_list.allow-all.id] + route_table_id = oci_core_route_table.default-via-gw.id +} +``` + +### Instances + +Here is how to create the two always free tier instances. The tricky part was to understand how ipv6 addresses are like second class citizens on oracle cloud : +```hcl +data "oci_identity_availability_domains" "ads" { + compartment_id = var.oracle_tenancy_ocid +} +data "oci_identity_fault_domains" "fd" { + compartment_id = var.oracle_tenancy_ocid + availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name +} +# taken from https://docs.oracle.com/en-us/iaas/images/all/?search=Oracle-Linux-8.4 +data "oci_core_image" "ol8" { + image_id = "ocid1.image.oc1.eu-amsterdam-1.aaaaaaaaj46eslsa6ivgneyneypomtvzb6dmg22gtewy6opwiniuwgsdv7uq" +} + +resource "oci_core_instance" "amd64-vms" { + count = length(var.oracle_amd64_instances_names) + compartment_id = var.oracle_tenancy_ocid + availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name + fault_domain = data.oci_identity_fault_domains.fd.fault_domains[count.index % length(data.oci_identity_fault_domains.fd.fault_domains)].name + display_name = var.oracle_amd64_instances_names[count.index % length(var.oracle_amd64_instances_names)] + shape = "VM.Standard.E2.1.Micro" + preserve_boot_volume = true + create_vnic_details { + subnet_id = oci_core_subnet.adyxax-production.id + hostname_label = var.oracle_amd64_instances_names[count.index] + display_name = var.oracle_amd64_instances_names[count.index] + } + source_details { + boot_volume_size_in_gbs = 50 + source_type = "image" + source_id = data.oci_core_image.ol8.id + } + metadata = { + "ssh_authorized_keys" : "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILOJV391WFRYgCVA2plFB8W8sF9LfbzXZOrxqaOrrwco" + } +} +data "oci_core_vnic_attachments" "amd64-vms-vnics" { + count = length(var.oracle_amd64_instances_names) + compartment_id = var.oracle_tenancy_ocid + instance_id = oci_core_instance.amd64-vms[count.index].id +} +resource "oci_core_ipv6" "amd64-vms-ipv6s" { + count = length(var.oracle_amd64_instances_names) + vnic_id = data.oci_core_vnic_attachments.amd64-vms-vnics[count.index].vnic_attachments[0].vnic_id + display_name = var.oracle_amd64_instances_names[count.index] +} +``` + +### Bonus : Provisionning cloudflare's dns + +If like me you are managing your dns with cloudflare, here is how to provision the relevant records : +```hcl +resource "cloudflare_record" "adyxax-org-oracle-amd64-vms-ipv4" { + count = length(var.oracle_amd64_instances_names) + zone_id = lookup(data.cloudflare_zones.adyxax-org.zones[0], "id") + name = var.oracle_amd64_instances_names[count.index] + value = oci_core_instance.amd64-vms[count.index].public_ip + type = "A" + proxied = false +} +resource "cloudflare_record" "adyxax-org-oracle-amd64-vms-ipv6" { + count = length(var.oracle_amd64_instances_names) + zone_id = lookup(data.cloudflare_zones.adyxax-org.zones[0], "id") + name = var.oracle_amd64_instances_names[count.index] + value = oci_core_ipv6.amd64-vms-ipv6s[count.index].ip_address + type = "AAAA" + proxied = false +} +``` + +## Conclusion + +Putting all of this together was an interesting experience, and I am satisfied that it works well. In the future I plan to add my own oci image based on alpine linux which is not available natively. I tried oracle linux and it is fine, but consumes way too much ram for my taste. For now I installed alpine linux using the instance's cloud console and [my procedure for that]({{< ref "docs/alpine/remote_install_iso" >}}). -- cgit v1.2.3