CEPH – Perdre 2 serveurs sur 3

Expérience vécue !

Contexte: Chez OVH, nous avons 1 cluster ceph composé de 3 serveurs. Sur chaque serveur, 1 MON, 2 OSD de 2To chaque.
Au total, nous avons 3 MON et 6 OSD, et plusieurs VM KVM utilisent le ceph en backend storage + vRACK OVH pour les flux privés.

Nous décidons de résilier 2 serveurs et de migrer toutes les VM en local pour des raisons diverses (on se concentre sur des containers et on réparti notre infra entre OVH et SCW pour la redondance).

Le jour J arrive, nous perdons les 2 serveurs et surprise, nous avons oublié 1 VM sur le cluster ceph.

*Panique*

Sur le seul serveur restant du cluster, la commande de status hang :

 ceph -s 

Nous avons un REPLICA à 3, on se dit tout n’est pas perdu ! *théoriquement*

1. Nous décidons de reconfigurer la mon map pour déclarer 1 seul MON

– On extrait la monmap active:

# systemctl stop ceph-mon@inxovh-hy001
# ceph-mon -i inxovh-hy001 --extract-monmap /tmp/monmap

– On supprime les 2 MON DOWN

# monmaptool  /tmp/monmap --rm inxovh-hy002
# monmaptool  /tmp/monmap --rm inxovh-hy003

– On réinjecte la monmap :

# ceph-mon -i inxovh-hy001 --inject-monmap /tmp/monmap

– On peut démarrer le mon survivant:

systemctl start ceph-mon@inxovh-hy001

– Ouf ceph -s répond désormais

# ceph -s
cluster:
    id:     0054ab1b-7efb-4456-8e29-db1213048fd6
    health: HEALTH_WARN
            noout flag(s) set
            4 osds down
            2 hosts (4 osds) down
            Reduced data availability: 200 pgs inactive, 200 pgs down
            Degraded data redundancy: 200 pgs unclean
data:
    pools:   3 pools, 200 pgs
    objects: 168k objects, 674 GB
    usage:   675 GB used, 1292 GB / 1968 GB avail
    pgs:     100.000% pgs not active
             200 down

C’est pas glorieux, tous nos PG sont down.

– Les OSD morts sont encore vus UP :

root@inxovh-hy001 (node1):~# ceph osd tree
ID CLASS WEIGHT  TYPE NAME             STATUS REWEIGHT PRI-AFF
-1       6.00000 root default
-2       2.00000     host inxovh-hy001
 4   hdd 1.00000         osd.4             up  1.00000 1.00000
 5   hdd 1.00000         osd.5             up  1.00000 1.00000
-3       2.00000     host inxovh-hy002
 0   hdd 1.00000         osd.0             up  1.00000 1.00000
 1   hdd 1.00000         osd.1             up  1.00000 1.00000
-4       2.00000     host inxovh-hy003
 2   hdd 1.00000         osd.2             up  1.00000 1.00000
 3   hdd 1.00000         osd.3             up  1.00000 1.00000

– OK on les marque down:

root@inxovh-hy001 (node1):~# ceph osd down osd.0
marked down osd.0.
root@inxovh-hy001 (node1):~# ceph osd down osd.1
marked down osd.1.
root@inxovh-hy001 (node1):~# ceph osd down osd.2
marked down osd.2.
root@inxovh-hy001 (node1):~# ceph osd down osd.3
marked down osd.3.

– c’est mieux au niveau osd tree

root@inxovh-hy001 (node1):~# ceph osd tree
ID CLASS WEIGHT  TYPE NAME             STATUS REWEIGHT PRI-AFF
-1       6.00000 root default
-2       2.00000     host inxovh-hy001
 4   hdd 1.00000         osd.4             up  1.00000 1.00000
 5   hdd 1.00000         osd.5             up  1.00000 1.00000
-3       2.00000     host inxovh-hy002
 0   hdd 1.00000         osd.0           down  1.00000 1.00000
 1   hdd 1.00000         osd.1           down  1.00000 1.00000
-4       2.00000     host inxovh-hy003
 2   hdd 1.00000         osd.2           down  1.00000 1.00000
 3   hdd 1.00000         osd.3           down  1.00000 1.00000

– Mais le cluster (ce qui en reste) est toujours pas utilisable

root@inxovh-hy001 (node1):~# ceph -s
  cluster:
    id:     0054ab1b-7efb-4456-8e29-db1213048fd6
    health: HEALTH_WARN
            noout flag(s) set
            4 osds down
            2 hosts (4 osds) down
            Reduced data availability: 109 pgs inactive, 200 pgs down
            Degraded data redundancy: 200 pgs unclean

  services:
    mon: 1 daemons, quorum inxovh-hy001
    mgr: inxovh-hy001(active)
    osd: 6 osds: 2 up, 6 in
         flags noout

  data:
    pools:   3 pools, 200 pgs
    objects: 168k objects, 674 GB
    usage:   675 GB used, 1292 GB / 1968 GB avail
    pgs:     100.000% pgs not active
             200 down

  io:
    client:   289 GB/s rd, 1120 GB/s wr, 70215 kop/s rd, 41429 kop/s wr
    recovery: 525 GB/s, 784 keys/s, 131 kobjects/s

– A ce moment, on se dit “est ce qu’on a bien un replica a 3 au fait ?”. Allez on vérifie

root@inxovh-hy001 (node1):~#  ceph osd dump | grep "^pool"
pool 0 'data' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 39347 flags hashpspool stripe_width 0 application rbd
pool 6 'libvirt-pool' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 128 pgp_num 128 last_change 39348 flags hashpspool stripe_width 0 application rbd
pool 7 '.rgw.root' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 39344 owner 18446744073709551615 flags hashpspool stripe_width 0 application rgw

Ouf.

– En regardant le status détaillé, on voit que plein de pg sont dans un état paralysé

# ceph health detail

# ceph pg 6.3f query

J’ai plus le output mais en gros, ca nous dit qu’il faut passer les osd down en lost.

{ "state": "down+peering",
...
 "blocked": "peering is blocked due to down osds",
         "down_osds_we_would_probe": [
               1],
   "peering_blocked_by": [
               { "osd": 1,
                 "current_lost_at": 0,
                 "comment": "starting or marking this osd lost may let us proceed"}]},

– On passe les OSD down en LOST

# ceph osd lost osd.0
Error EPERM: are you SURE?  this might mean real, permanent data loss.  pass–yes-i-really-mean-it if you really do.

– Pas très rassurant, mais on y va en se disant qu’il y aura pas de retour arrière possible (appeler OVH et leur demander de rallumer les serveurs en payant 1 mois supplémentaire).

 root@inxovh-hy001 (node1):/var/log/ceph# ceph osd lost osd.0 --yes-i-really-mean-it
marked osd lost in epoch 39718
 root@inxovh-hy001 (node1):/var/log/ceph# ceph osd lost osd.1 --yes-i-really-mean-it
marked osd lost in epoch 39718
 root@inxovh-hy001 (node1):/var/log/ceph# ceph osd lost osd.2 --yes-i-really-mean-it
marked osd lost in epoch 39718
 root@inxovh-hy001 (node1):/var/log/ceph# ceph osd lost osd.3 --yes-i-really-mean-it
marked osd lost in epoch 39718

– A ce moment, ca marche toujours pas, l’erreur est que la condition min_size n’est pas honoré et en effet, elle est à 2 alors que nous avons 1 seul serveur. On le met à 1:

root@inxovh-hy001 (node1):/var/log/ceph# ceph osd pool set libvirt-pool min_size 1

– Hourra, tout remarche

– On exporte la VM qui restait

root@inxovh-hy001 (node1):~# rbd export  libvirt-pool/dnxovh-web001_data /zdata/vms/dnxovh-web001_data.img
Exporting image: 100% complete...done.

We are happy.

Authentifier Apache vers IMAP

Authentifier Apache vers IMAP

