Nota

Imposta un failover IP virtuale Linux su Oracle Cloud Infrastructure gestito da Pacemaker

Introduzione

In molti ambienti, è ancora essenziale utilizzare infrastrutture con un cluster Linux attivo o passivo, che richiedono l'uso di IP fluttuanti. Nell'infrastruttura cloud, l'indirizzo IP secondario deve essere gestito non solo dal sistema operativo ma anche dall'infrastruttura cloud.

In questo tutorial vedremo come l'IP mobile di un cluster Linux può essere gestito come risorsa integrata da Pacemaker, in modo semplice e senza codice personalizzato. Per ulteriori informazioni, vedere Task 3: Impostare il cluster Samba e Failover IP virtuale automatico su Oracle Cloud Infrastructure.

Architettura

immagine

Obiettivi

Prerequisiti

Task 1: Impostare l'ambiente

  1. Avviare due istanze di computazione, selezionare Ubuntu 22 come sistema operativo per ogni istanza.

  2. Assegnare un indirizzo IP privato secondario alla scheda di interfaccia di rete virtuale (VNIC) a node1. Per ulteriori informazioni, vedere Assegnazione di un nuovo IP privato secondario a una VNIC. Questo sarà l'IP mobile. Ad esempio, 10.10.1.115.

  3. Crea un gruppo dinamico.

    1. Eseguire il login alla console OCI, passare a Identità e sicurezza, Gruppi dinamici e fare clic su Crea gruppo dinamico.

    2. Immettere le informazioni riportate di seguito.

      • Nome: immettere OCIVIP.
      • Aggiungere la regola seguente per includere le istanze nel compartimento specificato.

        All {instance.compartment.id = 'Your compartment OCI ID'}
        
  4. Aggiungere un criterio al gruppo dinamico.

    1. Passare a Identità e sicurezza, Criteri e fare clic su Crea criterio.

    2. Immettere le informazioni riportate di seguito.

      • Nome: immettere OCIVIP_policy.

      • Aggiungere la seguente istruzione per consentire al gruppo dinamico di utilizzare la famiglia di reti virtuali:

        allow dynamic-group OracleIdentityCloudService/OCIVIP to use virtual-network-family in compartment id 'Your compartment OCI ID'
        

Task 2: configurare il cluster e l'IP mobile

