Ασφαλέστερα Rootless Containers με το Podman

Ασφαλέστερα Rootless Containers με το Podman

Ένας οδηγός εισαγωγής στον κόσμο των containers και παρουσίασης των θετικών τους από πλευράς κυβερνoασφάλειας, αναβαθμίσεων και ανάκαμψης.

Στον σύγχρονο κόσμο που ζούμε σήμερα, η διαχείριση των ψηφιακών υποδομών έχει περάσει σε έναν νέο κόσμο, με ψηφιακά μέσα και cloud, τα οποία φιλοξενούν τις υποδομές μας πιο εύκολα από ποτέ.
Με την χρήση των containers, μπορούμε να αυτοματοποιήσουμε τις υποδομές μας, να τις κάνουμε εύκολα μεταφερόμενες και φυσικά μπορούμε να δημιουργήσουμε ευκολότερα αντίγραφα ασφαλείας χωρίς να χρειάζεται η κλωνοποίηση ολόκληρων δίσκων/MicroSD. Και το κυριότερο, μπορούμε να πραγματοποιήσουμε ευκολότερα και ασφαλέστερα αναβαθμίσεις, ενώ η ανάκαμψη γίνεται συντομότερη, σε περίπτωση προβληματικής ενημέρωσης ή προβλήματος της υποδομής.

Το άρθρο αυτό αποτελεί μέρος της σειράς Raspberry Pi Server, υποστηριζόμενο από την επίσημη αντιπροσωπία του Raspberry Pi στην Ελλάδα, το nettop.gr το οποίο με προμήθευσε με το Raspberry Pi 5 ώστε να δημιουργήσω περισσότερο περιεχόμενο για τις δυνατότητες και τα Project που μπορούν να τρέξουν self-hosted πάνω στο Raspberry Pi στα Ελληνικά. Ευχαριστώ πάρα πολύ το nettop.gr για την υποστήριξη!!!


:uk: The English version from this article can be found there: (TBD)

(Αν και εγώ έχω γενέθλια σήμερα, ορίστε ένα αναλυτικότατο άρθρο δώρο από εμένα)

Review: Μέλος της κοινότητας του Linux-User .gr / TuxHouse.


Και τι είναι τα Containers;

Σε αυτό το άρθρο θα παρουσιάσουμε μία πιο γενική εικόνα για τα Containers έτσι ώστε να είναι κατανοητός ο τρόπος λειτουργίας τους καθώς και οι δυνατότητες που προσφέρουν. Ταυτόχρονα, θα παρουσιάσουμε το πώς λειτουργεί το Podman.
Για όποιον θέλει να μάθει τι είναι το Docker, οπού αποτελεί την μεγάλη “ναυαρχίδα” των Containers, υπάρχει ήδη στο Linux-User.gr ένας πολύ αναλυτικός οδηγός:, οπού εμπεριέχει αναλυτικότερες πληροφορίες σχετικά με τις τεχνολογίες αυτές.

Συνοπτικά

Συνοπτικά, τα containers θα μπορούσαν να ταυτιστούν με ελαφριά, φορητά “κουτιά” λογισμικού. Τα “κουτιά” λογισμικού αυτά, μπορούμε πολύ εύκολα να τα σηκώσουμε, να τα μετακινήσουμε, να τα αντιγράψουμε κλπ… Κάθε “κουτί” περιλαμβάνει ό,τι είναι απαραίτητο για να μπορέσει να λειτουργήσει ένα λογισμικό ολοκληρωμένα, χωρίς να χρειάζεται άλλες δεσμεύσεις.

