Έναρξη του εργαστηρίου και περιήγηση στις διεπαφές

11 λεπτά
Κοινό
αρχάριος, τα προαπαιτούμενα του μαθήματος 02 όλα πράσινα
Διάρκεια
30 λεπτά (συν το πρώτο κατέβασμα των εικόνων)
Ενότητα
1/7
Στοχευόμενη δεξιότητα
να ξεκινάς το stack, να φορτώνεις τα δεδομένα, να διαβάζεις το etat, να στέλνεις ένα πρώτο ερώτημα στο Kibana Dev Tools και στο Neo4j Browser

Σε μία εικόνα

Η εκκίνηση του εργαστηρίου είναι σαν να ανάβεις ένα κτίριο τριών ορόφων. Το demarrer πατά τον γενικό διακόπτη, μετά ένας θυρωρός περνά από κάθε όροφο για να επαληθεύσει ότι το φως είναι πράγματι αναμμένο πριν σου δώσει τα κλειδιά: αυτός ο θυρωρός είναι τα healthchecks του Docker Compose. Το Kibana δεν έχει καν το δικαίωμα να ξεκινήσει πριν το Elasticsearch δηλωθεί υγιές. Στη συνέχεια το importer γεμίζει τα ράφια του Elasticsearch, το charger-graphe γεμίζει αυτά του Neo4j, και το etat σου δίνει τον χάρτη του κτιρίου: ποιος είναι εκεί, ποιος απαντά, πόσα έγγραφα σε κάθε index. Το υπόλοιπο του μαθήματος είναι μια ξενάγηση στα δύο δωμάτια όπου θα περάσεις το μάθημα: την κονσόλα Dev Tools του Kibana και το Neo4j Browser.

Πώς λειτουργεί

Το demarrer αλυσιδώνει τρία βήματα του docker compose: pull (κατεβάζει τις εικόνες, ~6 GB την πρώτη φορά, τίποτα μετά), up -d (δημιουργεί και εκκινεί τα κοντέινερ στο παρασκήνιο), μετά ένας βρόχος αναμονής που ρωτά το docker inspect κάθε 3 δευτερόλεπτα μέχρι κάθε κοντέινερ να γίνει healthy.

Η λέξη healthy προέρχεται από το docker-compose.yml. Κάθε υπηρεσία δηλώνει εκεί ένα τεστ που το Docker επαναλαμβάνει τακτικά:

ΥπηρεσίαΤεστ που εκτελείται στο κοντέινερΡυθμός
elasticsearchτο curl -fsS http://localhost:9200/_cluster/health πρέπει να περιέχει "status":"green" ή "yellow"κάθε 10 δ., 30 προσπάθειες, 30 δ. χάριτος στην εκκίνηση
kibanaτο curl -fsS http://localhost:5601/api/status πρέπει να περιέχει "level":"available"κάθε 10 δ., 30 προσπάθειες, 40 δ. χάριτος
neo4jτο wget -qO- http://localhost:7474 απαντάκάθε 10 δ., 30 προσπάθειες, 30 δ. χάριτος

Όσο το τεστ αποτυγχάνει, το κοντέινερ είναι starting· όταν πετυχαίνει, healthy· μετά από 30 αποτυχίες, unhealthy. Η υπηρεσία kibana δηλώνει depends_on: elasticsearch: condition: service_healthy: το Compose την εκκινεί μόνο αφού το Elasticsearch γίνει healthy, κάτι που αποφεύγει το περίφημο «Kibana server is not ready yet» κατά την εκκίνηση.

Δύο λεπτομέρειες του αρχείου compose αξίζει να ειπωθούν από τώρα. xpack.security.enabled=false: κανένας κωδικός πρόσβασης ούτε πιστοποιητικό για το Elasticsearch, είναι ένα τοπικό εργαστήριο, ποτέ διαμόρφωση παραγωγής. cluster.routing.allocation.disk.threshold_enabled=false: το Elasticsearch δεν θα θέσει τα index σου σε λειτουργία μόνο ανάγνωσης αν ο δίσκος σου υπερβεί το 95% (μάθημα 04, βλάβη αρ. 5).

Βήμα προς βήμα

Πρώτα το kit του εργαστηρίου. Όλα τα παρακάτω εκτελούνται από τη ρίζα του kit — https://github.com/hrhouma2/aiopsatlas-recherche-graphes-labo-fr — που αποκτήθηκε με git clone https://github.com/hrhouma2/aiopsatlas-recherche-graphes-labo-fr ή με το κουμπί Code → Download ZIP (μάθημα 02, βήμα 4). Αν το dir (ή το ls) δεν δείχνει τα docker-compose.yml, labo.sh και labo.ps1, δεν βρίσκεσαι στο σωστό μέρος.

Όλα τα ερωτήματα αυτού του μαθήματος: elasticsearch/requetes/01-03-premiere-visite.txt.

  1. Εκκίνηση του stack. Από τον φάκελο του kit:

    bash
    ./labo.sh demarrer
    powershell
    .\labo.ps1 demarrer

    Το σενάριο εμφανίζει τρία μπλοκ: == Téléchargement des images == (μεγάλο την πρώτη φορά, σιωπηλό μετά), == Démarrage == (οι γραμμές Container labo-elasticsearch Started του Compose), μετά == Attente que chaque service soit prêt == όπου κάθε γραμμή γεμίζει με τελείες μέχρι prêt (…s). Τελειώνει με:

    text
    Le labo est prêt.
      Kibana                 http://localhost:5601   (Dev Tools : menu ☰ → Management → Dev Tools)
      Elasticsearch          http://localhost:9200
      Neo4j Browser          http://localhost:7474   (utilisateur neo4j · mot de passe aiopsatlas2026)
    
    Étape suivante : ./labo.sh importer   puis   ./labo.sh charger-graphe

    Αυτό που πρέπει να δεις: τρία prêt (έτοιμο) (elasticsearch, kibana, neo4j). Υπολόγισε ένα με δύο λεπτά μετά το κατέβασμα. Αν μια γραμμή εμφανίζει unhealthy, exited ή délai dépassé (υπέρβαση προθεσμίας), πήγαινε στο μάθημα 04.

  2. Φόρτωση των index Elasticsearch.

    bash
    ./labo.sh importer

    Η εντολή δημιουργεί κάθε index με το mapping του (αρχεία elasticsearch/mappings/*.json) μετά στέλνει τα δεδομένα στο API _bulk. Πραγματική έξοδος, εδώ σε ένα εργαστήριο όπου τα index υπήρχαν ήδη (η εντολή επαναλαμβάνεται χωρίς κίνδυνο):

    text
    == Import dans elasticsearch ==
    — index cours existe déjà — conservé
      ✔ données cours chargées
    — index avis existe déjà — conservé
      ✔ données avis chargées
    — index acces existe déjà — conservé
      ✔ données acces chargées
    
    index docs.count store.size
    acces      12000      1.5mb
    avis         609     74.6kb
    cours        504    183.6kb
    
    Import terminé. Attendu : cours = 504, avis = 609, acces = 12000.

    Αυτό που πρέπει να δεις: την πρώτη φορά, οι γραμμές γίνονται ✔ index cours créé avec son mapping. Οι τρεις μετρητές πρέπει να είναι ακριβώς 504, 609 και 12000· τα έγγραφα φέρουν το δικό τους _id, οπότε η επανεκτέλεση της εισαγωγής δεν δημιουργεί ποτέ διπλότυπο.

  3. Φόρτωση του γράφου Neo4j.

    bash
    ./labo.sh charger-graphe

    Το σενάριο εκτελεί το neo4j/cypher/01-contraintes.cypher (περιορισμοί μοναδικότητας και index) μετά το 02-charger.cypher (LOAD CSV + MERGE για κάθε αρχείο του neo4j/import/). Τελειώνει με τον απολογισμό που υπολογίζει το τελευταίο ερώτημα του σεναρίου, MATCH (n) RETURN labels(n)[0] AS etiquette, count(*) AS noeuds ORDER BY etiquette:

    text
    etiquette, noeuds
    "Competence", 22
    "Cours", 504
    "Etudiant", 300
    "Professeur", 30
    "Ville", 16
    
    Graphe chargé. Attendu : Competence 22, Cours 504, Etudiant 300, Professeur 30, Ville 16.

    Αυτό που πρέπει να δεις: 872 κόμβοι συνολικά. Όλα γίνονται με MERGE, οπότε η επανεκτέλεση της εντολής δεν δημιουργεί κανένα διπλότυπο.

  4. Ανάγνωση της κατάστασης του εργαστηρίου. Είναι η εντολή που θα πληκτρολογείς πιο συχνά:

    bash
    ./labo.sh etat

    Πραγματική έξοδος (εδώ με το ενεργό προφίλ OpenSearch, που δεν θα εμφανιστεί σε σένα πριν την ενότητα 5):

    text
    == Conteneurs ==
    NAME                         STATUS                    PORTS
    labo-elasticsearch           Up 16 minutes (healthy)   0.0.0.0:9200->9200/tcp, [::]:9200->9200/tcp
    labo-kibana                  Up 16 minutes (healthy)   0.0.0.0:5601->5601/tcp, [::]:5601->5601/tcp
    labo-neo4j                   Up 14 minutes (healthy)   0.0.0.0:7474->7474/tcp, [::]:7474->7474/tcp, 0.0.0.0:7687->7687/tcp, [::]:7687->7687/tcp
    labo-opensearch              Up 16 minutes (healthy)   0.0.0.0:9201->9200/tcp, [::]:9201->9200/tcp
    labo-opensearch-dashboards   Up 16 minutes             0.0.0.0:5602->5601/tcp, [::]:5602->5601/tcp
    
    == Services ==
      ✔ Elasticsearch : {"status":"green","number_of_nodes":1}
         index : acces 12000 avis    609 cours   504
      ✔ Kibana répond (http://localhost:5601)
      ✔ Neo4j répond — nœuds : 872
      ✔ OpenSearch : {"status":"green","number_of_nodes":1}

    Αυτό που πρέπει να δεις: (healthy) σε κάθε γραμμή κοντέινερ, green για το cluster, τους τρεις μετρητές index και 872 κόμβους. Χωρίς OpenSearch, η τελευταία γραμμή λέει — OpenSearch non démarré (profil optionnel : ./labo.sh demarrer opensearch).

  5. Άνοιγμα του Kibana Dev Tools. Πήγαινε στο http://localhost:5601. Το Kibana είναι στα γαλλικά (I18N_LOCALE=fr-FR). Κάνε κλικ στο μενού πάνω αριστερά· στην ενότητα Management, επίλεξε Outils de développement (είναι η μετάφραση του «Dev Tools»· το breadcrumb εμφανίζει Outils de développement > Console). Φτάνεις στην καρτέλα Console, υποκαρτέλα Shell: έναν επεξεργαστή αριστερά, την απάντηση δεξιά. Το κουμπί Effacer cette entrée αδειάζει τον επεξεργαστή από το παράδειγμα.

    Αυτό που πρέπει να δεις: όταν πληκτρολογείς ένα ερώτημα, εμφανίζεται ένα κουμπί ▶ («Cliquer pour envoyer la requête») στο τέλος της γραμμής. Συντόμευση: Ctrl + Enter (⌘ + Enter σε Mac) στέλνει το ερώτημα κάτω από τον δρομέα. Κάτω δεξιά της απάντησης, το Kibana εμφανίζει τον κωδικό HTTP και τη διάρκεια, για παράδειγμα 200 - OK 23 ms.

  6. Πρώτο ερώτημα: η υγεία του cluster.

    text
    GET _cluster/health
    json
    {
      "cluster_name": "labo",
      "status": "green",
      "timed_out": false,
      "number_of_nodes": 1,
      "number_of_data_nodes": 1,
      "active_primary_shards": 53,
      "active_shards": 53,
      "unassigned_shards": 0,
    
      "active_shards_percent_as_number": 100
    }

    Αυτό που πρέπει να δεις: "status": "green". Τα index του εργαστηρίου δημιουργούνται με number_of_replicas: 0, άρα κανένα replica σε αναμονή: green σε έναν μόνο κόμβο. Ο αριθμός των shards (53) περιλαμβάνει index συστήματος του Kibana· μπορεί να διαφέρει.

  7. Ποιος απαντά, και ποια index υπάρχουν;

    text
    GET /

    Απάντηση: "name": "labo-es-1", "cluster_name": "labo", "version": { "number": "9.5.3", …, "lucene_version": "10.5.1" }, "tagline": "You Know, for Search".

    text
    GET _cat/indices/cours,avis,acces?v&s=index
    text
    health status index uuid                   pri rep docs.count docs.deleted store.size pri.store.size dataset.size
    green  open   acces aii68fsfQXKyt5wqkE1mPA   1   0      12000            0      1.5mb          1.5mb        1.5mb
    green  open   avis  W9j_JrwJT4mdzpWcS5k7xg   1   0        609            0     74.6kb         74.6kb       74.6kb
    green  open   cours pmq403ZgSZWeHJY9uNw1Qw   1   0        504            0    183.6kb        183.6kb      183.6kb

    Αυτό που πρέπει να δεις: pri 1, rep 0, και τους τρεις μετρητές. Το ?v προσθέτει τη γραμμή κεφαλίδας, το s=index ταξινομεί κατά όνομα. Χωρίς το φίλτρο cours,avis,acces, το GET _cat/indices?v απαριθμεί επίσης εσωτερικά index που ξεκινούν με τελεία (.internal.alerts-…): αγνόησέ τα.

  8. Ο κόμβος και οι μετρήσεις.

    text
    GET _cat/nodes?v
    text
    ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role   master name
    172.24.0.2           39          63   2    0.43    0.38     0.64 cdfhilmrstw *      labo-es-1
    text
    GET cours/_count
    json
    { "count": 504, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 } }

    Το ίδιο για GET avis/_count"count": 609 και GET acces/_count"count": 12000. Αυτό που πρέπει να δεις: ένας μόνο κόμβος, master *, και heap.percent γύρω στο 40% με τη ρύθμιση -Xmx1g του compose.

  9. Ένα πρώτο έγγραφο.

    text
    GET cours/_search
    json
    {
      "query": { "match_all": {} },
      "size": 1
    }

    Απάντηση (περικομμένη):

    json
    {
      "took": 1,
      "hits": {
        "total": { "value": 504, "relation": "eq" },
        "max_score": 1,
        "hits": [
          {
            "_index": "cours",
            "_id": "C0001",
            "_score": 1,
            "_source": {
              "id": "C0001",
              "titre": "Docker expliqué simplement",
              "categorie": "DevOps", "sujet": "Docker", "niveau": "debutant",
              "prix": 129, "note_moyenne": 4.4, "nb_avis": 327,
              "professeur": { "id": "P001", "nom": "Karim Caron", "ville": "Gatineau" },
    
            }
          }
        ]
      }
    }

    Αυτό που πρέπει να δεις: το hits.total.value = 504 (όλα τα έγγραφα ταιριάζουν με το match_all) αλλά μόνο ένα επιστρέφεται χάρη στο size: 1. Το Dev Tools στέλνει ένα GET με σώμα ως POST από κάτω· και τα δύο γίνονται δεκτά.

  10. Άνοιγμα του Neo4j Browser και σύνδεση. Πήγαινε στο http://localhost:7474. Το παράθυρο Connect to instance προτείνει ήδη Protocol neo4j:// και Connection URL localhost:7687 (η θύρα Bolt, όχι η 7474). Άφησε το Database user στο neo4j, πληκτρολόγησε το Password aiopsatlas2026, κάνε κλικ Connect. Αυτό που πρέπει να δεις: πάνω, μια πράσινη κουκκίδα και Instance: neo4j://localhost:7687, Database: neo4j, User: neo4j. Το πλαίσιο Database information αριστερά εμφανίζει Nodes (872) με τις ετικέτες Competence, Cours, Etudiant, Professeur, Ville, και Relationships (3,712) με COUVRE, ENSEIGNE, HABITE, INSCRIT_A, PREREQUIS_DE. Η πλαϊνή μπάρα προτείνει Database overview, Saved Cypher, History, Cypher reference, Parameters, Settings (η διεπαφή είναι στα αγγλικά).

  11. Πρώτο ερώτημα Cypher. Στον επεξεργαστή πάνω (neo4j$), πληκτρολόγησε μετά κάνε κλικ Run (ή Ctrl + Enter):

    cypher
    MATCH (c:Cours) RETURN c LIMIT 25

    Αυτό που πρέπει να δεις: ένα πλαίσιο αποτελεσμάτων με τρεις προβολές Graph, Table, Raw, και δεξιά Results overview : Nodes (25) · Cours (25). Στην προβολή Graph, 25 πορτοκαλί φυσαλίδες· κάνε κλικ σε μία για να δεις τις ιδιότητές της (id, titre, categorie, prix…). Στην προβολή Table, οι ίδιοι 25 κόμβοι σε JSON. Η ενότητα 6 σε μαθαίνει να γράφεις αυτά τα ερωτήματα· προς το παρόν, ξέρεις πού να τα πληκτρολογείς.

  12. Και το OpenSearch; Το εργαστήριο μπορεί επίσης να ξεκινήσει το OpenSearch 3.8.0 και το OpenSearch Dashboards στις θύρες 9201 και 5602, με ./labo.sh demarrer opensearch μετά ./labo.sh importer opensearch. Είναι ένα προαιρετικό προφίλ του Compose: δεν εκκινείται εξ ορισμού, και απαιτεί 6 GB μνήμης για το Docker. Το ενεργοποιούμε στην ενότητα 5, για να ξαναπαίξουμε τα ίδια ερωτήματα και στους δύο κινητήρες και να συγκρίνουμε. Τίποτα να κάνεις σήμερα.

Αν κολλήσεις

  • Το Kibana εμφανίζει «Kibana server is not ready yet» αμέσως μετά το demarrer → Το Kibana ξεκίνησε αλλά δεν έχει ολοκληρώσει ακόμα τη σύνδεσή του με το Elasticsearch και τη δημιουργία των εσωτερικών του index. Περίμενε 30 δευτερόλεπτα και ανανέωσε τη σελίδα. Αν το μήνυμα επιμένει πέρα από δύο λεπτά, ./labo.sh journal kibana (μάθημα 04, βλάβη αρ. 4).

  • Το Dev Tools απαντά 404 με "type": "index_not_found_exception", "reason": "no such index [cour]" → Ορθογραφικό λάθος στο όνομα του index (cour αντί cours). Το Elasticsearch δεν μαντεύει· το GET _cat/indices?v σου δίνει τα ακριβή ονόματα. Παραλλαγή: 400 με "no handler found for uri [/cours/_serch] and method [GET]" → είναι το όνομα του API που είναι λάθος γραμμένο (_serch).

  • Το Dev Tools απαντά 400 με x_content_parse_exception … was expecting double-quote to start field name → Το JSON είναι κακοσχηματισμένο, συνηθέστερα ένα κόμμα παραπάνω πριν το κλείσιμο αγκύλης ("size": 1, }). Ο επεξεργαστής υπογραμμίζει τη λανθασμένη γραμμή με κόκκινο πριν καν την αποστολή.

  • Neo4j Browser: «Connection to instance failed — The client is unauthorized due to authentication failure.» (λεπτομέρειες: Neo.ClientError.Security.Unauthorized) → Λανθασμένος κωδικός πρόσβασης. Είναι aiopsatlas2026 (καθορισμένος από το NEO4J_AUTH στο compose), όχι ο προεπιλεγμένος κωδικός neo4j. Ξαναπληκτρολόγησέ τον, χωρίς τελικό κενό.

  • Το etat εμφανίζει Neo4j répond — nœuds : 0 → Το κοντέινερ τρέχει αλλά ξέχασες το charger-graphe. Εκτέλεσέ το· χρειάζεται περίπου τριάντα δευτερόλεπτα.

Να θυμάσαι

  • Η τριάδα εκκίνησης: demarrer, importer, charger-graphe. Οι δύο τελευταίες επαναλαμβάνονται χωρίς να δημιουργούν διπλότυπα (ρητά αναγνωριστικά στο Elasticsearch, MERGE στο Neo4j).
  • Το demarrer περιμένει την κατάσταση healthy κάθε κοντέινερ· αυτή η κατάσταση προέρχεται από τα healthchecks του docker-compose.yml, και το Kibana ξεκινά μόνο μετά το Elasticsearch χάρη στο depends_on … service_healthy.
  • Το etat με μια ματιά: (healthy) παντού, cluster green, 504 / 609 / 12000 έγγραφα, 872 κόμβοι.
  • Kibana Dev Tools: μενού ☰ → Management → Outils de développement· ένα ερώτημα = μια γραμμή GET διαδρομή ακολουθούμενη από το JSON της κολλημένο από κάτω· Ctrl + Enter για αποστολή.
  • Neo4j Browser: http://localhost:7474, σύνδεση Bolt στο localhost:7687, χρήστης neo4j, κωδικός aiopsatlas2026· τα αποτελέσματα διαβάζονται σε Graph, Table ή Raw.

Για να πας πιο μακριά

Το αρχείο 01-03-premiere-visite.txt είναι στην ακριβή μορφή του Dev Tools: στην κονσόλα, το κουμπί Importer les requêtes (εικονίδιο πάνω δεξιά του επεξεργαστή) δέχεται αυτό το αρχείο και το επικολλά στον επεξεργαστή. Όλα τα αρχεία του φακέλου elasticsearch/requetes/ λειτουργούν έτσι· δεν θα χρειαστεί ποτέ να ξαναπληκτρολογήσεις ένα ερώτημα του μαθήματος.