Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
ansible_adanced_oci [2022/01/30 21:13] – [Compute Node] andonovj | ansible_adanced_oci [2024/08/19 13:03] (current) – andonovj | ||
---|---|---|---|
Line 17: | Line 17: | ||
< | < | ||
- | (venv) julien.andonov@julienandonovs-MacBook-Pro venv % ansible-playbook -i oci_inventory.py setup_computenode.yaml | + | (venv) julien.andonov@julienandonovs-MacBook-Pro venv % ansible-playbook -i oci_inventory.py setup_computenode.yaml --extra-vars " |
[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: | ||
- | - / | ||
tasks: | tasks: | ||
- block: | - block: | ||
Line 150: | Line 148: | ||
< | < | ||
- | ansible-playbook -i oci_inventory.py setup_mysql.yml | + | ansible-playbook -i oci_inventory.py setup_mysql.yml --extra-vars " |
</ | </ | ||
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: | ||
+ | |||
+ | < | ||
+ | ansible-playbook -i oci_inventory.py setup_storage_computenode.yml --extra-vars " | ||
+ | </ | ||
+ | |||
+ | The playbook itself, you can see below: | ||
+ | |||
+ | < | ||
+ | --- | ||
+ | |||
+ | - hosts: localhost | ||
+ | collections: | ||
+ | - oracle.oci | ||
+ | tasks: | ||
+ | - block: | ||
+ | - name: Get instance details | ||
+ | oci_compute_instance_facts: | ||
+ | compartment_id: | ||
+ | lifecycle_state: | ||
+ | display_name: | ||
+ | register: instances_details | ||
+ | |||
+ | - name: Get facts | ||
+ | debug: | ||
+ | msg: "{{ instances_details }}" | ||
+ | |||
+ | - name: Save instance info | ||
+ | set_fact: | ||
+ | instance: '{{ instances_details[" | ||
+ | instance_ips: | ||
+ | | ||
+ | - name: Show instances name | ||
+ | debug: | ||
+ | msg: ' | ||
+ | |||
+ | - name: Show instance' | ||
+ | debug: | ||
+ | msg: ' | ||
+ | |||
+ | - name: Add instance(s) to in-memory inventory | ||
+ | add_host: | ||
+ | name: '{{ item }}' | ||
+ | loop: '{{ instance_ips }}' | ||
+ | |||
+ | |||
+ | - name: Get hostvars | ||
+ | debug: | ||
+ | msg: '{{ hostvars[" | ||
+ | |||
+ | - name: Create a block device | ||
+ | oci_blockstorage_volume: | ||
+ | compartment_id: | ||
+ | availability_domain: | ||
+ | display_name: | ||
+ | size_in_gbs: | ||
+ | register: created_volume | ||
+ | |||
+ | - name: Get the block device data | ||
+ | oci_blockstorage_volume_facts: | ||
+ | display_name: | ||
+ | availability_domain: | ||
+ | compartment_id: | ||
+ | lifecycle_state: | ||
+ | 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_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: | ||
+ | |||
+ | - import_playbook: | ||
+ | vars: | ||
+ | instance_ip: | ||
+ | bash_commands: | ||
+ | |||
+ | </ | ||
+ | |||
+ | That playbook, will create a block device, attach it and also attach it on the host using the following playbook: | ||
+ | |||
+ | < | ||
+ | --- | ||
+ | |||
+ | - name: Attach the device | ||
+ | vars: | ||
+ | ansible_user: | ||
+ | ansible_become: | ||
+ | ansible_become_method: | ||
+ | |||
+ | hosts: '{{ instance_ip }}' | ||
+ | tasks: | ||
+ | - block: | ||
+ | - name: Execute commands | ||
+ | ansible.builtin.command: | ||
+ | loop: '{{ bash_commands }}' | ||
+ | </ | ||
+ | |||
+ | With all that, we can finally configure the refresh (resnap) and configure the replication: | ||
+ | |||
+ | |||
+ | ====Resnap the primary block device==== | ||
+ | < | ||
+ | --- | ||
+ | |||
+ | - hosts: localhost | ||
+ | collections: | ||
+ | - oracle.oci | ||
+ | vars_files: | ||
+ | - / | ||
+ | |||
+ | tasks: | ||
+ | - block: | ||
+ | - name: Get Replica instance details | ||
+ | oci_compute_instance_facts: | ||
+ | compartment_id: | ||
+ | lifecycle_state: | ||
+ | display_name: | ||
+ | register: replica_details | ||
+ | |||
+ | - name: Save Replica info | ||
+ | set_fact: | ||
+ | instance: '{{ replica_details[" | ||
+ | replica_ip: ' | ||
+ | |||
+ | - name: Add replica instance(s) to in-memory inventory | ||
+ | add_host: | ||
+ | name: " | ||
+ | ansible_host: | ||
+ | |||
+ | - name: Get attached devices on Replica | ||
+ | oci_compute_volume_attachment_facts: | ||
+ | compartment_id: | ||
+ | instance_id: | ||
+ | register: replica_volume_attachment_facts | ||
+ | |||
+ | - import_playbook: | ||
+ | vars: | ||
+ | instance_ip: | ||
+ | |||
+ | - name: Create iSCSI attachement | ||
+ | hosts: localhost | ||
+ | collections: | ||
+ | - oracle.oci | ||
+ | vars_files: | ||
+ | - / | ||
+ | tasks: | ||
+ | - block: | ||
+ | - name: Get Primary instance details | ||
+ | oci_compute_instance_facts: | ||
+ | compartment_id: | ||
+ | lifecycle_state: | ||
+ | display_name: | ||
+ | register: primary_details | ||
+ | |||
+ | - name: Save primary info | ||
+ | set_fact: | ||
+ | instance: '{{ primary_details[" | ||
+ | primary_ip: ' | ||
+ | primary_prv_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_id: | ||
+ | register: primary_volume_attachment_facts | ||
+ | |||
+ | - name: Get all devices on Replica | ||
+ | oci_compute_volume_attachment_facts: | ||
+ | compartment_id: | ||
+ | instance_id: | ||
+ | register: replica_volume_attachment_facts | ||
+ | |||
+ | - name: Set fact, attached device on the replica | ||
+ | set_fact: | ||
+ | replica_attached_blockdevice_id: | ||
+ | replica_attached_volume_id: | ||
+ | |||
+ | - name: Detach block level attachement device from Clone | ||
+ | oci_compute_volume_attachment: | ||
+ | volume_attachment_id: | ||
+ | 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: ' | ||
+ | availability_domain: | ||
+ | compartment_id: | ||
+ | size_in_gbs: | ||
+ | register: created_clone_block_volume | ||
+ | |||
+ | - name: Attach the clone to the replica | ||
+ | oci_compute_volume_attachment: | ||
+ | compartment_id: | ||
+ | instance_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: | ||
+ | |||
+ | - import_playbook: | ||
+ | vars: | ||
+ | instance_ip: | ||
+ | bash_commands: | ||
+ | |||
+ | - import_playbook: | ||
+ | vars: | ||
+ | instance_ip: | ||
+ | primary_host: | ||
+ | primary_prv_ip: | ||
+ | primary_password: | ||
+ | </ | ||
+ | |||
+ | |||
+ | That playbook will use our final playbook: " | ||
+ | |||
+ | ====Setup replication==== | ||
+ | <Code: bash|Setup replication> | ||
+ | --- | ||
+ | |||
+ | - name: Detach the device | ||
+ | vars: | ||
+ | ansible_user: | ||
+ | ansible_become: | ||
+ | ansible_become_method: | ||
+ | vars_files: | ||
+ | - / | ||
+ | | ||
+ | hosts: '{{ instance_ip }}' | ||
+ | tasks: | ||
+ | - name: Stop Firewall | ||
+ | service: name=firewalld state=stopped enabled=false | ||
+ | |||
+ | - name: Get file coordinate | ||
+ | shell: | | ||
+ | cat / | ||
+ | register: replication_file | ||
+ | |||
+ | - name: Get position coordinate | ||
+ | shell: | | ||
+ | wc {{ replication_file.stdout }} | awk -F " " ' | ||
+ | register: replication_position | ||
+ | |||
+ | - name: Change the UUID of MySQL | ||
+ | shell: | | ||
+ | newUUID=`uuidgen` | ||
+ | echo " | ||
+ | [auto] | ||
+ | server-uuid=${newUUID}" | ||
+ | |||
+ | - name: Start MySQL | ||
+ | service: name=mysqld state=started enabled=true | ||
+ | |||
+ | - name: Change primary on Replica | ||
+ | community.mysql.mysql_replication: | ||
+ | mode: changeprimary | ||
+ | primary_host: | ||
+ | primary_log_file: | ||
+ | primary_log_pos: | ||
+ | login_unix_socket: | ||
+ | login_user: root | ||
+ | login_password: | ||
+ | primary_user: | ||
+ | primary_password: | ||
+ | |||
+ | - name: Start replica | ||
+ | community.mysql.mysql_replication: | ||
+ | mode: startreplica | ||
+ | login_unix_socket: | ||
+ | login_user: root | ||
+ | login_password: | ||
+ | </ | ||
+ | |||
+ | 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' | ||
+ | |||
+ | There is one more playbook which we need to add. | ||
+ | |||
+ | < | ||
+ | --- | ||
+ | |||
+ | - name: Detach the device | ||
+ | vars: | ||
+ | ansible_user: | ||
+ | ansible_become: | ||
+ | ansible_become_method: | ||
+ | |||
+ | hosts: '{{ instance_ip }}' | ||
+ | tasks: | ||
+ | - name: Find the IQN | ||
+ | shell: | | ||
+ | iscsiadm --mode session | ||
+ | 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 / | ||
+ | register: locking_processes | ||
+ | ignore_errors: | ||
+ | |||
+ | - 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: ' | ||
+ | |||
+ | - name: Unmount File system | ||
+ | mount: | ||
+ | path: / | ||
+ | state: unmounted | ||
+ | |||
+ | - name: Detach the iSCSI | ||
+ | community.general.open_iscsi: | ||
+ | login: no | ||
+ | target: ' | ||
+ | when: iqn.stdout != "" | ||
+ | </ | ||
+ | |||
+ | 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:// | ||
+ |