Έτσι, ξέρουμε ότι αν το κουτί αυτό το μεταφέρουμε από το γραφείο, στο κρεβάτι, θα συνεχίσει να έχει ακριβώς τα ίδια χαρακτηριστικά. Όπως και αν το κλωνοποιήσουμε, θα είναι ακριβώς το ίδιο κουτί παντού, σε όλα τα περιβάλλοντα.
Με αυτόν τον τρόπο, όπου κι αν μεταφέρουμε ένα container, το λογισμικό θα λειτουργεί με τον ίδιο ακριβώς τρόπο, είτε είναι στο φορητό μας υπολογιστή είτε σε έναν μεγάλο server σε κάποιο cloud.
Κοινώς, φτιάχνεις μία υποδομή μία φορά και έπειτα είσαι σε θέση να την μοιραστείς ως κλώνους σε πολλές διαφορετικές υποδομές, εταιρείες ή χρήσεις, γνωρίζοντας πως σε όλες τις περιπτώσεις, το αποτέλεσμα θα είναι πάντα το ίδιο.

Συνηθισμένα προβλήματα στην παραδοσιακή δομή των συστημάτων

Όλοι έχουμε βιώσει, ειδικά σε περιβάλλοντα GNU/Linux να θέλουμε να εγκαταστήσουμε μία εφαρμογή που δεν είναι μέρος της διανομής όπου χρησιμοποιούμε, και να ψάχνουμε χειροκίνητα να βρούμε τις βιβλιοθήκες (libraries) όπου λείπουν έτσι ώστε να λειτουργεί η εφαρμογή. Ή ο μεγαλύτερος φόβος μετά από μία αναβάθμιση: Να μην υπάρχει κάποια βιβλιοθήκη ή δέσμευση της εφαρμογής στην ενημερωμένη έκδοση, με αποτέλεσμα να μην μπορεί να τρέξει και να απαιτούνται αρκετές ώρες προσπάθειας ώστε να βρεθεί λύση.

Με την χρήση των containers, όλοι αυτοί οι φόβοι, όπως θα αναλυθεί και παρακάτω, μπορούν να ξεπεραστούν!

Η βασική δομή των Containers

Συνήθως, οι εταιρείες ή οι προγραμματιστές δημιουργούν εικόνες ή αλλιώς images. Σε αυτά τα images εμπεριέχεται οτιδήποτε χρειάζεται για να δημιουργήσουμε ένα container. Δηλαδή, μία ολόκληρη διανομή Linux, ένας web server, μία βάση δεδομένων ή πολλά από αυτά σε συνδυασμό μεταξύ τους.
Βασισμένοι σε ένα image, δημιουργούμε ένα container το οποίο συνοπτικά αποτελείται από τα εξής χαρακτηριστικά (αλλά δεν περιορίζεται αποκλειστικά σε αυτά):

  • Κατεβάζει ένα image με προκαθορισμένα χαρακτηριστικά,
  • Δημιουργεί τουλάχιστον ένα volume που αποτελεί τον αποθηκευτικό χώρο του container αυτού,
  • Λαμβάνει τις ρυθμίσεις όπου ορίζουν ποια volumes αντιστοιχούν σε ποιους υποφακέλους, τις πόρτες επικοινωνίας μεταξύ του κύριου συστήματος και του container κτλπ.
  • Το εικονικό δίκτυο στο οποίο θα ανήκει το container αυτό.

Σε αυτό το σημείο θα πρέπει να αναφερθεί ότι σε κάθε ένα container όπου δημιουργείται, δίνεται ένας μοναδικός αναγνωριστικός αριθμός καθώς και ένα όνομα container, έτσι ώστε να μπορεί να διακριθεί από τα υπόλοιπα.

Έτσι, μπορούμε πάρα πολύ εύκολα:

  • Να αλλάζουμε υποδίκτυα στα οποία θα ανήκει ένα Container ανάλογα τις ανάγκες μας,
  • Να δώσουμε περισσότερο χώρο αποθήκευσης σε ένα container, βάζοντας ως ένα υποφάκελο ένα νέο volume το οποίο ενδεχομένως θα ανήκει σε έναν νέο δίσκο. Με αυτό τον τρόπο, μπορεί να βελτιωθεί σημαντικά το scalability χωρίς την ανάγκη μεταφοράς ή αντικατάστασης δίσκων,
  • Να αναβαθμίσουμε ένα container, κατεβάζοντας απλά ένα νέο image και αντικαταστώντας το με το image που είχαμε στο container προηγουμένως, κάνοντας την διαδικασία αναβάθμισης εξαιρετικά απλοϊκή και γρήγορη, κάτι το οποίο μπορεί να μας προστατεύσει και από κενά ασφαλείας συμβάλλοντας στο Vulnerability Patch Management.
  • Να δημιουργήσουμε εύκολα αντίγραφα ασφαλείας, απλά αντιγράφοντας τα volumes και τις ρυθμίσεις σε ένα εναλλακτικό μέσο αποθήκευσης ( π.χ. χρησιμοποιώντας το εργαλείο rsync),

