0% found this document useful (0 votes)
380 views

1automating Oracle Database Administration Practical Examples With Ansible Ilmar Kerm PDF

Uploaded by

Vusi Mazibuko
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
380 views

1automating Oracle Database Administration Practical Examples With Ansible Ilmar Kerm PDF

Uploaded by

Vusi Mazibuko
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

Automating Oracle database administration, practical

examples with Ansible


Mikael Sandström / Ilmar Kerm
@oravirt
@ilmarkerm
Kindred in Numbers All numbers from Q4 2017

GWR: Ebitda: Customers: Daily transactions:

£238m £75m 20m 16-18m


GWR from locally regulated markets: GWR from mobile:

42% 70%
Employees: Offices: Nationalities: Brands:

1,400 15 52 11
Our A portfolio of
brands within

brands
sportsbook,
casino and
games
© Kindred Group plc 2017

Where we operate

Our Offices Our Licenses


Stockholm | Copenhagen | Tallinn | Antwerp | Sydney Australia | Belgium | Denmark | Estonia | France | Germany
London | Paris | Milan | Gibraltar | Malta | Darwin Gibraltar | Ireland | Italy | Malta | Romania | United Kingdom
WHOAMI: Ilmar Kerm

• Senior database administrator in Kindred Group


• Working in IT since 2000
• Working with Oracle database since 2003
• Working at Kindred since 2007/2015
• From LAMP developer to Oracle DBA
• Oracle ACE

Blog: https://ilmarkerm.eu
Email: [email protected]
Twitter: @ilmarkerm
WHOAMI: Mikael Sandström

• Senior database administrator at Kindred Group


• Worked with Oracle for a long time
• Working at Kindred since early 2016
• Automation junkie

Blog: https://oravirt.wordpress.com
Email: [email protected]
Twitter: @oravirt
Ansible for Oracle use cases
• Easy
‒ Setting up database environment infrastructure, OS
‒ Installation of RDBMS software
‒ Automation of routine OS tasks
• Medium
‒ Push of the button datacenter deployment
‒ Initial creation of databases, pushing out initial configuration
‒ Automation of routine DBA tasks: patching, creating tablespaces, …
‒ One time tasks needing high level of orchestration – upgrades, …
‒ Implementing missing features from Oracle
‒ Enforcing common security settings
• Advanced
‒ All database configuration and changes deployed as version controlled code
‒ Easy to review and audit, repeatable
Agenda
• We expect that you are familiar with Ansible
• Things we cover
‒ Setting up Ansible environment for Oracle DB use: inventory, modules, cxOracle
‒ Handling Ansible inventory for database usage
‒ Creating/managing users and roles, syncing with Active Directory
‒ Services, tablespaces, resource manager, DBMS_SCHEDULER, AWR settings, INIT.ORA
parameters, ASM diskgroups
‒ User privileges, including grants to entire target schema
‒ Gathering facts about databases
‒ Managing passwords in playbooks
‒ Practical playbook deployment: execution, scheduling, configuration
• Things we do not cover, because every other Ansible presentation does these
‒ What is Ansible (check the first bullet point)
‒ Managing OS
‒ Installing Oracle RDBMS/Grid software
‒ Creating databases/clusters (we will create PDBs though)
Introducing Oracle modules for Ansible
• Modules for administering Oracle database infrastructure
• Hosted in Github
‒ https://github.com/oravirt/ansible-oracle-modules
• Currently not part of Ansible standard modules
‒ Work in progress
• Written in Python
• Require cx_Oracle
‒ Needed where the modules are executed
‒ cx_Oracle needs an Oracle client
‒ If run locally on ‘control-machine’ Instant Client is fine, otherwise just install on
the database host
‒ pip or yum/rpm
Introducing Oracle modules for Ansible
• Currently manages:
‒ Users and roles, including synchronization from AD/LDAP
‒ Grants: system and object privileges, including wildcards
‒ Tablespaces
‒ Parameters
‒ Services
‒ ASM diskgroups and volumes
‒ Pluggable databases
‒ DBMS_SCHEDULER jobs, windows and schedules
‒ Resource manager consumer groups, including mappings by user profile
‒ AWR snapshot settings
• Helper modules:
‒ Gathering database facts
‒ Executing SQL
Setting up – playbook structure
|____ansible.cfg | | |____tasks
|____site.yml | | | |____main.yml
|____build-host.yml | | |____templates
|____db-config.yml | | | |____oracle-seclimits.conf.j2
|____group_vars | |____oracle-asm-diskgroups
git clone https://github.com/oravirt/ansible-oracle-modules library
| |____doag | | |____defaults
| | |____doag.yml | | | |____main.yml
| | |____passwords.yml | | |____tasks
|____library | | | |____main.yml
| |____oracle_asmdg
| |____oracle-database
| |____oracle_awr
| | |____defaults
| |____oracle_facts
| | | |____main.yml
| |____oracle_ldapuser
| | |____tasks
| |____oracle_parameter
| | | |____main.yml
| |____...
| | |____templates
|____roles
| | | |____dbca.rsp.j2
| |____host | | | |____netca.rsp.j2
| | |____defaults
| | | |____main.yml
Ansible inventory
• Inventory describes for Ansible where the servers are
• Inventory only describes hosts
• Hosts can be divided into groups
• NB! Hosts may not exactly map into databases
Inventory and databases [Potential problem]
• One config file per db
group_vars/db1

