Should I use tags in Oracle Cloud Infrastructure?

In Oracle Cloud Infrastructure you have two options to tag your resources, defined tags which are setup by your administrator or free form tags which can be applied by any user who has access to a resource.

So why should you tag resources?

In my opinion when you start your OCI project this is definitely a concept which you shouldn’t overlook! Even though you can separate your resources in different compartments everyone should setup set of pre-defined tags which are applied to resources.

With this you can list and organize resources lot easier and perhaps also later on do tag-based billing? It’s an easy step to overlook and definitely not the most attractive one so that’s why I wanted to highlight this in a post.

I’d even go as far as saying having a tag strategy is critical for your cloud operations in the long run.

Free form tagging

With free form tagging you just select your resource and enter a key value pair what you want to apply.


Adding a free form tag to a resource

Free form tags give a lot of freedom and you can just use them as you like but it’s better to start using defined tags as then you can standardize tagging used within the compartment.

Defined tags

As written earlier these are predefined tags what you can assign to specific compartment so users who have access resources under that compartment can tag them.

Defined tags you find under Menu => Governance => Tag Namespaces

First you need to select your compartment and then click the Create Namespace Definition. I will create namespace resource-tags under my OracleEBS compartment.

Don’t be fooled to add tags here unless you want to tag your tag namespace!

After creating the namespace definition you can add the actual tags into it. I’ve added two tags to my namespace. Tags for owner and environment.


Now the tags are ready to be used. If I create an instance in Oracle-EBS compartment I can choose the tag namespace I created and then define the tags for owner and environment.


The problem I see is that even though I have a tag namespace with multiple tags I can’t force that they are used. If we have defined five tags what should be used within a namespace, user can still choose only one tag and leave rest of them blank.

That’s why its good to use Terraform to create your instances. You can have module ready for instance creation and in the Terraform template you have tags defined in the variables file.


I wrote a simple module which creates the namespace and also tags for the namespace from the list. That way you can create as many tags per namespace you want and the module will loop it through. The module looks like this:

variable "tenancy_ocid" {}
variable "compartment_ocid" {}
variable "tag_namespace_description" {}
variable "tag_namespace_name" {}
variable "is_retired" {}
variable "tag_names" {type = "list"}
variable "tag_description" {type = "list"}