Συνοψίζοντας την εισαγωγή στα Containers

Mε τα παραπάνω γίνεται κατανοητό ότι μπορούμε πολύ εύκολα να φτιάχνουμε αντίγραφα ασφαλείας στα containers μας καθώς και να μετακινούμε την υποδομή από cloud σε cloud, από self-hosted server σε self-hosted server, από Raspberry Pi σε Raspberry Pi, γρήγορα, μεθοδευμένα και με μεγάλη ασφάλεια, ενώ οι ενημερώσεις ασφαλείας γίνονται παιχνιδάκι.

Και αν σπάσει όντως κάτι κατά την αναβάθμιση Container;

Αν κάποιο container μετά από κάποια αναβάθμιση δεν δουλέψει και χρειαστεί να πραγματοποιήσουμε κάποιο rollback σε προηγούμενη έκδοση, τότε απλά επαναφέρουμε το προηγούμενο image, και όλα θα δουλεύουν και πάλι κανονικά.

Ακόμα και σε περίπτωση που δεν δουλέψει κάτι όμως, μπορεί να επιτευχθεί πολύ γρήγορα ανάκαμψη επαναφέροντας από τα αντίγραφα ασφαλείας, τα παλιότερα volumes.
Έτσι, μέσα σε απειροελάχιστα λεπτά, η υποδομή μας είναι και πάλι λειτουργική. Κάτι πάρα πολύ χρήσιμο στα χρόνια που διανύουμε με τις κυβερνοεπιθέσεις να βρίσκονται στα ύψη.

Δυστυχώς όσοι έχουν δουλέψει σε ΙΤ, έχουν βιώσει να υπάρχουν legacy συστήματα που δεν μπορούν να γίνουν αναβαθμίσεις ή δεν γίνονται με την απαιτούμενη συχνότητα, αφήνοντας έτσι τα συστήματα αυτά εκτιθέμενα. Και όταν γίνει το κακό, είμαστε πρώτη γραμμή να βρούμε γρήγορες λύσεις, συνεπώς τα containers μπορούν να βοηθήσουν εξαιρετικά στην καθημερινότητά μας.

Γιατί να προτιμήσουμε containers αντί των τυπικών virtual machines;

Τα Virtual Machines κάνουν πολύ καλά την δουλειά τους, ωστόσο λόγω ότι στην πραγματικότητα φιλοξενούν ένα ολόκληρο λειτουργικό σύστημα, καταναλώνουν σημαντικούς πόρους όπου ενδεχομένως να είναι ζωτικής σημασίας για την ομαλή λειτουργία του server μας. Επιπροσθέτως, καταλαμβάνουν πάρα πολύ χώρο και συνεπώς είναι δυσκολότερη η συντήρηση ή μεταφορά τους.

Στην πραγματικότητα, έχεις έναν κανονικό υπολογιστή, απλά σε εικονική μορφή όπου μπορείς ευκολότερα να δημιουργήσεις αντίγραφα ασφαλείας.
Όμως, αν κάθε διαδικτυακή εφαρμογή που τρέχει, είναι σε διαφορετικό virtual machine, τότε η πολυπλοκότητα αυξάνεται ραγδαία, ιδιαίτερα όταν κάθε εγκατεστημένο λειτουργικό σύστημα πλέον είναι άνω των 10GB στις περισσότερες περιπτώσεις.


Με τα containers, όπως φαίνεται και στο παραπάνω διάγραμμα όπου φιλοξενείται από το dazzyddos.github.io, όλα αυτά γίνονται ευκολότερα μιας και δεν τρέχει ένα ολόκληρο λειτουργικό σύστημα, η δουλειά πραγματοποιείται ολόκληρη από τον linux kernel του host μηχανήματος.