- Inventory
[db1]
host1.example.com

ansible-playbook dbconfig.yml –e db=db1

• Add another db config (db2), on the same host


group_vars/db1
group_vars/db2

- Inventory
[db1]
host1.example.com
[db2]
host1.example.com

ansible-playbook dbconfig.yml –e db=db2

• You might get unexpected results (variables might not come from the configuration you expected)
Inventory and databases [Solutions]
• Separate inventory files, one config per inventory
$ cat inventory/db1
[db1]
host1.example.com
$ cat inventory/db2
[db2]
host1.example.com
and target the config with ‘ansible-playbook … -i inventory/db1’ etc

• Use fake hosts


[db1]
host-db1 ansible_host=host1.example.com
[db2]
host-db2 ansible_host=host1.example.com

• Use one DNS CNAME per database, same concept as fake hosts
• Use one database per host
Inventory (random thoughts)
• Try to keep the inventories as standard as possible (for as long as possible)
• Maybe keep inventory in its own repository (to avoid duplication, if many different
repos for management).
‒ Possible to softlink, or just point playbook to inventory
• If environment is large, external service registry could be needed
‒ Dynamic inventory script, like for AWS
Setting up scenarios – common variables
oracle_base: /u01/app/oracle
oracle_home: "{{ oracle_base }}/product/{{ oracle_db.version }}/db"
oracle_env:
ORACLE_HOME: "{{ oracle_home }}"
LD_LIBRARY_PATH: "{{ oracle_home }}/lib“
user: system
oracle_db:
name: orcl
passwd: "{{ oracle_passwd }}” #<- Password taken from external file
version: 12.2.0.1
cdb: true
db_dest: +DATA
fra_dest: +DATA
pdb:
- appdb1
- appdb2
Scenario: Setting init.ora parameters 1/2 variables

init_parameters:
- name: db_recovery_file_dest_size - name: audit_trail
value: 60G value: XML
- name: db_recovery_file_dest scope: spfile
value: “{{ oracle_db.fra_dest }}” - name: sec_case_sensitive_logon
- name: db_create_file_dest value: TRUE
value: “{{ oracle_db.db_dest }}” - name: sec_max_failed_login_attempts
- name: filesystemio_options value: 3
value: setall - name: sql92_security
scope: spfile value: TRUE
- name: optimizer_adaptive_features scope: spfile
state: absent
Scenario: Setting init.ora parameters 2/2 task
- name: Set parameters
local_action:
module: oracle_parameter
hostname: “{{ inventory_hostname }}”
service_name: “{{ oracle_db.name }}”
user: “{{ oracle_db.user }}”
password: “{{ oracle_db.passwd }}”
name: “{{ item.name }}”
value: "{{ item.value }}"
state: “{{ item.state | default('present') }}”
scope: “{{ item.scope | default('both') }}”
environment: "{{ oracle_env }}"
with_items: "{{ init_parameters }}"
tags: param
Scenario: Creating PDB-s
- name: Create pdb
local_action:
module: oracle_pdb
hostname: "{{ inventory_hostname }}"
username: sys
password: "{{ oracle_db.passwd }}"
service_name: "{{ oracle_db.name }}"
mode: sysdba
name: "{{ item }}"
datafile_dest: "{{ oracle_db.db_dest }}"
state: present
environment: "{{ oracle_env }}“
with_items: “{{ oracle_db.pdb }}”
tags: pdb
Scenario: Creating database users 1/3 variables
dba_user:
- schema: dbauser
schema_password_hash: "{{dbauser_pwhash}}"
default_tablespace: dbauser_data
default_temp_tablespace: temp
grants:
- dba