resource "oci_identity_tag_namespace" "CreateTagNamespace" {

    compartment_id = "${var.compartment_ocid}"
    description = "${var.tag_namespace_description}"
    name = "${var.tag_namespace_name}"
    is_retired = "${var.is_retired}"


resource "oci_identity_tag" "CreateTag" {

    count = "${length(var.tag_names)}"
    description = "${var.tag_description[count.index]}"
    name = "${var.tag_names[count.index]}"
    tag_namespace_id = "${}"
    is_retired = false


Only thing to highlight are two variables coming in as a list and then using the count under resource to loop variables through. I had four tags in my which then got created within this single module. Quite handy!

Next if I want to use tags in the instance creation I will just add variable as per documentation:

defined_tags = {"Operations.CostCenter"= "42"}

To pass this as a variable you should have it defined in your as a map:

variable "project-tag" {
default = {project-tags.costcenter = "42"}

And in the module which creates instance I take the variable as map also and then use the defined_tags to assign it:

variable "project_tag" {type = "map"}
resource "oci_core_instance" "CreateInstance" {
    count = "${var.server_count}"
    availability_domain = "${var.instance_availability_domain}"
    compartment_id = "${var.compartment_ocid}"
    image = "${var.image_id}"
    shape = "${var.instance_shape}"
    defined_tags = "${var.project_tag}"

When I now create instances through Terraform I can see the defined tag I assigned is applied.


And if there is need to apply more defined tags you can easily pass them in the map which you define in


Like I wrote earlier you can’t force tags. This would be good so there wouldn’t exist resources without tags you want to use. However using Terraform gives you a better control to manage what variables are requires when you create a resource.

Remember you can’t delete a namespace, you can only retire a namespace including tags so it’s not used anymore.

Also once you have created tags you can then filter resources based on the tag.


At the moment you can only add tags and filter your resources based on tag but hopefully in the long run you can also use them for cost distribution. Having compartments available gives you already flexibility on IAM so you can easily control access with them and don’t need tags for that.

I highly recommend that you take tags into use right from the start as you will need them to group your resources and perhaps you get some advantages in the future as well if you have proper tag setup!



Oracle Cloud Infrastructure Service Gateway

Recently Oracle announced Service Gateway for Oracle Cloud Infrastructure (OCI). One of the problematic areas what I have found with OCI is that if you use Object Storage for example for your database backups you have been required to have public internet access from your OCI subnets either by placing instance to public subnet or using a NAT instance between.

Service Gateway is going to change this as now you can access object storage through your private subnet by setting the route rule towards service gateway only without need to access public internet.

This is great news! I wanted to try this out with below example.

Creating and testing Service Gateway

For this example I had created following:

  • VCN with a private subnet
  • Empty routing table
  • Empty security list
  • One instance in the private subnet with oci-cli installed
  • A bucket in object storage

Below are instance and private subnet details.

Instance is created in the Suomenlinna compartment without public IP address


Private subnet with own Routetable and a securitylist

First I will need to create the Service Gateway under Networking => My Test VCN and selecting Service Gateway from the left.

To create SGW just select compartment, a name for SGW and the services available. Currently only ObjectStorage service is available.
After creation SGW shows up available almost immediately.

After creating the Service Gateway I now need to create a route rule on my routing table for the private subnet. If you’ve done some VCN configuration earlier this is no different than selecting an Internet Gateway for your public subnet.

When configuring the route rule you select target type as Service Gateway and define destination service, compartment and select the SGW you created in earlier step.

So now when we have the routing in place we are ready to test!

I’m logged into my OCI instance in the private subnet (by using a jump server in between). I will use oci-cli to list my buckets in the Suomenlinna compartment.

[opc@instance-20180627-1115 ~]$ oci os bucket list --compartment-id ocid1.compartment.oc1..aaaaaaaafidv5tggg5lxxeb4tf35nkjyl5z4ehdauiiwgk4zhetoq2uehl7a
"code": "NamespaceNotFound",
"message": "You do not have authorization to perform this request, or the requested resource could not be found.",
"opc-request-id": "07178F60467D445ABCB891E721B44A20",
"status": 404

What! Something is missing?

Remember always to configure also security lists as by default everything is denied. Accessing Object Storage is no different.

I will just make necessary change to my security list as shown below.


Time for a new try!

[opc@instance-20180627-1115 ~]$ oci os bucket list --compartment-id ocid1.compartment.oc1..aaaaaaaafidv5tggg5lxxeb4tf35nkjyl5z4ehdauiiwgk4zhetoq2uehl7a
"data": [
"compartment-id": "ocid1.compartment.oc1..aaaaaaaafidv5tggg5lxxeb4tf35nkjyl5z4ehdauiiwgk4zhetoq2uehl7a",
"created-by": "ocid1.saml2idp.oc1..aaaaaaaab6mng7jcan6vncjxehd6mkhlobzm4redvlthq2l4nhmqrow7hnza/",
"defined-tags": null,
"etag": "62809e66-083e-453e-bc78-916a54dc84a1",
"freeform-tags": null,
"name": "test-bucket",
"namespace": "simo",
"time-created": "2018-06-25T07:18:23.919000+00:00"

Working, now I can see my test-bucket on my namespace!


Service Gateway is really good addition to basic functionality you need with OCI. I think for a lot of people having a necessity to use public internet for your database backups could have been an issue.

Next service I’m waiting which would be required is a NAT Gateway service so you wouldn’t need to create your own NAT instances in the public subnet like you have to do today.

Create multiple instances with one Terraform module in Oracle Cloud Infrastructure

Since I’ve become a big fan of modules a case where you might need them is by creating multiple instances at the same time for your Terraform project.

One option is that you have the main Terraform project and call the modules from projects file multiple times like this:

module “CreatePublicInstance1” {
module “CreatePublicInstance2” {
module “CreatePublicInstance3” {
But there is other option where you use the count variable in a resource. You can easily scale the amount of resources by providing the count parameter to the module and it will loop the resource as many times you have defined.
Note that at this time there are some limitations with count – it can not be a value from other module but rather you need to define it as a static variable.

Terraform project for creating instances

Again I have three files in my Terraform project named “Create_three_instances”. The files are:


Let’s take a look of them.

In the I have defined the necessary variables for this project. In this case when I’m creating instances I have some variables pointing to existing resources related to compartment, network and instance image/shape. These are required as in the I will need to get existing OCID’s for subnets, ADs etc. I have also defined a variable server_count which is the amount of servers I want to create in this example.

In the I get existing data by using the variables.


As you can see I first get the compartment information by passing tenancy_ocid and filter the result by compartment name. After that I use the compartment OCID to get Availability Domains and VCNs.

With compartment and VCN OCID I get the subnet information and limit the result with the subnet name. Lookups are very easy to use to get already existing data created by my network project earlier!

Next I call the actual module which creates the instances.


Calling this module I pass the server_count variable, some data through lookups which are required and also some static variables which were defined in the

One additional thing to note is the instance_create_vnic_details_private_ip. As you can see I actually pass the cidr_block of the subnet. Why? You will see when the actual module is being used.

Finally in the I will just print out the instance name, public and private IPs.


Using count when creating the resource

Now by looking the actual resource “oci_core_instance” “CreateInstance” you can see the usage of the count.


I pass the server_count variable to count in the start of the resource and this determines how many times the create resource will be looped through.

As you might want to or you have to separate the naming for some resources I’ve used  ${count.index} in some places to have separation without creating a list of variables in the project’s In my opinion list might hard to keep updated and by using the numbering you can still have different naming.

If you take a look on the private_ip variable you see now the usage of the subnet cidr block I mentioned earlier. I use built-in function cidrhost to give specific private IP addresses for each host. You could let OCI to allocate those automatically but in some cases you want to define them.

Definition of cidrhost is as follows:

cidrhost(iprange, hostnum) – Takes an IP address range in CIDR notation and creates an IP address with the given host number. If given host number is negative, the count starts from the end of the range. For example, cidrhost(“”, 2) returns and cidrhost(“”, -2) returns

Reason why I have +3 in the end is that Oracle reserves two first IP addresses in the start of every subnet so the first instance will receive .3 IP address and continue to grow from there.

I also have in the module. There I need to use splat syntax (*) to send the list out.

output “instancePublicIP” {value = [“${oci_core_instance.CreateInstance.*.public_ip}”]}

Creating the resources

Now when I’m ready to create the resource I will run the usual terraform init, plan and apply. If you want to know more about those check my earlier blog post and video from here.

When I run terraform plan it will show that it will create three new resources:

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

That matches the server_count variable. Once I’ve executed apply the outputs for the instances are:

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.


instanceName = [
instancePrivateIP = [,,
instancePublicIP = [


Here is video also showing the exact same thing as above. You can see the code as well as running the Terraform project.


When you use Terraform modules the main goal would be to make easily repeatable code for your infrastructure. As Terraform isn’t always so flexible to different cases using count is one way to scale your resources up based on the need.

Lot of valuable information about Terraform I’ve got and used also here is from Yevgeniy Brikman’s book Terraform: Up and Running: Writing Infrastructure as CodeDefinitely buy it if you are interested to learn more!

Create DB system to Oracle Cloud Infrastructure with Terraform

One of the most important areas with Oracle Cloud Infrastructure is that you can utilize Oracle databases easily as part of your infrastructure. There are different options how you can provision the databases but as Terraform is the supported orchestration tool with OCI you should investigate if using it is feasible for your project.

This way all the databases created in your tenancy will be done through Terraform in the same way specially if you utilize Terraform modules which are sort of pre-build parts which are written for standard operations. When different “projects” utilize those modules they always call them in the same way and there is no need to write them again each time.

In this post I’ll share simple way of creating the module and using it to create a database.

Basics of DB systems in OCI

In OCI you have different options for your DB system. It can run either on VM, BM or Exadata instance. For each there are variety of different shapes available in terms of CPU, Memory, storage available etc. (And different Exadata shapes obviously)

For VMs you can create 2-node RAC configuration.

Database editions which are available:

  • Standard Edition
  • Enterprise Edition
  • Enterprise Edition – High Performance
  • Enterprise Edition – Extreme Performance (required for 2-node RAC DB systems)

And currently supported DB versions:

  • Oracle Database 18c Release 1 (18.1)
  • Oracle Database 12c Release 2 (12.2)
  • Oracle Database 12c Release 1 (12.1)
  • Oracle Database 11g Release 2 (11.2)

For licensing you have the option either to bring your own license (BYOL) or have the license included. This reflects in the cost of your system.

One important thing to remember is that the database is deployed into public subnet. You don’t need to define Internet Gateway but the database system requires public subnet. I would imagine some people don’t like this idea so much even though you can limit the access completely from outside.

Whole DB service documentation can be found from here.

Terraform setup

I’ve placed necessary Terraform files inside two folders. The module folder is named“database” and inside it I have two files:

  • – this one has code which calls resource oci_database_db_system to create the DB system
  • – this one sends variables out that I want

The project folder is named “create_db_system”  and it has three files inside.

  • – this one gets necessary data from different sources and calls database module by passing different variables which are specific to this case
  • – all the custom variables defined in this file
  • – outputs which I want to print after successfully running Terraform

Terraform module

Setting up the database module is fairly straightforward. Good example case can be found from OCI Terraform documentation here.

Note that the required parameter for resource oci_database_db_system data_storage_size_in_gb is named elsewhere as data_storage_size_in_gbbut seems correct way of calling it is without the s.

I’ve used the module so that I don’t do any data gathering inside the module but rather pass only “ready” variables into it.

My resource looks like this:


resource "oci_database_db_system" "CreateDBSystem" {


    availability_domain = "${var.db_system_availability_domain}"

    compartment_id = "${var.compartment_id}"

    cpu_core_count = "${var.db_system_cpu_core_count}"

    database_edition = "${var.db_system_database_edition}"

    db_home {


        database {


            admin_password = "${var.db_system_db_home_database_admin_password}"

            db_name = "${var.db_system_db_home_database_db_name}"

            character_set = "${var.db_system_db_home_database_character_set}"

            db_backup_config {

            ncharacter_set = "${var.db_system_db_home_database_ncharacter_set}"

            pdb_name = "${var.db_system_db_home_database_pdb_name}"


        db_version = "${var.db_system_db_home_db_version}"


        display_name = "${var.db_system_db_home_display_name}"



    shape = "${var.db_system_shape}"

    ssh_public_keys = ["${var.ssh_public_key}"]

    subnet_id = "${var.db_subnet_id}"

    data_storage_percentage = "${var.db_system_data_storage_percentage}"

    data_storage_size_in_gb = "${var.db_system_data_storage_size_in_gbs}" #For VMs only

    license_model = "${var.db_system_license_model}"

    node_count = "${var.db_system_node_count}"


Terraform project

For the project itself I’ve defined all the necessary variables inside – either these variables are passed to database module or I use them to get specific OCID’s what I require further on.

You define default variable like this:

variable “compartment_display_name” {default = “PrivDBCompartment”}

In the I fetch data using variables like here to get the compartment data:


data "oci_identity_compartments" "GetCompartments" {

#Required - tenancy OCID

  compartment_id = "${var.tenancy_ocid}"



values= ["${var.compartment_display_name}"]



This one is bit misleading as I pass tenancy OCID as compartment_id to get filtered list of available compartments.

The compartment is then used to get specific DB subnet I want to use for the DB system:


data "oci_core_subnets" "GetDBSubnet" {


  compartment_id = "${lookup(data.oci_identity_compartments.GetCompartments.compartments[0],"id")}"



To understand what variables you need to pass to get list of subnets you can see the documentation example. Same applies to all other list requests, check the documentation!


To use the data you then use lookups to get specific values you want. I didn’t understand this in the start how it works but all available variables can be seen from documentation and then you can just use it like above to get required variables for availability domains etc.

Another good example how to use lookup is to have the necessary db_system_availability_domain variable defined from above GetDBSubnet:


db_system_availability_domain = 


I’ve defined the GetDBSubnet earlier and now I just fetch the availability_domain the subnet belongs to. This way you can get all the variables related to some specific resource.

From the still few settings to point out to this exercise:

“db_system_database_edition” {default = “ENTERPRISE_EDITION”}
“db_system_db_home_db_version” {default = “”}
“db_system_shape” {default = “VM.Standard2.1”}
“db_system_license_model” {default = “LICENSE_INCLUDED”}

My database will be a VM 2.1 shape with Enterprise Edition database with license included option.

Creating the Database system

Now I’m ready to create the DB system. As usual I will run first terraform init to initialize the modules and the OCI provider for terraform.

After that I will run terraform plan to see what changes will be applied and this time I will have only 1 change to add. I’ve created compartment with network already earlier using different terraform project.

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

After that I will run terraform apply to do the actual changes. Creating the database took around 70 minutes in total with my configuration.

module.cr_private_db.oci_database_db_system.CreateDBSystem: Creation complete after 1h12m42s (ID:…34qsdaozzgyb254hnr7w6nlkpaz7tshpfdy2oa)

Since I’ve set my ssh keys I can login to the DB system by providing my private key with opc user. If I look pmon processes:

[oracle@hostsimo dbhome_1]$ ps -ef|grep pmon|grep oracle
oracle 65038 47622 0 08:38 pts/0 00:00:00 grep pmon
oracle 76130 1 0 08:13 ? 00:00:00 ora_pmon_SIMO1

Besides grid ASM there is my database now also running.



Thing to remember is that if you want to allow connections to listener port modify your security lists to allow traffic! This should be part of your network setup.

After the test I’ll run terraform destroy to remove the database and that completes in bit over 7 minutes.

module.cr_private_db.oci_database_db_system.CreateDBSystem: Destruction complete after 7m19s



You can easily automatize your database creation through Terraform modules. Initial module setup takes some time so that you figure out the parameters you need but once that is done you get all your databases created in standardized way!

This was a simple example but for real world cases modules will be more complex and will require more work obviously.

Deep dive into OCI with compartments, users, groups and policies

I’ve said it before and I’ll state it once more. One of the best services with Oracle Cloud Infrastructure is Identity & Access Management. Oracle has made managing your tenancy really easy with compartments and policies.

With compartments you can manage your single account without too much of complexity by restricting user access to specific compartments and giving only access for users inside that compartment.

For example you have a user who can only use network resources in a compartment so the user can launch new instances. This way you leave administration of network components to your OCI network admins.

IAM documentation can be found from here. It’s a very well structured documentation so I would give it a read when you start working with OCI IAM.


Policies are what define who can access resource in a specific way at a group or compartment level. You always allow with your policies and never deny as by default OCI access is defined by least privilege so if something isn’t allowed it is denied. There are four level of access:

  • Inspect – you can list resources but not get the metadata or any confidential information (with network resources you still get all information!)
  • Read – Same as Inspect but you get also the metadata and the resource itself
  • Use – Includes read but has the ability so you can use the resource which varies by resource type. Includes also update of the resource apart from when update is the same as create (Updating security list for example)
  • Manage – Includes all permissions to resource

Policy syntax is as follows:

Allow <subject> to <verb> <resource-type> in <location> where <conditions>

Which translates to:

Allow group network-admins to manage virtual-network-family in tenancy

Or if you would like to give compartment level network admin access to network components only:

Allow group projectx-network-admins to manage virtual-network-family in 
compartment ProjectX

Some resources such as users and groups are managed on tenancy level.

I’ve used a resource example which is type of a “family”. This has all related resources combined inside so you don’t need to go and allow access one by one to all network resources. Advantage is that if Oracle adds more components to network resources these will be automatically added to “family” and you don’t need to go and specify them.

But if you wan’t to give access only to individual resource-type this is certainly possible! Just be careful it doesn’t come too much of work in the long run. Policy reference with family resource-types are listed here.

So what if you have more requirements – for example you want to limit group access only to modify specific compartments. This is possible with conditions.

Online documentation says this about them:


Specify one or more conditions. Use any or all with multiple conditions for a logical OR or AND, respectively.

Syntax for a single condition: variable =|!= value

Syntax for multiple conditions: any|all {<condition>,<condition>,...}


Condition variable is always either relevant to the request itself or relevant on the resource which is being accessed. This comes always with a prefix of a request or a target.

You want to limit your group admins to be able to modify anything but the Admin group (example from Online documentation):

Allow group GroupAdmins to use users in tenancy where != 

And if you want to limit group access on specific resource-types you can use(example from Online documentation):

Allow group XYZ to manage groups in tenancy
 where any {request.permission='GROUP_INSPECT',

Normally when you grant the manage groups permission it has one additional individual resource-type: GROUP_DELETE. Now when you limit the permission not to include it then group XYZ does not have access to delete groups.

In conditions you can also use either string with single-quotes or a pattern match. Pattern match is used as /*OCI*/, /*OCI/ or /OCI*/.

Example case

Now for a typical case what might come up. Company has two or more different applications and you don’t want users to access other resources apart from what they should. In my case I will have Oracle EBS and Oracle BI as example applications. I want to have network admin group which manages networks in all compartments and admin groups for each different compartments with specific policies.

In addition I will have group for user management. Each group will have one user assigned.

Compartment example
This is what compartment, group and user layout will look like

Group policies what I will give are as follows.

For Network-Admins:

Allow group Network-Admins to manage virtual-network-family in tenancy

For User-Management:

Allow group User-Management to manage users in tenancy
Allow group User-Management to manage groups in tenancy

For Oracle-BI-Admin:

Allow group Oracle-BI-Admin to manage instance-family in 
compartment Oracle-BI

Allow group Oracle-BI-Admin to use virtual-network-family in 
compartment Oracle-BI

Allow group Oracle-BI-Admin to manage volume-family in 
compartment Oracle-BI

Allow group Oracle-BI-Admin to manage database-family in 
compartment Oracle-BI

For Oracle-EBS-Admin:

Allow group Oracle-EBS-Admin to manage instance-family in 
compartment Oracle-EBS

Allow group Oracle-EBS-Admin to use virtual-network-family in 
compartment Oracle-EBS

Allow group Oracle-EBS-Admin to manage volume-family in 
compartment Oracle-EBS

Allow group Oracle-EBS-Admin to manage database-family in
compartment Oracle-EBS

Allow group Oracle-EBS-Admin to manage file-family in
compartment Oracle-EBS

I’m giving quite wide permissions for both admins here. If you would like to you could always limit the access so users can’t create volumes but just use existing one for attaching etc. It depends on your use case!

Also both compartment admins get access to manage database-family. It might be that for some reason you wouldn’t want to create database through service but install it yourself. Then you wouldn’t need the database-family policy.

Group Oracle-EBS-Admin gets also policy to manage file-family. This is really good service for EBS customers as you can create the shared APPL_TOP mounts through file-family and then just mount on servers where you need to have it.

Deploying the compartment layout with Terraform

If you want you can always create everything manually with OCI. But I want to use automation and infrastructure as code so I will use Terraform to deploy these to my OCI tenancy.

With Terraform I have four different modules in their respective folders and one main folder which calls these reusable modules. Main folder has also variables defined specific for this case. So as an example when I create users I call the same module like this:


Few important things to remember. When you make policy statement variables they are passed as a list. So the variable will look like:


Remember to define type as a list in the module:

variable “statements” {type = “list”}


Also right now the modules I have are: “create users”, “create compartments”, “create groups with policy” and “create group relationship with user”.

I used to have separate modules for groups and policies but noticed that sometimes Terrafrom dependency didn’t work as expected even though I was passing some variables from group module to policy module.

To my understanding Terraform should then wait the referenced resource to be created first. To have a workaround I put both resources under same module which was a good and simple solution in this case.

Now I will just run familiar Terraform commands terraform init, terraform plan and finally terraform apply.

My example created total of 22 OCI resources:

Apply complete! Resources: 22 added, 0 changed, 0 destroyed.

And if I just check from the console I can see everything is there as required. Below you can see compartments and policies created.



In this post I wanted to show how easy it is to deploy base layout for your operations. You can start small and then think what kind of policies are required for users and how to have them setup in a most efficient way.

Unless there is a real requirement I wouldn’t want to make whole setup too complicated. On the other hand giving a wide access to all users could create some other issues in your setup.

Oracle Cloud Infrastructure Architect certification review

Earlier this week I took the Oracle Cloud Infrastructure (OCI) Architect Associate certification 1Z0-932 which I had been studying for few months while using OCI at the same time. Glad to say I passed it with good score to leave me happy on the effort!

As the certification is quite new there isn’t a lot out there what you should focus on while studying. Oracle has put out the exam topics here. As you can see it lists most of the services related to OCI and how you should be familiar with those.

In my study I wanted to focus on few specific areas – getting idea on how the overall network services work with OCI , Database service and also Identity and Access Managent (IAM). Now after the test I’d say this was a good approach. You really should know the network components inside out and get idea on how to build high availability solutions. Understand what difference you have with public and private subnets and how you can access different components from subnets and how you setup load balancers for high availability.

On the Database service you want to understand what types of service you can use and how the backups and restores are handled. Databases are still Oracle’s core offering so obviously a lot of questions are from this area.

With IAM once you get the concept of policies, compartments and groups learning it comes quite easy. This is different compared to AWS IAM and is one of the best features of OCI so learn it!

I had also gotten quite familiar with Terraform and this was reoccurring topic in the exam. It’s good Oracle tries to get you focusing on infrastructure as code and automation as that should be at least considered in each OCI project as a possibility.

Each OCI service was covered in the exam so remember to study all of them! During studying I used the youtube videos of OCI fundamentals by Oracle and read the Online Documentation few times through.

I’d suggest also creating free account for OCI which gives you 30 days time to test things while you are studying. Using the services and console you get the idea how you can create resources and what is needed when you create each resource.

If I compare OCI and AWS Solution Architect certifications then AWS understandably has wider range of services what you need to learn but both concentrate on similar topics so studying for one gives you a good basis for another! AWS certifications I did earlier this year definitely helped on the network concepts.

Hope this helps you on your study!

Using Oracle Cloud Infrastructure with Terraform modules

When I started to use Terraform I quickly adapted on concept of using modules with it. Why?

Because in my opinion the more you can automate and standardize the easier overall management of your solution becomes.

So what are modules and why should I use them? I made a short video presentation on creating infrastructure using Terraform modules. If you have time to check it it’s right here!


Leave me some feedback if you liked the video and if you would like to see similar videos on Terraform or OCI in the future.

As promised some links which I mention in my presentation:

Oracle Cloud Infrastructure documentation:

Oracle Cloud Infrastructure fundamentals playlist(this is really good!):

Terraform and downloads:

Terraform OCI provider:

Terraform OCI documentation (again really useful!):

Accenture OCI performance study: