Monthly Archives: October 2020

Terraform in OCI

What is Terraform

Terraform is an infrastructure as code software by HashiCorp.

It allows users to define a datacenter infrastructure in a high-level configuration language, from which it can create an execution plan to build the infrastructure.

Infrastructure is defined in a HCL Terraform syntax or JSON format.

Can be used with the following cloud providers. (This is not an all inclusive list.)

  • AWS
  • IBM Cloud
  • Google Cloud Platform
  • Microsoft Azure
  • Oracle Cloud Infrastructure

Example Provisioning of Linux Instance in OCI-Terraform

OCI Pre-requisites

  • IAM User
  • IAM API Fingerprint

Terraform Pre-requisites

  • Linux or other supported OS
  • Install Terraform and OCI-Provider

Set Environment

$ cat env-vars
# ####################################################################
# # Public/private keys used on the instance
# ####################################################################
export TF_VAR_ssh_public_key=$(cat /home/user/.ssh/my_opc_key.pub)
export TF_VAR_ssh_private_key=/home/user/.ssh/my_opc_key

# ####################################################################
# # Authentication
# ####################################################################
export TF_VAR_user_ocid="ocid1.user.oc1..xxxxxxxxxxx"
export TF_VAR_fingerprint="xxxxxxxxxxx"
export TF_VAR_private_key_path=/home/user/.ssh/my_api_key

Configure TF Files for Cloud Server Provisioning

In this example, an OL 7.5 VM will be provisioned.

$ ls -1
block.tf
compute.tf
datasources.tf
links.sh
outputs.tf
terraform.tfstate
userdata
variables.tf
vars-compartment.tf
vars-images.tf
vars-provider.tf
vars-region.tf
vars-ssh.tf
vars-subnets.tf
vars-tenancy.tf
vars-user.tf
vars-vcn-cidr.tf

The variables.tf is one the file that has the variable values will need to be set.
The other files contain the structure of the instance, where it is to be provisioned and the mappings for the variables being used.

$ cat variables.tf
# ######################################
# instance details
# ######################################
variable "AD" { default = "2" }
variable "privateIP" { default = "10.10.10.74" }
variable "subnet" { default = "SN2" }

variable "InstanceShape" { default = "VM.Standard2.1" }
variable "InstanceName" { default = "test01phx" }
variable "image_id" { default = "ol75-phoenix" }
# boot volume
variable "bv_size" { default = "100" }

# block volume
variable "BV1Name" { default = "test01phxBV1" }
variable "BV1Size" { default = "50" }

variable "BootStrapFile" { default = "./userdata/bootstrap" }

The variables.tf file above defines the following:

  • OL 7.5 operating system
  • Boot volume of 100G (the defualt is 50G)
  • A block volume of 50G
  • The contents of the bootstrap file will install the required packages to resize the boot volume.

In order to change the image version, subnet or other variable, please reference the vars*.tf files for the appropriate values.

Provisioning the Virtual Machine

Execute “terraform plan” to verify the tf files and the placement of the VM.

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.oci_identity_availability_domains.ADs: Refreshing state...

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
~ update in-place
<= read (data resources)

Terraform will perform the following actions:

~ data.oci_core_vnic.InstanceVnic
id: "" => <computed>
availability_domain: "" => <computed>
compartment_id: "" => <computed>
display_name: "" => <computed>
hostname_label: "" => <computed>
is_primary: "" => <computed>
mac_address: "" => <computed>
private_ip_address: "" => <computed>
public_ip_address: "" => <computed>
skip_source_dest_check: "" => <computed>
state: "" => <computed>
subnet_id: "" => <computed>
time_created: "" => <computed>
vnic_id: "" => "${lookup(data.oci_core_vnic_attachments.InstanceVnics.vnic_attachments[0],\"vnic_id\")}"

<= data.oci_core_vnic_attachments.InstanceVnics
id: <computed>
availability_domain: "PHX-AD-2"
compartment_id: "ocid1.compartment.oc1..xxxxxxxxxxx"
instance_id: "${oci_core_instance.TFInstance.id}"
vnic_attachments.#: <computed>