Αυτοί είναι οι κύριοι λόγοι που τα Containers και ιδιαίτερα το Docker έχουν γίνει τόσο διάσημα τα τελευταία χρόνια. Φτιάχνεις μία υποδομή μία φορά, και τότε μπορεί να λειτουργήσει παντού!

Kαι αφού αναλύσαμε εισαγωγικά το πώς λειτουργούν τα Containers, ήρθε η ώρα του Podman

Κατανόηση του Podman: Η Daemon-less προσέγγιση

Το Podman αποτελεί μια εναλλακτική του Docker, με το οποίο είναι συμβατό ως OCI based αρχιτεκτονική (Open Container Initiative), και ξεχωρίζει για το χαρακτηριστικό του ότι λειτουργεί χωρίς την ανάγκη ύπαρξης κάποιου κεντρικού daemon. Σε αντίθεση με το Docker, όπως βλέπουμε και στο παραπάνω διάγραμμα, που βασίζεται σε ένα container engine, και τρέχουν πάνω σε αυτό όλα τα containers, το Podman λειτουργεί με ένα εναλλακτικό μοντέλο που δεν διαθέτει ένα κεντρικό daemon για να τρέξει καθώς και δεν απαιτεί ούτε δικαιώματα διαχειριστή (root), ενισχύοντας έτσι την ασφάλεια και επιτρέποντας τον άμεσο έλεγχο των container μέσω τερματικού ή του GUI εργαλείου όπου προσφέρει.

Mε την αποφυγή χρήση ενός κεντρικού daemon,στην πραγματικότητα αποφεύγουμε το single point of failure.

Podman vs Docker: Οι Κύριες Διαφορές

Παρόλο που το Podman και το Docker προσφέρουν αρκετές παρόμοιες λειτουργίες, ενώ όπως θα δούμε παρακάτω και η σύνταξη τους είναι σχεδόν ίδια, οι διαφορές στην αρχιτεκτονική τους που τα διαχωρίζουν είναι οι εξής:

  1. Αρχιτεκτονική Χωρίς Daemon: Όπως αναφέρθηκε και προηγουμένως, Το Podman δεν απαιτεί τη ύπαρξη ενός daemon για να λειτουργήσει, μειώνοντας έτσι και την επιβάρυνση του συστήματος και τους πιθανούς κινδύνους ασφαλείας που προέρχονται από το να exploitαριστεί ο daemon και τότε να πάρει κάποιος πρόσβαση σε όλα τα containers (και με root μιας και το docker τρέχει ως root συνήθως),
  2. Rootless Containers: Το Podman επιτρέπει σε χρήστες χωρίς δικαιώματα root να δημιουργούν και να διαχειρίζονται containers, κάτι το οποίο συμβάλει εξαιρετικά στην ασφάλεια των υποδομών μας,
  3. Συμβατότητα με SELinux: Το Podman έρχεται προεγκατεστημένο στις εκδόσεις του Fedora Silverblue και Fedora IoT τα οποία αποτελούν immutable Linux οπού είναι διαθέσιμο και στο Raspberry Pi και διαθέτουν και ενεργοποιημένο SELinux από προεπιλογή, άρα μεγαλύτερη ασφάλεια στην υποδομή μας,
  4. Το Podman υποστηρίζει την λήψη και εκτέλεση images από πολλαπλές πηγές. Δηλαδή, εκτός από το αποθετήριο του Dockerhub που διαθέτει εκατοντάδες containers, μπορείτε να κατεβάσετε images και από άλλες πηγές απευθείας.
  5. Η εκκίνηση των Containers με podman γίνεται εξαιρετικά πάρα πολύ γρήγορα λόγω του daemon-less σχεδιασμού, Μόλις πατήσετε το start, απευθείας η υποδομή ξεκινάει και τρέχει. Παρόλο που και στο Docker η διαδικασία έναρξης είναι σχετικά γρήγορη, στο Podman πραγματικά, συμβαίνει σε ελάχιστα κλάσματα του δευτερολέπτου.