roles:
- name: approle1
role_grants:
- create session
- create table
- select any dictionary
Scenario: Creating database users 2/3 task
- name: Create DBA user
local_action:
module: oracle_user
hostname: “{{ inventory_hostname }}”
service_name: “{{ oracle_db.name }}”
user: “{{ oracle_db.user }}”
password: “{{ oracle_db.passwd }}”
schema: “{{ item.0.schema }}”
schema_password_hash: “{{ item.0.schema_password_hash }}”
state: “{{ item.0.state | default(‘present’) }}”
default_temp_tablespace: “{{ item.0.default_temp_tablespace }}”
default_tablespace: “{{ item.0.default_tablespace }}”
grants: “{{ item.1 }}”
update_password: on_create
environment: "{{ oracle_env }}"
with_subelements:
- "{{ dba_user }}"
- grants
tags: users
Scenario: Creating database users 3/3 task
- name: Create application role - name: Add grants to role
local_action: local_action:
module: oracle_role module: oracle_grants
hostname: “{{ inventory_hostname }}” hostname: “{{ inventory_hostname }}”
service_name: “{{ oracle_db.name }} service_name: “{{ oracle_db.name }}”
user: “{{ oracle_db.user }}” user: “{{ oracle_db.user }}”
password: “{{ oracle_db.passwd }}” password: “{{ oracle_db.passwd }}”
role: “{{ item.name }}” role: “{{ item.name }}”
state: present grants: "{{ item.role_grants }}"
environment: "{{ oracle_env }}" state: present
with_items: "{{ roles }}" environment: "{{ oracle_env }}"
tags: role with_items: "{{ roles }}"
tags: role,grant
Scenario: Syncing users and roles from AD
- name: oracle_ldapuser
local_action:
module: oracle_ldapuser
### Target Oracle database connection information is cut from this slide
### LDAP parameters
ldap_connect: "ldap://mycompany.domain:389"
ldap_binddn: [email protected]
ldap_bindpassword: Ansible2017
ldap_user_basedn: OU=Users,OU=Demo,DC=ansible,DC=test
# The following filter means that objectClass is person, member of one specific group and account is not disabled
ldap_user_filter: (&(objectClass=person)(memberOf=CN=prod_db,OU=Groups,DC=ansible,DC=test)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
ldap_username_attribute: sAMAccountName
### New user parameters
user_profile: LDAP_USER
All synced users must have
user_grants:
a common dedicated profile!
- create session
- create table
group_role_map:
- {dn: "CN=HR,OU=Groups,OU=Demo,DC=ansible,DC=test", group: "department_hr"}
- {dn: "CN=IT,OU=Groups,OU=Demo,DC=ansible,DC=test", group: "department_it"}
deleted_user_mode: lock Users missing from LDAP query
environment: "{{ oracle_env }}"
will be locked or deleted.
Scenario: Maintaining wildcard privileges
- name: Manage what objects DEPARTMENT_HR can access
local_action:
module: oracle_privs:
### Target Oracle database connection information is cut from this slide
roles:
- DEPARTMENT_HR SELECT owner, object_name
privs: FROM all_objects
- SELECT WHERE (owner||’.’||object_name LIKE
- FLASHBACK ‘HR.%’ OR owner||’.’||object_name =
objs: ‘HRREST.COUNTRIES’)
- HR.% AND object_type IN (‘TABLE’,’VIEW’)
- HRREST.COUNTRIES
objtypes:
- TABLE
- VIEW Existing extra privileges not
state: present matching the privs + objects
environment: "{{ oracle_env }}" list will be revoked!
Scenario: Managing resource manager

- name: Manage consumer group for LDAP synced users


local_action:
module: oracle_rsrc_consgroup
### Target Oracle database connection information is cut from this slide
name: ad_user_consgroup
state: present
# NB! Oracle resource manager actually does not support
# user profile based mapping, so we expand it to user list
map_oracle_user_profile: LDAP_USER
grant_user_profile: LDAP_USER
environment: "{{ oracle_env }}"
Managing passwords
• You should not store plain text passwords in playbooks!
• Ansible-vault
‒ Ansible native solution to encrypt YML files that can be included in playbooks
‒ Ansible-vault files can be committed to git
‒ Password delivered through user input, file or script
• Oracle wallet
‒ Ansible-oracle-modules use cx_Oracle python module that requires OCI client, therefore it
also supports Oracle wallet authentication
‒ Requires setting up tnsnames.ora and sqlnet.ora
‒ Each TNS name needs password entry in wallet
• Limitation for large deployments?
• Calling remote password service from playbook
‒ REST API calls to e.g Passwordstate to fetch individual DB passwords
‒ API key can be secured with ansible-vault
Scenario: Securing passwords with Ansible Vault
$ ansible-vault create passwords.yml

sys_password: Oracle123
dbauser_password: Oracle456

$ cat passwords.yml

$ANSIBLE_VAULT;1.1;AES256
37306631393231363334396666643466613062373336623836383333653963376463366234353130
3962383634356134663061313162386136386234616138380a616630626535613131353431356536
66623831316637306432363763333231323139363535666137666333353463633763633333383963
3535386137633165660a376435613736666663396233626531346530343462333865306137386434
35303466646564313131386565386364333762646130316439343764356366643034623563633061
32373832376136303834356664373534643631303439656434613761633732653433646536346231
343062396162376366326561333537343736
Scenario: Create job in all PDB 1/3 variables
pdb_json_query: pdb[?OPEN_MODE=='READ WRITE'].NAME

exclude_pdb:
- PDB$SEED

common_job:
name: DBAUSER.SEND_SLOW_SQL_REPORT
job_type: plsql_block
job_action: DBA_REPORTS_PKG.SEND_SLOW_SQL_REPORT
repeat_interval: FREQ=DAILY;BYHOUR=8
Scenario: Create job in all PDB 2/3 tasks

# Connect to CDB and gather facts


- name: Gather target CDB facts
local_action:
module: oracle_facts
hostname: “{{ inventory_hostname }}”
service_name: “{{ oracle_db.name }}”
user: “{{ oracle_db.user }}”
password: “{{ oracle_db.passwd }}”
register: dbfacts
environment: “{{ oracle_env }}”
Scenario: Create job in all PDB 3/3 tasks
# Connect to all PDB-s and create the job
- name: Create a small test job in all PDBs
local_action:
module: oracle_job
hostname: “{{ inventory_hostname }}”
service_name: “{{ item }}”
user: “{{ oracle_db.user }}”
password: “{{ oracle_db.passwd }}”
# Job info
state: present
name: “{{ common_job.name }}”
job_type: “{{ common_job.job_type }}”
job_action: “{{ common_job.job_action }}” Task only runs when target
repeat_interval: “{{ common_job.repeat_interval }}” database is CDB. Task is
environment: “{{ oracle_env }}” repeated for each PDB.
when: dbfacts.ansible_facts.cdb
with_items: "{{ dbfacts.ansible_facts | json_query(pdb_json_query) |
difference(exclude_pdb) }}"
Scheduling/running playbooks
• We use Jenkins
• Basically 3 ways of running jobs
‒ Manually
‒ Trigger based
• File is committed to Git
• Git HEAD branch is merged to stable PROD branch
‒ Scheduled
Running playbooks (a few other options)
• Ansible Tower (commercial offering)
• Ansible AWX (open source Tower)
• Rundeck
• Semaphore
• Tensor
• Polemarch
Oracle infrastructure as code
• No changes should be done manually on database infrastructure
• Changes done in Ansible code only
• Ansible code version controlled in git
• Commit/merge to git automatically executes Ansible playbooks that deploy the
change
DEMO: Oracle infrastructure as code
• Demo environment:
‒ Oracle 12cR2, with one CDB
‒ Git
‒ Bitbucket
‒ Ansible executed from Jenkins
• Action flow:
‒ Change in playbook committed to git (Bitbucket)
• Add new ASM diskgroup
• Change init.ora parameters in CDB
• Create and initialise new application PDB
‒ Add role with system grants
‒ Add tablespaces
‒ Add application schema
‒ Add service
‒ Bitbucket commit hook fires a job in Jenkins
Ansible is great, but...
• ... it is not for everything
• There are better solutions for:
‒ Managing schema objects
‒ Deploying database code
• Better look at specific tools for these purposes:
‒ Liquibase
‒ FlyWay
• But... Ansible can execute these tools as part of the release process orchestration
Resources
• Ansible homepage: https://www.ansible.com/
• Oracle database modules for Ansible:
https://github.com/oravirt/ansible-oracle-modules
• Deploying RAC with Ansible:
https://github.com/oravirt/ansible-oracle
Download scripts
• Here you can download the scripts used in this presentation
‒ https://github.com/oravirt/oug-ansible-oracle
Thank You

© Kindred Group plc 2017 41

You might also like