+ oci_core_instance.TFInstance
id: <computed>
availability_domain: "PHX-AD-2"
boot_volume_id: <computed>
compartment_id: "ocid1.compartment.oc1..xxxxxxxxxxx"
create_vnic_details.#: "1"
create_vnic_details.0.assign_public_ip: "false"
create_vnic_details.0.display_name: "primaryvnic"
create_vnic_details.0.hostname_label: "test01phx"
create_vnic_details.0.private_ip: "10.10.10.74"
create_vnic_details.0.skip_source_dest_check: <computed>
create_vnic_details.0.subnet_id: "ocid1.subnet.oc1.phx.xxxxxxxxxxx"
display_name: "test01phx"
image: <computed>
ipxe_script: <computed>
launch_mode: <computed>
launch_options.#: <computed>
metadata.%: "2"
metadata.ssh_authorized_keys: "ssh-rsaxxxxxxxxxxx"
metadata.user_data: "xxxxxxxxxxx"
private_ip: <computed>
public_ip: <computed>
region: <computed>
shape: "VM.Standard2.1"
source_details.#: "1"
source_details.0.boot_volume_size_in_gbs: "100"
source_details.0.source_id: "ocid1.image.oc1.phx.xxxxxxxxxxx"
source_details.0.source_type: "image"
state: <computed>
subnet_id: <computed>
time_created: <computed>

+ oci_core_volume.TFBlock1
id: <computed>
availability_domain: "PHX-AD-2"
compartment_id: "ocid1.compartment.oc1..xxxxxxxxxxx"
display_name: "test01phxBV1"
is_hydrated: <computed>
size_in_gbs: "50"
size_in_mbs: <computed>
source_details.#: <computed>
state: <computed>
time_created: <computed>
volume_backup_id: <computed>

+ oci_core_volume_attachment.TFBlock1Attach
id: <computed>
attachment_type: "iscsi"
availability_domain: <computed>
chap_secret: <computed>
chap_username: <computed>
compartment_id: "ocid1.compartment.oc1..xxxxxxxxxxx"
display_name: <computed>
instance_id: "${oci_core_instance.TFInstance.id}"
ipv4: <computed>
iqn: <computed>
is_read_only: <computed>
port: <computed>
state: <computed>
time_created: <computed>
use_chap: <computed>
volume_id: "${oci_core_volume.TFBlock1.id}"


Plan: 3 to add, 1 to change, 0 to destroy.

------------------------------------------------------------------------

Once verified all settings are correct, execute “terraform apply” to provision the VM.
The output will display the progress of the provisioning and it can also be viewed in the OCI console on the Instances page.

References

Terraform: https://www.terraform.io/
Terraform OCI-Provider: https://www.terraform.io/docs/providers/oci/index.html
Terraform/OCI-Provider GitHub: https://github.com/terraform-providers/terraform-provider-oci

Ansible in OCI – Oracle Cloud Infrastructure

Ansible is open source software that automates software provisioning, configuration management, and application deployment. Ansible connects via SSH, remote PowerShell or via other remote APIs.

In this example, I am using it to install and configure an OL7.5 VM after it was provisioned in OCI.

List the Servers to Configure

$ ansible-playbook generic-server-setup.yml --list-hosts
playbook: generic-server-setup.yml
play #1 (dr-others): dr-others TAGS: []
pattern: [u'dr-others']
hosts (1):
10.201.5.74

List the Tasks to Execute

$ ansible-playbook generic-server-setup.yml --list-tasks

playbook: generic-server-setup.yml