Pour avoir une DB user unique, je suis parti sur ma source d’utilisateur et dans mon cas c’est postfixadmin pour les mails.
Du coup; je me suis amusé à écrire un petit bout perl qui permet à apache de s’auth vers un serveur IMAP.

  • Installer les dépendances
    apt-get install libnet-imap-simple-ssl-perl
    apt-get install libunix-syslog-perl
    apt-get install libapache2-mod-authnz-external
    
  • Protéger les pages Xymon avec l’auth IMAP
     cat /etc/apache2/conf-enabled/xymon.conf
    DefineExternalAuth dovecotpw pipe /etc/apache2/auth/dovecotpw.pl
    
    ScriptAlias /xymon-cgi "/usr/lib/xymon/cgi-bin"
    Directory "/usr/lib/xymon/cgi-bin"
        AllowOverride None
        Options ExecCGI Includes
    
        
    
            AuthType Basic
            AuthName "Xymon Administration"
            Require valid-user
            AuthBasicProvider external
            AuthExternal dovecotpw
    
        
    
  • Ensuite le code perl
     cat /etc/apache2/auth/dovecotpw.pl
    
    #!/usr/bin/perl
    use strict;
    use warnings;
    use Unix::Syslog qw(:macros :subs);
    use Net::IMAP::Simple::SSL;
    
    my $VERSION = '1.0';
    
    my $server = 'imap.distran.org';
    my $port = 993;
    my $use_ssl = 1;
    
    syslog LOG_INFO,"imap-auth: waiting for packet";
    chomp(my $user = );
    chomp(my $password = );
    my $result;
    #print "checking [$user] and [$password]\n";
    syslog(LOG_INFO,"imap-auth: request ('auth', \"$user\", '****')");
    
    # successful authentication
    if (is_valid($user, $password)){
          	$result = 0;
           	syslog(LOG_INFO,"imap-auth: -> +OK");
    } else {
             $result = 1;
    }
    
    closelog;
    exit $result;
    
    sub is_valid
    {
    	my ($user, $password) = @_;
    	my $is_valid = 0;
    
    	# Create the object
    	my $imap = Net::IMAP::Simple->new($server,
    		(
    			port => $port,
    			use_ssl => $use_ssl
    		) ) ||
    
    	die "Unable to connect to IMAP: $Net::IMAP::Simple::errstr\n";
    
    	$imap->starttls;
         	if ( $imap->login("$user", $password) ) {
    		$is_valid = 1;
           	         syslog(LOG_INFO,"imap-auth: -> +OK imap server says you're cool. Welcome.");
    	} else {
           	         syslog(LOG_INFO,"imap-auth: -> -ERR imap server has a problem with you: $! $_ $/ " . $imap->errstr);
    	}
    
    	$imap->quit;
    
    	return ($is_valid);
    }
    
    
  • Check des logs
     tail /var/log/syslog
    
    Nov 24 13:01:05 xymon-server01 perl: imap-auth: waiting for packet
    Nov 24 13:01:05 xymon-server01 perl: imap-auth: request ('auth', "user@domain.com", '****')
    Nov 24 13:01:05 xymon-server01 perl: imap-auth: -> +OK imap server says you're cool. Welcome.
    Nov 24 13:01:05 xymon-server01 perl: imap-auth: -> +OK
    
    
  • Si le serveur IMAP est local sur la meme machine
     cat /etc/apache2/auth/dovecotpw.sh
    #!/bin/bash
    read DCUSER
    read DCPASS
    /usr/bin/doveadm auth ${DCUSER} ${DCPASS}
    exit $?
    
  • Test de Post depuis un script Perl

    test from Command line

    Code source:

    
    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use WordPress::XMLRPC;
    
    my $o = WordPress::XMLRPC->new({
     username => 'thot',
     password => 'xxxxxxx',
     proxy => 'http://distran.org/xmlrpc.php',
     });
    
    my $article;
     $article->{title} = "Test de Post depuis un script Perl";
     $article->{categories} = ['Vrac'];
     $article->{description} = "test from Command line";
    
    $o->newPost($article,1);
    
    

    Ne pas oublier d’installer le port p5-WordPress-XMLRPC

    # portinstall p5-WordPress-XMLRPC