Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
ansible_adanced_oci [2022/01/30 21:01] – created andonovj | ansible_adanced_oci [2024/08/19 13:03] (current) – andonovj | ||
---|---|---|---|
Line 16: | Line 16: | ||
Of course you need to create a VCN prior that with the correct name: | Of course you need to create a VCN prior that with the correct name: | ||
+ | < | ||
+ | (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 | ||
+ | PLAY [localhost] ********************************************************************************************************************************************************************************************************** | ||
+ | |||
+ | TASK [Gathering Facts] **************************************************************************************************************************************************************************************************** | ||
+ | ok: [localhost] | ||
+ | |||
+ | TASK [set_fact] *********************************************************************************************************************************************************************************************************** | ||
+ | |||
+ | </ | ||
+ | |||
+ | Actually that command, created the server on which that page is currently running :D | ||
+ | |||
+ | |||
+ | ====Playbook==== | ||
+ | The playbook you can see below: | ||
+ | |||
+ | < | ||
+ | --- | ||
+ | |||
+ | - hosts: localhost | ||
+ | collections: | ||
+ | - oracle.oci | ||
+ | tasks: | ||
+ | - block: | ||
+ | - name: Get Running Instance ID | ||
+ | oci_compute_instance_facts: | ||
+ | compartment_id: | ||
+ | lifecycle_state: | ||
+ | register: instance_facts | ||
+ | |||
+ | - name: Launch an instance | ||
+ | oci_compute_instance: | ||
+ | availability_domain: | ||
+ | compartment_id: | ||
+ | name: "{{ hostname }}" | ||
+ | image_id: "{{ instance_image }}" | ||
+ | shape: "{{ instance_shape }}" | ||
+ | create_vnic_details: | ||
+ | assign_public_ip: | ||
+ | hostname_label: | ||
+ | subnet_id: "{{ instance_subnet_id }}" | ||
+ | metadata: | ||
+ | ssh_authorized_keys: | ||
+ | freeform_tags: | ||
+ | wait: True | ||
+ | when: (instance_facts.instances | regex_findall(' | ||
+ | register: result | ||
+ | |||
+ | - name: Print Result | ||
+ | debug: | ||
+ | msg: "{{ result }}" | ||
+ | |||
+ | - name: Get the facts when instance is already created | ||
+ | oci_compute_instance_facts: | ||
+ | compartment_id: | ||
+ | display_name: | ||
+ | lifecycle_state: | ||
+ | register: instances | ||
+ | |||
+ | - name: Print Instances | ||
+ | debug: | ||
+ | msg: "{{ instances }}" | ||
+ | |||
+ | - set_fact: | ||
+ | result: "{{ instances.instances[0] }}" | ||
+ | |||
+ | - name: Print instance details | ||
+ | debug: | ||
+ | msg: " | ||
+ | - set_fact: | ||
+ | instance_id: | ||
+ | when: instances is defined | ||
+ | |||
+ | - name: Get the VNIC attachment details of instance | ||
+ | oci_compute_vnic_attachment_facts: | ||
+ | compartment_id: | ||
+ | instance_id: | ||
+ | register: result | ||
+ | |||
+ | - name: Get details of the VNIC | ||
+ | oci_network_vnic_facts: | ||
+ | id: "{{ result.vnic_attachments[0].vnic_id }}" | ||
+ | register: result | ||
+ | - set_fact: | ||
+ | instance_public_ip: | ||
+ | |||
+ | - name: Print the public ip of the newly launched instance | ||
+ | debug: | ||
+ | msg: " | ||
+ | |||
+ | - name: Wait (upto 10 minutes) for port 22 to become open | ||
+ | wait_for: | ||
+ | port: 22 | ||
+ | host: '{{ instance_public_ip }}' | ||
+ | state: started | ||
+ | delay: 10 | ||
+ | timeout: 600 | ||
+ | vars: | ||
+ | ansible_connection: | ||
+ | |||
+ | - set_fact: | ||
+ | ssh_command_with_generated_key: | ||
+ | | ||
+ | - set_fact: | ||
+ | ssh_command_with_custom_key: | ||
+ | |||
+ | - name: Attempt a ssh connection to the newly launched instance | ||
+ | command: "{{ ssh_command_with_custom_key if ' | ||
+ | retries: 3 | ||
+ | delay: 5 | ||
+ | register: result | ||
+ | until: result.rc == 0 | ||
+ | |||
+ | - name: Print SSH response from launched instance | ||
+ | debug: | ||
+ | msg: "SSH response from instance -> {{ result.stdout_lines }}" | ||
+ | |||
+ | - name: Add host | ||
+ | add_host: | ||
+ | name: "{{ hostname }}" | ||
+ | ansible_ssh_host: | ||
+ | </ | ||
+ | |||
+ | So the playbook, won't create a compute node which already exist and it will also verify that the server has been created :) | ||
+ | |||
+ | =====MySQL Setup===== | ||
+ | Now, since OCI stands for Oracle Cloud Interface, well...they have Oracle Linux and AS SUCH, by default it is MySQL 8, so...my first task is to DELETE the MySQL 8 :D in my playbook. Then I install the new packages and so on so far.... :) | ||
+ | |||
+ | < | ||
+ | ansible-playbook -i oci_inventory.py setup_mysql.yml --extra-vars " | ||
+ | </ | ||
+ | |||
+ | For the people who are wondering what the: " | ||
+ | |||
+ | ====Playbook==== | ||
+ | Again, the playbook you can see below: | ||
+ | |||
+ | < | ||
+ | --- | ||
+ | |||
+ | - hosts: localhost | ||
+ | collections: | ||
+ | - oracle.oci | ||
+ | vars_files: | ||
+ | - / | ||
+ | |||
+ | 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: Add instance(s) to in-memory inventory | ||
+ | add_host: | ||
+ | name: '{{ item }}' | ||
+ | loop: '{{ instance_ips }}' | ||
+ | |||
+ | |||
+ | - name: Configure MySQL | ||
+ | vars: | ||
+ | ansible_user: | ||
+ | ansible_become: | ||
+ | ansible_become_method: | ||
+ | |||
+ | hosts: '{{ hostvars[" | ||
+ | tasks: | ||
+ | - block: | ||
+ | - name: Remove repository (and clean up left-over metadata) | ||
+ | file: | ||
+ | path: / | ||
+ | state: absent | ||
+ | |||
+ | - name: Remove MySQL 8.0 packages | ||
+ | yum: | ||
+ | name: | ||
+ | - mysql-community-client-plugins-8* | ||
+ | - mysql-community-common-8* | ||
+ | - mysql-community-libs-8* | ||
+ | - mysql-community-libs-compat-8* | ||
+ | state: absent | ||
+ | |||
+ | - name: yum-clean-metadata | ||
+ | command: yum clean metadata | ||
+ | args: | ||
+ | warn: no | ||
+ | |||
+ | - name: Add repository | ||
+ | yum_repository: | ||
+ | name: mysql-ol7-5.7 | ||
+ | baseurl: https:// | ||
+ | description: | ||
+ | enabled: yes | ||
+ | gpgcheck: yes | ||
+ | gpgkey: file:/// | ||
+ | |||
+ | - name: Install MySQL Packages | ||
+ | yum: | ||
+ | name: | ||
+ | - mysql-community-server | ||
+ | - mysql-community-client | ||
+ | - MySQL-python | ||
+ | state: present | ||
+ | |||
+ | - name: Stop MySQL | ||
+ | service: name=mysqld state=stopped enabled=false | ||
+ | |||
+ | - name: Change ownership of MySQL Directory | ||
+ | ansible.builtin.file: | ||
+ | path: / | ||
+ | owner: mysql | ||
+ | group: mysql | ||
+ | mode: 0755 | ||
+ | |||
+ | - name: Re-create the Data Directory | ||
+ | ansible.builtin.file: | ||
+ | path: / | ||
+ | state: absent | ||
+ | |||
+ | - name: Create MySQL Data directory if it doesn' | ||
+ | ansible.builtin.file: | ||
+ | path: / | ||
+ | owner: mysql | ||
+ | group: mysql | ||
+ | state: directory | ||
+ | mode: 0755 | ||
+ | |||
+ | - name: Create MySQL Log directory if it doesn' | ||
+ | ansible.builtin.file: | ||
+ | path: / | ||
+ | state: directory | ||
+ | owner: mysql | ||
+ | group: mysql | ||
+ | mode: ' | ||
+ | |||
+ | - name: Create MySQL Log file | ||
+ | ansible.builtin.file: | ||
+ | path: / | ||
+ | state: touch | ||
+ | owner: mysql | ||
+ | group: mysql | ||
+ | mode: ' | ||
+ | |||
+ | |||
+ | - name: Stop MySQL | ||
+ | service: name=mysqld state=stopped enabled=true | ||
+ | |||
+ | - name: Get last three characters of a string | ||
+ | shell: | | ||
+ | hostname | tail -c 4 | ||
+ | register: server_id | ||
+ | |||
+ | - name: Modify the config file | ||
+ | shell: | | ||
+ | echo " | ||
+ | [mysqld] | ||
+ | back_log = 128 | ||
+ | binlog_cache_size = 128K | ||
+ | binlog_row_image = minimal | ||
+ | character_set_server = utf8 | ||
+ | collation_server = utf8_bin | ||
+ | datadir = / | ||
+ | expire_logs_days = 10 | ||
+ | innodb_adaptive_hash_index = 0 | ||
+ | innodb_buffer_pool_instances = 4 | ||
+ | innodb_buffer_pool_size = 9216M | ||
+ | innodb_data_file_path = ibdata1: | ||
+ | innodb_data_home_dir = / | ||
+ | innodb_flush_log_at_trx_commit = 2 | ||
+ | innodb_flush_method = O_DIRECT | ||
+ | innodb_io_capacity = 300 | ||
+ | innodb_lock_wait_timeout = 120 | ||
+ | innodb_log_file_size = 1G | ||
+ | innodb_log_files_in_group = 2 | ||
+ | innodb_log_group_home_dir = / | ||
+ | innodb_numa_interleave = 1 | ||
+ | innodb_purge_batch_size = 1000 | ||
+ | innodb_purge_threads = 8 | ||
+ | innodb_read_io_threads = 12 | ||
+ | innodb_tmpdir = / | ||
+ | innodb_write_io_threads = 12 | ||
+ | join_buffer_size = 128K | ||
+ | key_buffer_size = 32M | ||
+ | local_infile = 0 | ||
+ | log_bin = / | ||
+ | log_error = / | ||
+ | log_slave_updates = 1 | ||
+ | log_slow_admin_statements = 1 | ||
+ | lower_case_table_names = 1 | ||
+ | max_allowed_packet = 32M | ||
+ | max_connect_errors = 50000 | ||
+ | max_connections = 500 | ||
+ | max_heap_table_size = 64M | ||
+ | max_relay_log_size = 1G | ||
+ | open_files_limit = 32768 | ||
+ | read_rnd_buffer_size = 2M | ||
+ | relay_log = mysql-relay-bin | ||
+ | relay_log_index = mysql-relay-bin.index | ||
+ | relay_log_info_repository = TABLE | ||
+ | relay_log_recovery = ON | ||
+ | replicate_ignore_db = mysql | ||
+ | replicate_ignore_table = mysql.user | ||
+ | replicate_ignore_table = mysql.db | ||
+ | replicate_ignore_table = mysql.host | ||
+ | replicate_ignore_table = mysql.tables_priv | ||
+ | replicate_ignore_table = mysql.columns_priv | ||
+ | replicate_ignore_table = mysql.procs_priv | ||
+ | replicate_ignore_table = mysql.proxies_priv | ||
+ | report_host = {{ hostname }} | ||
+ | server-id = {{ server_id.stdout }} | ||
+ | skip_name_resolve = 1 | ||
+ | skip_slave_start = 1 | ||
+ | slave_compressed_protocol = 1 | ||
+ | slave_parallel_type = LOGICAL_CLOCK | ||
+ | slave_parallel_workers = 2 | ||
+ | slave_preserve_commit_order = 1 | ||
+ | slow_query_log = 1 | ||
+ | slow_query_log_file = / | ||
+ | socket = / | ||
+ | sort_buffer_size = 32M | ||
+ | sql_mode = PIPES_AS_CONCAT, | ||
+ | sync_binlog = 0 | ||
+ | sysdate_is_now = 1 | ||
+ | table_open_cache = 8192 | ||
+ | thread_cache_size = 128 | ||
+ | tmp_table_size = 64M | ||
+ | tmpdir = /tmp | ||
+ | user = mysql" > /etc/my.cnf | ||
+ | |||
+ | - name: Start MySQL | ||
+ | service: name=mysqld state=started enabled=true | ||
+ | |||
+ | - name: Check if a file exist | ||
+ | stat: | ||
+ | path: / | ||
+ | register: mysql_file | ||
+ | |||
+ | - name: Obtain & Change temporal password | ||
+ | shell: | | ||
+ | temporal_password=`awk '/A temporary password is generated for/ {a=$0} END{ print a }' / | ||
+ | mysql -uroot -p${temporal_password} --connect-expired-password -S / | ||
+ | echo " | ||
+ | user=root | ||
+ | password=\" | ||
+ | when: not mysql_file.stat.exists | ||
+ | |||
+ | - name: Create mysql replication user | ||
+ | community.mysql.mysql_user: | ||
+ | login_user: root | ||
+ | login_password: | ||
+ | login_unix_socket: | ||
+ | name: replication | ||
+ | host: ' | ||
+ | priv: " | ||
+ | password: "{{ root_password }}" | ||
+ | </ | ||
+ | |||
+ | 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:// | ||
+ |