play #1 (dr-others): dr-others TAGS: []
tasks:
oci-console-user : create group TAGS: []
oci-console-user : create user TAGS: []
oci-console-user : create directory TAGS: []
oci-console-user : Set authorized key took from file TAGS: []
oci-console-user : common user alias TAGS: []
oci-console-user : set password TAGS: []
linux_rpms : install RPMs TAGS: [pkgs]
configure_sudoers : put entry in /etc/sudoers TAGS: [osuser]
create_linux_user : create group TAGS: [osuser]
create_linux_user : create user TAGS: [osuser]
create_linux_user : create directory TAGS: [osuser]
create_linux_user : Set authorized key took from file TAGS: [osuser]
create_linux_user : common user alias TAGS: [osuser]
create_linux_user : root alias TAGS: [osuser]
credential-rotation : show file TAGS: [osuser]
credential-rotation : display the result TAGS: [osuser]
credential-rotation : copy credential-rotation.sh TAGS: [osuser]
credential-rotation : run credential-rotation.sh TAGS: [osuser]
dns-disable-ipv6 : put entry in /etc/sysconfig/network TAGS: [dns]
dns-update-search-domains : touch /etc/dhcp/dhclient.conf TAGS: [dns]
dns-update-search-domains : put entry in /etc/dhcp/dhclient.conf TAGS: [dns]
dns-update-search-domains : Update search domains for Phoenix TAGS: [dns]
snmp-setup : put entry in /etc/snmp/snmpd.conf TAGS: [snmp]
snmp-setup : comment out entry in /etc/snmp/snmpd.conf TAGS: [snmp]
snmp-setup : comment out entry in /etc/snmp/snmpd.conf TAGS: [snmp]
snmp-setup : comment out entry in /etc/snmp/snmpd.conf TAGS: [snmp]
snmp-setup : Stop service snmp TAGS: [snmp]
snmp-setup : Start service snmp TAGS: [snmp]
snmp-setup : Enable service snmp TAGS: [snmp]
configure_iscsi : copy iscsiadd.sh TAGS: [iscsi]
configure_iscsi : put line in /etc/rc.local TAGS: [iscsi]
configure_iscsi : make /etc/rc.d/rc.local executable TAGS: [iscsi]
configure_iscsi : show lsblk TAGS: [iscsi]
configure_iscsi : display the disks TAGS: [iscsi]
configure_iscsi : attach the iscsi volumes TAGS: [iscsi]
configure_iscsi : show lsblk TAGS: [iscsi]
timezone : set timezone to {{ time_zone }} TAGS: [tz]
enable-display-back : X11DisplayOffset setting TAGS: [sshd]
enable-display-back : X11UseLocalhost setting TAGS: [sshd]
ntp_config : show file TAGS: [ntp]
ntp_config : display the result TAGS: [ntp]
ntp_config : install RPMs TAGS: [ntp]
ntp_config : copy update-ntp.sh TAGS: [ntp]
ntp_config : run update-ntp.sh TAGS: [ntp]
ntp_config : put entry in /etc/ntp.conf TAGS: [ntp]
ntp_config : put entry in /etc/ntp.conf TAGS: [ntp]
ntp_config : put entry in /etc/ntp.conf TAGS: [ntp]
ntp_config : put entry in /etc/ntp.conf TAGS: [ntp]
ntp_config : put entry in /etc/ntp.conf TAGS: [ntp]
ntp_config : start and enable the NTP service on OL6 TAGS: [ntp]
ntp_config : start and enable the NTP service on OL7 TAGS: [ntp]
ntp_config : stop and disable the chronyd service TAGS: [ntp]
ntp_config : display the ntpq output TAGS: [ntp]
ntp_config : display the result TAGS: [ntp]
reboot_vm : reboot VM TAGS: [reboot_vm]
set_fact TAGS: [reboot_vm]
reboot_vm : wait for server to come down TAGS: [reboot_vm]
reboot_vm : wait for server to come back up TAGS: [reboot_vm]

Run the Ansible playbook

Here is the beginning of the playbook run.

… and here is the end of the playbook run.

Note the ntp_config has “if” logic for different OS version.

Ansible is a versatile tool and easily allows you to automate the configuration of cloud VMs.

GDS – Global Data Services

Oracle GDS provides the following key capabilities for a set of replicated databases that are globally distributed or located within the same data center.

I implemented this architectural solution for a large financial company to meet their 99.99% SLA database uptime requirements.

Here is a short video showing a Java script using UCP connecting through GDS to two backend Oracle databases.

As an example the video below depicts how we used gdsctl to relocate the Oracle service to the other database and the Java script will also flip over with FAN events that via UCP connections. The end result … connections automatically continue on the surviving database automatically.