Ξεκινώντας με το Podman

Εκτός από τις Fedora Based διανομές GNU/Linux, το Podman μπορεί να εγκατασταθεί πάρα πολύ εύκολα και σε Ubuntu/Debian Based διανομές (και Raspberry Pi OS) από το επίσημο αποθετήριο. Πολύ εύκολα, ανοίγουμε ένα τερματικό και δίνουμε:

sudo apt install podman

Διαχείριση Containers με το Podman

Όπως αναφέρθηκε και προηγουμένως, για να τρέξουμε/φτιάξουμε Containers, η διαδικασία δεν έχει ιδιαίτερη διαφορά από το Docker.

  1. Εκτέλεση Container:
    Για να τρέξουμε ένα container στο Podman, μπορούμε να χρησιμοποιήσουμε την εντολή:

    podman run -dt --name my_container nginx
    

    Αυτή η εντολή στην πραγματικότητα κατεβάζει το image του Nginx (αν δεν υπάρχει ήδη) και έπειτα δημιουργεί ένα νέο container με το όνομα my_container.

  2. Προβολή Λίστας με τα Containers::
    Για να δούμε όλα τα containers που τρέχουν, δίνουμε:

    podman ps
    

    Για να δούμε όλα τα containers, ακόμα και αυτά που έχει διακοπή η λειτουργεία τους, δίνουμε:

    podman ps -a
    
  3. Υιοθέτηση shell μέσα σε ένα container:
    Με την παρακάτω εντολή, λέμε στο container με όνομα my_container να μας δώσει bash shell:

    podman exec -it my_container /bin/bash
    
  4. Παύση λειτουργίας ενός container:
    Για να σταματήσουμε ένα Container, δίνουμε:

    podman stop my_container
    

    Για να αφαιρέσουμε ένα container δίνουμε:

    podman rm my_container
    

Για να δούμε τα images όπου έχουμε κατεβάσει δίνουμε:

podman images

Αξιοποιώντας τις Προχωρημένες Δυνατότητες του Podman

Podman Compose

Το Podman μπορεί να χρησιμοποιηθεί μαζί με το systemd, ώστε τα containers να εκτελούνται κατά την εκκίνηση του συστήματος πάρα πολύ εύκολα, όπως θα πραγματοποιούσαμε και με άλλα services που θα έτρεχαν απευθείας απευθείας πάνω στο σύστημα μας.

   sudo apt install podman-compose

Επιπλέον, το Podman διαθέτει και Podman Compose το οποίο λειτουργεί όπως ακριβώς το Docker Compose (στο Linux-User.gr υπάρχει ήδη οδηγός που εξηγεί πώς λειτουργεί, η λογική είναι ακριβώς η ίδια, όπου docker-compose, γράφουμε podman-compose και όλα τρέχουν κανονικά).

Dockerfile στο Podman

Λόγω της συμβατότητας τους, μπορούμε να δημιουργήσουμε Dockerfile και να κατασκευάσουμε τα δικά μας images πάρα πολύ εύκολα και να τα τρέξουμε έπειτα μέσα στο Podman.
Για να σηκώσουμε ένα podman-compose δίνουμε:

podman-compose up -d

Port Mapping στο Podman

Το Port Mapping, όπως και τα προηγούμενα, ακολουθούν την ίδια σύνταξη με το docker:

   podman run -d -p 8080:80 --name httpd-basic quay.io/httpd-parent

Και με αυτό το παράδειγμα, η πόρτα 80 is the port number which Container listens/exposes και μπορούμε να έχουμε πρόσβαση σε αυτή έξω από το container από την πόρτα 8080.

Αξίζει να επισημανθεί ότι μία υποδομή που τρέχει μέσα από το Podman, για μεγαλύτερη ασφάλεια, δεν είναι by default προσβάσιμη από τον χρήστη εκτός του υπολογιστή αυτού, από το υπόλοιπο δίκτυο στο οποίο είναι συνδεδεμένος ένας υπολογιστής. Θα πρέπει να το επιτρέψουμε εμείς οι ίδιοι.