Dopo aver configurato l'ambiente, possiamo procedere alla configurazione di Pacemaker e all'integrazione dell'agente delle risorse OCIVIP. Connettersi alle istanze utilizzando SSH ed eseguire le operazioni di installazione del cluster su entrambi i nodi fino al passo 10 incluso.

  1. Aggiornare il sistema operativo.

    sudo apt update
    sudo apt upgrade
    
  2. Installare l'interfaccia CLI OCI e verificarne le funzionalità.

    bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"
    

    Impostare l'interfaccia CLI OCI.

    oci setup config
    

    Verificare l'installazione dell'interfaccia CLI OCI.

    oci os ns get
    
  3. Per un ambiente di test, è possibile rimuovere la regola di rifiuto alla riga 6 nella sezione INPUT di iptables, quindi renderla persistente per consentire la comunicazione dell'istanza. Ricordarsi di configurare iptables in modo sicuro e appropriato negli ambienti di produzione.

    sudo iptables -D INPUT 6
    sudo su
    sudo iptables-save > /etc/iptables/rules.v4
    sudo ip6tables-save > /etc/iptables/rules.v6
    
  4. Aggiornare il file /etc/hosts con gli indirizzi IP privati assegnati alle due istanze: node1 e node2.

    Eseguire il comando seguente per modificare il file.

    sudo nano /etc/hosts
    

    Aggiungere i nomi dei nodi e gli indirizzi IP.

    10.10.1.111 node1
    10.10.1.118 node2
    
  5. Installare i pacchetti correlati al cluster, incluso jq.

    sudo apt install -y pacemaker corosync pcs jq
    
  6. Eseguire il backup del file corosync.conf.

    sudo cp /etc/corosync/corosync.conf /etc/corosync/corosync.conf.bk
    

    Modificare il file corosync.conf.

    sudo nano /etc/corosync/corosync.conf
    

    Copiare il contenuto seguente nel file corosync.conf.

     # Please read the corosync.conf.5 manual page
     system {
             # This is required to use transport=knet in an unprivileged
             # environment, such as a container. See man page for details.
             allow_knet_handle_fallback: yes
     }
    
     totem {
             version: 2
    
             # Corosync itself works without a cluster name, but DLM needs one.
             # The cluster name is also written into the VG metadata of newly
             # created shared LVM volume groups, if lvmlockd uses DLM locking.
            cluster_name: ha_cluster
             transport: udpu
             secauth: off
             # crypto_cipher and crypto_hash: Used for mutual node authentication.
             # If you choose to enable this, then do remember to create a shared
             # secret with "corosync-keygen".
             # enabling crypto_cipher, requires also enabling of crypto_hash.
             # crypto works only with knet transport
             crypto_cipher: none
             crypto_hash: none
     }
    
     logging {
             # Log the source file and line where messages are being
             # generated. When in doubt, leave off. Potentially useful for
             # debugging.
             fileline: off
             # Log to standard error. When in doubt, set to yes. Useful when
             # running in the foreground (when invoking "corosync -f")
             to_stderr: yes
             # Log to a log file. When set to "no", the "logfile" option
             # must not be set.
             to_logfile: yes
             logfile: /var/log/corosync/corosync.log
             # Log to the system log daemon. When in doubt, set to yes.
             to_syslog: yes
             # Log debug messages (very verbose). When in doubt, leave off.
             debug: off
             # Log messages with time stamps. When in doubt, set to hires (or on)
             #timestamp: hires
             logger_subsys {
                     subsys: QUORUM
                     debug: off
             }
     }
    
     quorum {
             # Enable and configure quorum subsystem (default: off)
             # see also corosync.conf.5 and votequorum.5
             provider: corosync_votequorum
             two_node: 1
             wait_for_all: 1
             last_man_standing: 1
             auto_tie_breaker: 0
     }
    
     nodelist {
             # Change/uncomment/add node sections to match cluster configuration
    
             node {
                     # Hostname of the node.
                     # name: node1
                     # Cluster membership node identifier
                     nodeid: 101
                     # Address of first link
                     ring0_addr: node1
                     # When knet transport is used it's possible to define up to 8 links
                     #ring1_addr: 192.168.1.1
             }
             # ...
             node {
                     ring0_addr: node2
                     nodeid: 102
                 }
    }
    
  7. Aggiungere la risorsa che Pacemaker utilizzerà per gestire in modo nativo l'IP mobile OCI nella directory /usr/lib/ocf/resource.d/heartbeat/. Scaricare il contenuto del file da qui: ocivip.txt.

    Nota: questa risorsa non è sviluppata da Oracle, ma da sviluppatori di terze parti.

    Questo è il contenuto del file ocivip.

    #!/bin/sh
    #
    #
    # Manage Secondary Private IP in Oracle Cloud Infrastructure with Pacemaker
    #
    #
    # Copyright 2016-2018 Lorenzo Garuti <garuti.lorenzo@gmail.com>
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    #
    
    #
    #  Prerequisites:
    #
    #  - OCI CLI installed (https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/climanualinst.htm)
    #  - jq installed
    #  - dynamic group with a policy attached
    #  - the policy must have this statement:
    #    allow dynamic-group <GROUP_NAME> to use virtual-network-family in compartment id <COMPARTMENT_ID>
    #  - a reserved secondary private IP address for Compute Instances high availability
    #
    
    #######################################################################
    # Initialization:
    
    : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
    . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
    
    #######################################################################
    
    #
    # Defaults
    #
    OCF_RESKEY_ocicli_default="/usr/local/bin/oci"
    OCF_RESKEY_api_delay_default="3"
    OCF_RESKEY_cidr_netmask_default="24"
    OCF_RESKEY_interface_alias_default="0"
    export OCI_CLI_AUTH=instance_principal
    
    : ${OCF_RESKEY_ocicli=${OCF_RESKEY_ocicli_default}}
    : ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}}
    : ${OCF_RESKEY_cidr_netmask=${OCF_RESKEY_cidr_netmask_default}}
    : ${OCF_RESKEY_interface_alias=${OCF_RESKEY_interface_alias_default}}
    
    meta_data() {
        cat <<END
    <?xml version="1.0"?>
    <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
    <resource-agent name="ocivip">
    <version>1.0</version>
    
    <longdesc lang="en">
    Resource Agent for OCI Compute instance Secondary Private IP Addresses.
    
    It manages OCI Secondary Private IP Addresses for Compute instances with oci cli.
    
    See https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm for more information about oci cli.
    
    Prerequisites:
    
    - OCI CLI installed (https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/climanualinst.htm)
    - jq installed
    - dynamic group with a policy attached
    - the policy must have this statement: allow dynamic-group GROUP_NAME to use virtual-network-family in compartment id COMPARTMENT_ID
    - a reserved secondary private IP address for Compute Instances high availability
    
    </longdesc>
    <shortdesc lang="en">OCI Secondary Private IP Address for Compute instances Resource Agent</shortdesc>
    
    <parameters>
    
    <parameter name="ocicli" unique="0">
    <longdesc lang="en">
    OCI Command line interface (CLI) tools
    </longdesc>
    <shortdesc lang="en">OCI cli tools</shortdesc>
    <content type="string" default="${OCF_RESKEY_ocicli_default}" />
    </parameter>
    
    <parameter name="secondary_private_ip" unique="1" required="1">
    <longdesc lang="en">
    reserved secondary private ip for compute instance
    </longdesc>
    <shortdesc lang="en">reserved secondary private ip for compute instance</shortdesc>
    <content type="string" default="" />
    </parameter>
    
    <parameter name="cidr_netmask" unique="0">
    <longdesc lang="en">
    netmask for the secondary_private_ip
    </longdesc>
    <shortdesc lang="en">netmask for the secondary_private_ip</shortdesc>
    <content type="integer" default="${OCF_RESKEY_cidr_netmask_default}" />
    </parameter>
    
    <parameter name="interface_alias" unique="0">
    <longdesc lang="en">
    numeric alias for the interface
    </longdesc>
    <shortdesc lang="en">numeric alias for the interface</shortdesc>
    <content type="integer" default="${OCF_RESKEY_interface_alias_default}" />
    </parameter>
    
    <parameter name="api_delay" unique="0">
    <longdesc lang="en">
    a short delay between API calls, to avoid sending API too quick
    </longdesc>
    <shortdesc lang="en">a short delay between API calls</shortdesc>
    <content type="integer" default="${OCF_RESKEY_api_delay_default}" />
    </parameter>
    
    </parameters>
    
    <actions>
    <action name="start"        timeout="30s" />
    <action name="stop"         timeout="30s" />
    <action name="monitor"      timeout="30s" interval="20s" depth="0" />
    <action name="migrate_to"   timeout="30s" />
    <action name="migrate_from" timeout="30s" />
    <action name="meta-data"    timeout="5s" />
    <action name="validate"     timeout="10s" />
    <action name="validate-all" timeout="10s" />
    </actions>
    </resource-agent>
    END
    }
    
    #######################################################################
    
    ocivip_usage() {
        cat <<END
    usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate|validate-all|meta-data}
    
    Expects to have a fully populated OCF RA-compliant environment set.
    END
    }
    
    ocivip_start() {
        ocivip_monitor && return $OCF_SUCCESS
    
        $OCICLI network vnic assign-private-ip --vnic-id $VNIC_ID \
            --unassign-if-already-assigned \
            --ip-address ${SECONDARY_PRIVATE_IP}
        RETOCI=$?
        ip addr add ${SECONDARY_PRIVATE_IP}/${CIDR_NETMASK} dev ${PRIMARY_IFACE} label ${PRIMARY_IFACE}:${INTERFACE_ALIAS}
        RETIP=$?
    
        # delay to avoid sending request too fast
        sleep ${OCF_RESKEY_api_delay}
    
        if [ $RETOCI -ne 0 ] || [ $RETIP -ne 0 ]; then
            return $OCF_NOT_RUNNING
        fi
    
        ocf_log info "secondary_private_ip has been successfully brought up (${SECONDARY_PRIVATE_IP})"
        return $OCF_SUCCESS
    }
    
    ocivip_stop() {
        ocivip_monitor || return $OCF_SUCCESS
    
        $OCICLI network vnic unassign-private-ip --vnic-id $VNIC_ID \
            --ip-address ${SECONDARY_PRIVATE_IP}
        RETOCI=$?
        ip addr del ${SECONDARY_PRIVATE_IP}/${CIDR_NETMASK} dev ${PRIMARY_IFACE}:${INTERFACE_ALIAS}
        RETIP=$?
    
        # delay to avoid sending request too fast
        sleep ${OCF_RESKEY_api_delay}
    
        if [ $RETOCI -ne 0 ] || [ $RETIP -ne 0 ]; then
            return $OCF_NOT_RUNNING
        fi
    
        ocf_log info "secondary_private_ip has been successfully brought down (${SECONDARY_PRIVATE_IP})"
        return $OCF_SUCCESS
    }
    
    ocivip_monitor() {
        $OCICLI network private-ip list --vnic-id $VNIC_ID | grep -q "${SECONDARY_PRIVATE_IP}"
        RETOCI=$?
    
        if [ $RETOCI -ne 0 ]; then
            return $OCF_NOT_RUNNING
        fi
        return $OCF_SUCCESS
    }
    
    ocivip_validate() {
        check_binary ${OCICLI}
        check_binary jq
    
        if [ -z "${VNIC_ID}" ]; then
            ocf_exit_reason "vnic_id not found. Is this a Compute instance?"
            return $OCF_ERR_GENERIC
        fi
    
        return $OCF_SUCCESS
    }
    
    case $__OCF_ACTION in
        meta-data)
            meta_data
            exit $OCF_SUCCESS
            ;;
    esac
    
    OCICLI="${OCF_RESKEY_ocicli}"
    SECONDARY_PRIVATE_IP="${OCF_RESKEY_secondary_private_ip}"
    CIDR_NETMASK="${OCF_RESKEY_cidr_netmask}"
    INTERFACE_ALIAS="${OCF_RESKEY_interface_alias}"
    VNIC_ID="$(curl -s -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/vnics/ | jq -r '.[0].vnicId')"
    PRIMARY_IFACE=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -n1)
    
    case $__OCF_ACTION in
        start)
            ocivip_validate || exit $?
            ocivip_start
            ;;
        stop)
            ocivip_stop
            ;;
        monitor)
            ocivip_monitor
            ;;
        migrate_to)
            ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}."
            ocivip_stop
            ;;
        migrate_from)
            ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}."
            ocivip_start
            ;;
        reload)
            ocf_log info "Reloading ${OCF_RESOURCE_INSTANCE} ..."
            ;;
        validate|validate-all)
            ocivip_validate
            ;;
        usage|help)
            ocivip_usage
            exit $OCF_SUCCESS
            ;;
        *)
            ocivip_usage
            exit $OCF_ERR_UNIMPLEMENTED
            ;;
    esac
    
    rc=$?
    ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
    exit $rc
    
  8. Modificare il file ocivip e il percorso dell'eseguibile dell'interfaccia CLI OCI nella variabile OCF_RESKEY_ocicli_default con il percorso dell'interfaccia CLI OCI.

    Se durante l'installazione dell'interfaccia CLI OCI in Ubuntu è stato mantenuto il percorso predefinito, la variabile sarà /home/ubuntu/bin/oci.

    OCF_RESKEY_ocicli_default="/home/ubuntu/bin/oci"
    

    Creare il file e copiare il codice scaricato dal passo 7 con la variabile aggiornata.

    sudo nano /usr/lib/ocf/resource.d/heartbeat/ocivip
    

    Modificare l'autorizzazione e il proprietario del file.

    sudo chown root /usr/lib/ocf/resource.d/heartbeat/ocivip
    sudo chmod 755 /usr/lib/ocf/resource.d/heartbeat/ocivip
    
  9. Attivare al boot e riavviare i servizi, nonché verificare che funzionino correttamente.

    sudo systemctl enable corosync
    sudo systemctl enable pacemaker
    sudo systemctl enable pcsd
    sudo systemctl restart pcsd
    sudo systemctl restart corosync
    sudo systemctl restart pacemaker
    sudo systemctl status pcsd
    sudo systemctl status corosync
    sudo systemctl status pacemaker
    
  10. Impostare la password per l'utente ocicluster.

    sudo passwd ocicluster
    
  11. Eseguire il comando riportato di seguito per autenticare i nodi.

    sudo pcs cluster auth node1 node2 -u ocicluster -p YOUR_PASSWORD
    
  12. Creare il cluster.

    sudo pcs cluster setup ha_cluster node1 node2
    
  13. Avviare e abilitare il cluster al boot su tutti i nodi.

    sudo pcs cluster start --all
    sudo pcs cluster enable --all
    
  14. Verificare che il cluster sia attivo e funzionante.

    sudo pcs status
    
  15. Aggiungere la risorsa OCIVIP per la gestione dell'IP mobile.

    Nota: modificare l'indirizzo IP virtuale in quello assegnato come secondario alla VNIC nel passo 2 di questa esercitazione.

    sudo pcs resource create OCIVIP ocf:heartbeat:ocivip secondary_private_ip="10.10.1.115" cidr_netmask="24" op monitor timeout="30s" interval="20s" OCF_CHECK_LEVEL="0"
    
  16. Verificare che la risorsa sia stata aggiunta correttamente e che funzioni correttamente.

    sudo pcs status
    
  17. Verificare che l'indirizzo IP secondario possa eseguire la migrazione tra le istanze, ad esempio riavviando node1, e controllare che OCI Console sia assegnato all'altra istanza e viceversa.

    Prima di riavviare node1, è anche possibile eseguire il ping dell'indirizzo mobile da una terza virtual machine e verificare che continui a rispondere dopo l'arresto di node1. Una breve interruzione di qualche luppolo è normale.

Il cluster attivo e passivo è attivo e in esecuzione. È ora possibile aggiungere i servizi che richiedono continuità aziendale.

conferme

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi a più contenuti gratuiti sulla formazione su Oracle Learning YouTube channel. Inoltre, visita education.oracle.com/learning-explorer per diventare un Oracle Learning Explorer.

Per la documentazione del prodotto, visita l'Oracle Help Center.