ansible_adanced_oci

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
ansible_adanced_oci [2022/01/30 21:13] – [Compute Node] andonovjansible_adanced_oci [2024/08/19 13:03] (current) andonovj
Line 17: Line 17:
  
 <Code:Bash| Create a compute node> <Code:Bash| Create a compute node>
-(venv) julien.andonov@julienandonovs-MacBook-Pro venv % ansible-playbook -i oci_inventory.py setup_computenode.yaml --private-key id_oci --extra-vars "hostname=jdbwiki"+(venv) julien.andonov@julienandonovs-MacBook-Pro venv % ansible-playbook -i oci_inventory.py setup_computenode.yaml --extra-vars "hostname=jdbwiki"
 [WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details [WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
  
Line 41: Line 41:
   collections:   collections:
     - oracle.oci     - oracle.oci
-  vars_files: 
-    - /Users/julien.andonov/Work/POCE-playbooks/oci-ansible-collection/samples/compute/venv/variables.yml 
   tasks:   tasks:
     - block:     - block:
Line 150: Line 148:
  
 <Code:bash|MySQL Deployment> <Code:bash|MySQL Deployment>
-ansible-playbook -i oci_inventory.py setup_mysql.yml --private-key id_oci --extra-vars "hostname=db-stg-001" --extra-vars "root_password=UlraSecurePassword123#" --extra-vars "version=5.7+ansible-playbook -i oci_inventory.py setup_mysql.yml --extra-vars "hostname=db-stg-001" --extra-vars "root_password=UlraSecurePassword123#" --extra-vars "version=5.7
 </Code> </Code>
  
Line 391: Line 389:
 Now, of course, I will change the configuration with a template and so on, but that is for a later module. Now, of course, I will change the configuration with a template and so on, but that is for a later module.
  
 +=====MySQL Replication & Refresh =====
 +Now, in order to configure replication and refresh. We need to implement the snapshot of the block device. But wait...we didn't configure a block device yet, so let's get that going.
 +
 +
 +====Block device====
 +To configure a block device you can use the following command:
 +
 +<Code:bash|Block device config>
 +ansible-playbook -i oci_inventory.py setup_storage_computenode.yml --extra-vars "hostname=db-stg-001"
 +</Code>
 +
 +The playbook itself, you can see below:
 +
 +<Code:bash|setup_storage_computenode.yml>
 +---
 +
 +- hosts: localhost
 +  collections:
 +    - oracle.oci
 +  tasks:
 +    - block:   
 +      - name: Get instance details
 +        oci_compute_instance_facts:
 +          compartment_id: "{{ instance_compartment }}"
 +          lifecycle_state: "RUNNING"
 +          display_name: "{{ hostname }}"
 +        register: instances_details
 +
 +      - name: Get facts
 +        debug:
 +          msg: "{{ instances_details }}"
 +
 +      - name: Save instance info
 +        set_fact:
 +          instance: '{{ instances_details["instances"] }}'
 +          instance_ips: '{{instances_details["instances"] | map(attribute="primary_public_ip" }}'
 +      
 +      - name: Show instances name
 +        debug:
 +          msg: '{{instance}}'
 +
 +      - name: Show instance's IPs
 +        debug:
 +          msg: '{{instance_ips}}'
 +
 +      - name: Add instance(s) to in-memory inventory
 +        add_host:
 +          name: '{{ item }}'
 +        loop: '{{ instance_ips }}'
 +
 +
 +      - name: Get hostvars
 +        debug:
 +          msg: '{{ hostvars["localhost"]["instance_ips"]}}'
 +
 +      - name: Create a block device
 +        oci_blockstorage_volume:
 +          compartment_id: "{{ instance_compartment }}"
 +          availability_domain: "{{ instances_details.instances[0].availability_domain }}"
 +          display_name: "{{ hostname }}-bv1"
 +          size_in_gbs: 20
 +        register: created_volume
 +
 +      - name: Get the block device data
 +        oci_blockstorage_volume_facts:
 +          display_name: "{{ hostname }}-bv1"
 +          availability_domain: "{{ instance_ad }}"
 +          compartment_id: "{{ instance_compartment }}"
 +          lifecycle_state: "AVAILABLE"
 +        register: compute_node_block_volume
 +
 +      - name: Print block devices 
 +        debug:
 +          msg: "{{ compute_node_block_volume }}"
 +        
 +      - name: Attach volume_attachment
 +        oci_compute_volume_attachment:
 +          compartment_id: "{{ instance_compartment }}"
 +          instance_id: "{{ instances_details.instances[0].id }}"
 +          type: service_determined
 +          volume_id: "{{ compute_node_block_volume.volumes[0].id }}"
 +        regoster: attached_block_device
 +
 +      - name: Save attachement commands
 +        set_fact: 
 +          iscsi_attach_commands: '{{ attached_block_device.volume_attachment.iscsi_attach_commands }}'
 +
 +- import_playbook: execute_shell_commands_root.yml
 +  vars:
 +    instance_ip: '{{ hostvars["localhost"]["instance_ips"] }}'
 +    bash_commands: '{{ hostvars["localhost"]["iscsi_attach_commands"] }}'
 +
 +</Code>
 +
 +That playbook, will create a block device, attach it and also attach it on the host using the following playbook:
 +
 +<Code:bash|execute_shell_commands>
 +---
 +
 +- name: Attach the device
 +  vars:
 +    ansible_user: opc
 +    ansible_become: yes
 +    ansible_become_method: sudo
 +
 +  hosts: '{{ instance_ip }}'
 +  tasks:
 +    - block:
 +      - name: Execute commands
 +        ansible.builtin.command: '{{ item }}'
 +        loop: '{{ bash_commands }}'
 +</Code>
 +
 +With all that, we can finally configure the refresh (resnap) and configure the replication:
 +
 +
 +====Resnap the primary block device====
 +<Code:bash|setup_resnap>
 +---
 +
 +- hosts: localhost
 +  collections:
 +    - oracle.oci
 +  vars_files:
 +    - /Users/julien.andonov/Work/POCE-playbooks/oci-ansible-collection/samples/compute/venv/variables.yml
 +
 +  tasks:
 +    - block:
 +      - name: Get Replica instance details
 +        oci_compute_instance_facts:
 +          compartment_id: "{{ instance_compartment }}"
 +          lifecycle_state: "RUNNING"
 +          display_name: "{{ REPLICA }}"
 +        register: replica_details
 +
 +      - name: Save Replica info
 +        set_fact:
 +          instance: '{{ replica_details["instances"] }}'
 +          replica_ip: '{{replica_details["instances"] | map(attribute="primary_public_ip" }}'
 +
 +      - name: Add replica instance(s) to in-memory inventory
 +        add_host:
 +          name: "replica_ip"
 +          ansible_host: '{{ replica_ip }}'
 +
 +      - name: Get attached devices on Replica
 +        oci_compute_volume_attachment_facts:
 +          compartment_id: "{{ instance_compartment }}"
 +          instance_id: "{{ replica_details.instances[0].id }}"
 +        register: replica_volume_attachment_facts
 +
 +- import_playbook: detach_iscsi.yml
 +  vars:
 +    instance_ip: '{{ hostvars["localhost"]["replica_ip"] }}'
 +
 +- name: Create iSCSI attachement
 +  hosts: localhost
 +  collections:
 +    - oracle.oci
 +  vars_files:
 +    - /Users/julien.andonov/Work/POCE-playbooks/oci-ansible-collection/samples/compute/venv/variables.yml
 +  tasks:
 +    - block:
 +      - name: Get Primary instance details
 +        oci_compute_instance_facts:
 +          compartment_id: "{{ instance_compartment }}"
 +          lifecycle_state: "RUNNING"
 +          display_name: "{{ PRIMARY }}"
 +        register: primary_details
 +
 +      - name: Save primary info
 +        set_fact:
 +          instance: '{{ primary_details["instances"] }}'
 +          primary_ip: '{{primary_details["instances"] | map(attribute="primary_public_ip" }}'
 +          primary_prv_ip: '{{primary_details["instances"] | map(attribute="primary_private_ip" }}'
 +
 +      - name: Add primary instance(s) to in-memory inventory
 +        add_host:
 +          name: '{{ item }}'
 +        loop: '{{ primary_ip }}'
 +
 +      - name: Get attached devices on Primary
 +        oci_compute_volume_attachment_facts:
 +          compartment_id: "{{ instance_compartment }}"
 +          instance_id: "{{ primary_details.instances[0].id }}"
 +        register: primary_volume_attachment_facts
 +
 +      - name: Get all devices on Replica
 +        oci_compute_volume_attachment_facts:
 +          compartment_id: "{{ instance_compartment }}"
 +          instance_id: "{{ replica_details.instances[0].id }}"
 +        register: replica_volume_attachment_facts
 +
 +      - name: Set fact, attached device on the replica
 +        set_fact:
 +          replica_attached_blockdevice_id: '{{ replica_volume_attachment_facts.volume_attachments | selectattr("lifecycle_state", "equalto", "ATTACHED") | map(attribute="id") }}'
 +          replica_attached_volume_id: '{{ replica_volume_attachment_facts.volume_attachments | selectattr("lifecycle_state", "equalto", "ATTACHED") | map(attribute="volume_id") }}'
 +
 +      - name: Detach block level attachement device from Clone
 +        oci_compute_volume_attachment:
 +          volume_attachment_id: '{{ replica_attached_blockdevice_id[0] }}'
 +          state: absent
 +        when: replica_attached_blockdevice_id|length != 0
 +
 +      - name: Delete the block volume
 +        oci_blockstorage_volume:
 +          volume_id: '{{ replica_attached_volume_id[0] }}'
 +          state: absent
 +        when: replica_attached_volume_id|length != 0
 +
 +      - name: Create a clone data from another block volume in the same availability domain
 +        oci_blockstorage_volume:
 +          name: '{{ REPLICA }}-bv-clone'
 +          source_details:
 +            id: '{{ primary_volume_attachment_facts.volume_attachments[0].volume_id }}'
 +            type: 'volume'
 +          availability_domain: '{{ instance_ad }}'
 +          compartment_id: '{{ instance_compartment }}'
 +          size_in_gbs: 50
 +        register: created_clone_block_volume
 +
 +      - name: Attach the clone to the replica
 +        oci_compute_volume_attachment:
 +          compartment_id: "{{ instance_compartment }}"
 +          instance_id: "{{ replica_details.instances[0].id }}"
 +          type: service_determined
 +          volume_id: "{{ created_clone_block_volume.volume.id }}"
 +        register: attached_block_device
 +
 +      - name: Save attachement commands
 +        set_fact: 
 +          iscsi_attach_commands: '{{ attached_block_device.volume_attachment.iscsi_attach_commands }}'
 +
 +- import_playbook: execute_shell_commands_root.yml
 +  vars:
 +    instance_ip: '{{ hostvars["localhost"]["replica_ip"] }}'
 +    bash_commands: '{{ hostvars["localhost"]["iscsi_attach_commands"] }}'
 +
 +- import_playbook: setup_replication.yml
 +  vars:
 +    instance_ip: '{{ hostvars["localhost"]["replica_ip"] }}'
 +    primary_host: '{{ PRIMARY }}'
 +    primary_prv_ip: '{{ hostvars["localhost"]["primary_prv_ip"] }}'
 +    primary_password: '{{ root_password }}'
 +</Code>
 +
 +
 +That playbook will use our final playbook: "setup_replication", which you can see below:
 +
 +====Setup replication====
 +<Code: bash|Setup replication>
 +---
 +
 +- name: Detach the device
 +  vars:
 +    ansible_user: opc
 +    ansible_become: yes
 +    ansible_become_method: sudo
 +  vars_files:
 +    - /Users/julien.andonov/Work/POCE-playbooks/oci-ansible-collection/samples/compute/venv/variables.yml
 +    
 +  hosts: '{{ instance_ip }}'
 +  tasks:
 +    - name: Stop Firewall
 +      service: name=firewalld state=stopped enabled=false
 +
 +    - name: Get file coordinate
 +      shell: |
 +        cat /var/lib/mysql/mysql5/{{ PRIMARY }}-bin.index | tail -1
 +      register: replication_file
 +
 +    - name: Get position coordinate
 +      shell: |
 +        wc {{ replication_file.stdout }} | awk -F " " '{print $3}'
 +      register: replication_position
 +
 +    - name: Change the UUID of MySQL
 +      shell: |
 +        newUUID=`uuidgen`
 +        echo "
 +        [auto]
 +        server-uuid=${newUUID}" > /var/lib/mysql/mysql5/auto.cnf
 +
 +    - name: Start MySQL
 +      service: name=mysqld state=started enabled=true
 +
 +    - name: Change primary on Replica
 +      community.mysql.mysql_replication:
 +        mode: changeprimary
 +        primary_host: '{{ primary_prv_ip[0] }}'
 +        primary_log_file: '{{ replication_file.stdout }}'
 +        primary_log_pos: '{{ replication_position.stdout }}'
 +        login_unix_socket: /var/lib/mysql/mysql5/mysql.sock
 +        login_user: root
 +        login_password: "{{ root_password }}"
 +        primary_user: 'replication'
 +        primary_password: "{{ root_password }}"
 +
 +    - name: Start replica
 +      community.mysql.mysql_replication:
 +        mode: startreplica
 +        login_unix_socket: /var/lib/mysql/mysql5/mysql.sock
 +        login_user: root
 +        login_password: "{{ root_password }}"
 +</Code>
 +
 +With this, we were able to setup replication using OCI and ansible. The resnap can be done as many time as needed. It will always clone the primary's block device and attach it on replica, then it will re-establish replication.
 +
 +There is one more playbook which we need to add.
 +
 +<Code:bash|detach_iscsi>
 +---
 +
 +- name: Detach the device
 +  vars:
 +    ansible_user: opc
 +    ansible_become: yes
 +    ansible_become_method: sudo
 +
 +  hosts: '{{ instance_ip }}'
 +  tasks:
 +    - name: Find the IQN
 +      shell: |
 +        iscsiadm --mode session  -P 3 | grep Target: | head | awk -F " " '{print $2}'
 +      register: iqn
 +
 +    - name: Stop  MySQL
 +      service: name=mysqld state=stopped enabled=false
 +      when: iqn.stdout != ""
 +
 +    - name: Find possible processes holding the file system
 +      shell: |
 +        lsof +D /var/lib/mysql |  awk -F " " '{print $2}' | uniq | grep -v "PID"
 +      register: locking_processes
 +      ignore_errors: yes
 +
 +    - name: Print locking process
 +      debug:
 +        msg: '{{ locking_processes }}'
 +      when: locking_processes.stdout_lines|length != 0
 +
 +    - name: Kill and unmount the file system
 +      shell: |
 +        kill -9 '{{ item }}'
 +      with_items: '{{ locking_processes.stdout_lines }}'
 +      when: locking_processes.stdout_lines|length != 0
 +
 +    - name: Print IQN
 +      debug:
 +        msg: '{{iqn.stdout}}'
 +
 +    - name: Unmount File system
 +      mount:
 +        path: /var/lib/mysql
 +        state: unmounted
 +
 +    - name: Detach the iSCSI
 +      community.general.open_iscsi:
 +        login: no
 +        target: '{{iqn.stdout}}'
 +      when: iqn.stdout != ""
 +</Code>
 +
 +That playbook will stop the MySQL and detach the iSCSI from the compute node, so we can safely, remove it from the OCI as well.
 +
 +=====MySQL Clusterset Automation=====
 +This ansible project consists of 3 roles:
 +  - MySQL Instance
 +  - MySQL InnoDB Cluster
 +  - MySQL Router
 +
 +That will create architecture with 1 InnoDB Clusterset and a replicaset attached to it. The full code, you can see here:
  
 +https://github.com/JulienAndonov/MySQL_Cluster_Ansible
 + 
  • ansible_adanced_oci.1643577216.txt.gz
  • Last modified: 2022/01/30 21:13
  • by andonovj