Υπηρεσίες που δοκιμάστηκαν και λειτουργούν απροβλημάτιστα με το Podman:

Σε αυτό το σημείο θα βρείτε μία λίστα με γνωστές υπηρεσίες οπού έχουν δοκιμαστεί και δουλεύουν άψογα με το Podman (και με SELinux ενεργοποιημένο) (Αν έχετε δοκιμάσει κι εσείς κάποιες ακόμα, αφήστε σχόλιο από κάτω έτσι ώστε να τις προσθέσω στον παρών οδηγό):

  • caddy
  • nextcloud+mariadb+caddy
  • kavita
  • jellyfin
  • fedora
  • ubuntu
  • ethsec
  • nginx

Podman με Γραφικό Περιβάλλον

Όπως αναφέρθηκε και στην αρχή αυτού του οδηγού, το Podman υποστηρίζει και γραφικό περιβάλλον ως εφαρμογή, ώστε να μπορούμε να διαχειριζόμαστε τα Containers πάρα πολύ ευκολότερα, χωρίς να χρειάζεται να θυμόμαστε απέξω όλες τις εντολές.

Στο Docker, ο περισσότερος κόσμος χρησιμοποιεί το Portainer ως web application container όπου επιτρέπει μέσα από τον browser να διαχειριστούμε τα containers μας.

Το Podman GUI είναι εξαιρετικά χρήσιμο και μπορούμε πανεύκολα να διαχειριστούμε την υποδομή μας. Παρακάτω θα ακολουθήσουν screenshots με τα μενού της GUI εφαρμογής του Podman. Όλες οι λειτουργίες που περιγράψαμε παραπάνω, όπως βλέπετε γίνονται με κουμπία όμορφα και ωραία.




Επίλογος

Το Podman και τα containers έχουν πάρα πολλές περισσότερες λειτουργίες από αυτές που αναφέρθηκαν, ελπίζω να το βρήκατε ενδιαφέρον και να αρχίσετε να ψάχνεστε περισσότερο με τις λύσεις όπου μπορούν να προσφέρουν τα containers.
Τις επόμενες εβδομάδες, θα ανέβουν οδηγοί με διάφορες υπηρεσίες όπου μπορούν να σηκωθούν με containers στο Podman/Docker ώστε να κάνετε την ζωή σας ακόμη ευκολότερη.
Σε κάθε περίπτωση, το Documentation του Podman μπορεί να βρεθεί εδώ:

7 «Μου αρέσει»

Ευχαριστούμε πολύ @sv1sjp .
Θέλουμε πολύ να δούμε παραδείγματα με υπηρεσίες, αλλά και παραδείγματα με pods.
Ένα πλεονέκτημα του podman είναι ότι σε βάζει πιο εύκολα στη λογική του kubernetes, από ότι έχω ακούσει.
Βέβαια, θα πρέπει να επιλέξουμε, ή podman ή docker σε έναν server, διαφορετικά έχω την εντύπωση ότι δημιουργούνται προβλήματα.
Άλλα γραφικά περιβάλλοντα για τα podman containers είναι το yacht αλλά και το cockpit. Έχουμε αναφερθεί στο cockpit-project παλαιότερα.

5 «Μου αρέσει»

Επικεντρώθηκα στα containers για την ώρα, για pods θα τα δούμε σε επόμενο άρθρο :)

1 «Μου αρέσει»

Σημείωση για archlinux users.

Αν σας αρέσει το cockpit,
Η εγκατάσταση του, σέρνει καράβι… πακέτων.

Ειδικώτερα το packagekit που ενδέχεται να προκαλέσει σωρεία προβλημάτων και το mkinitcpio να μην χτίζει σωστά το initramfs. Και συνεπώς να μην μπουτάρει μετά από αναβάθμιση kernel. systemd κλπ.
Σε -Rns απεγκατάση του cockpit, το ρημάδι μένει πίσω.

Ας έχετε κοντά ένα στικάκι με το archiso για να το ξηλώσετε :innocent:

2 «Μου αρέσει»