Εργαλεία για προγραμματιστές εφαρμογών που εκτελούνται στο Kubernetes

Εργαλεία για προγραμματιστές εφαρμογών που εκτελούνται στο Kubernetes

Μια σύγχρονη προσέγγιση των λειτουργιών επιλύει πολλά πιεστικά επιχειρηματικά προβλήματα. Τα κοντέινερ και οι ενορχηστρωτές διευκολύνουν την κλιμάκωση έργων οποιασδήποτε πολυπλοκότητας, απλοποιούν την κυκλοφορία νέων εκδόσεων, τα καθιστούν πιο αξιόπιστα, αλλά ταυτόχρονα δημιουργούν πρόσθετα προβλήματα στους προγραμματιστές. Ο προγραμματιστής, πρώτα απ 'όλα, ενδιαφέρεται για τον κώδικά του: αρχιτεκτονική, ποιότητα, απόδοση, κομψότητα - και όχι πώς θα λειτουργήσει στο Kubernetes και πώς να τον δοκιμάσει και να τον διορθώσει αφού κάνει έστω και ελάχιστες αλλαγές. Επομένως, είναι επίσης πολύ φυσικό τα εργαλεία για το Kubernetes να αναπτύσσονται ενεργά, βοηθώντας στην επίλυση των προβλημάτων ακόμη και των πιο «αρχαϊκών» προγραμματιστών και επιτρέποντάς τους να επικεντρωθούν στο κύριο πράγμα.

Αυτή η ανασκόπηση παρέχει σύντομες πληροφορίες σχετικά με ορισμένα από τα εργαλεία που κάνουν τη ζωή πιο εύκολη για έναν προγραμματιστή του οποίου ο κώδικας εκτελείται στο pod'ax ενός συμπλέγματος Kubernetes.

Απλοί βοηθοί

Kubectl-debug

  • Ουσία: προσθέστε το κοντέινερ σας σε ένα Pod και δείτε τι συμβαίνει σε αυτό.
  • GitHub.
  • Σύντομα στατιστικά GH: 715 αστέρια, 54 δεσμεύσεις, 9 συνεισφέροντες.
  • Γλώσσα: Πηγαίνετε.
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

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

Μπορείτε επίσης να μεταβείτε στο κοντέινερ διεργασίας εκτελώντας chroot /proc/PID/root - αυτό μπορεί να είναι πολύ βολικό όταν πρέπει να αποκτήσετε ένα κέλυφος ρίζας σε ένα δοχείο για το οποίο έχει οριστεί στο μανιφέστο securityContext.runAs.

Το εργαλείο είναι απλό και αποτελεσματικό, επομένως μπορεί να είναι χρήσιμο σε κάθε προγραμματιστή. Γράψαμε περισσότερα για αυτό στο ξεχωριστό άρθρο.

Τηλεπαρουσία

  • Ουσία: μεταφέρετε την εφαρμογή στον υπολογιστή σας. Ανάπτυξη και εντοπισμός σφαλμάτων τοπικά.
  • Τοποθεσία; GitHub.
  • Σύντομα στατιστικά GH: 2131 αστέρια, 2712 δεσμεύσεις, 33 συνεισφέροντες.
  • Γλώσσα: Python.
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

Η ιδέα αυτού του συμπληρωματικού προγράμματος είναι η εκκίνηση ενός κοντέινερ με την εφαρμογή στον τοπικό υπολογιστή χρήστη και η διαμεσολάβηση όλης της κυκλοφορίας από το σύμπλεγμα προς αυτό και πίσω. Αυτή η προσέγγιση σάς επιτρέπει να αναπτύσσετε τοπικά επεξεργάζοντας απλά αρχεία στο αγαπημένο σας IDE: τα αποτελέσματα θα είναι άμεσα διαθέσιμα.

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

Έχουμε ήδη μοιραστεί την εμπειρία μας από τη χρήση του Telepresence εδώ.

Ksync

  • Ουσία: σχεδόν στιγμιαίος συγχρονισμός του κώδικα με το κοντέινερ στο σύμπλεγμα.
  • GitHub.
  • Σύντομα στατιστικά GH: 555 αστέρια, 362 δεσμεύσεις, 11 συνεισφέροντες.
  • Γλώσσα: Πηγαίνετε.
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

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

Όταν αρχικοποιηθεί μία φορά από την εντολή ksync init δημιουργείται ένα DaemonSet στο σύμπλεγμα, το οποίο χρησιμοποιείται για την παρακολούθηση της κατάστασης του συστήματος αρχείων του επιλεγμένου κοντέινερ. Στον τοπικό υπολογιστή του, ο προγραμματιστής εκτελεί την εντολή ksync watch, το οποίο παρακολουθεί τις διαμορφώσεις και εκτελεί syncthing, το οποίο συγχρονίζει απευθείας τα αρχεία με το σύμπλεγμα.

Το μόνο που μένει είναι να δώσει οδηγίες στο ksync τι να συγχρονίσει με τι. Για παράδειγμα, αυτή η εντολή:

ksync create --name=myproject --namespace=test --selector=app=backend --container=php --reload=false /home/user/myproject/ /var/www/myproject/

...θα δημιουργήσει έναν παρατηρητή με το όνομα myprojectπου θα αναζητήσει μια ομάδα με ετικέτα app=backend και προσπαθήστε να συγχρονίσετε τον τοπικό κατάλογο /home/user/myproject/ με κατάλογο /var/www/myproject/ στο κοντέινερ που ονομάζεται php.

Προβλήματα και σημειώσεις για το ksync από την εμπειρία μας:

  • Πρέπει να χρησιμοποιείται σε κόμβους συμπλέγματος Kubernetes overlay2 ως πρόγραμμα οδήγησης αποθήκευσης για το Docker. Το βοηθητικό πρόγραμμα δεν θα λειτουργήσει με κανένα άλλο.
  • Όταν χρησιμοποιείτε τα Windows ως λειτουργικό σύστημα πελάτη, το πρόγραμμα παρακολούθησης συστήματος αρχείων ενδέχεται να μην λειτουργεί σωστά. Αυτό το σφάλμα παρατηρήθηκε όταν εργάζεστε με μεγάλους καταλόγους - με μεγάλο αριθμό ένθετων αρχείων και καταλόγων. Δημιουργήσαμε σχετικό θέμα στο έργο συγχρονισμού, αλλά δεν υπάρχει ακόμη πρόοδος σε αυτό (από τις αρχές Ιουλίου).
  • Χρήση αρχείου .stignore για να καθορίσετε διαδρομές ή μοτίβα αρχείων που δεν χρειάζεται να συγχρονιστούν (για παράδειγμα, καταλόγους app/cache и .git).
  • Από προεπιλογή, το ksync θα επανεκκινήσει το κοντέινερ κάθε φορά που αλλάζουν τα αρχεία. Για το Node.js αυτό είναι βολικό, αλλά για την PHP είναι εντελώς περιττό. Είναι καλύτερα να απενεργοποιήσετε το opcache και να χρησιμοποιήσετε τη σημαία --reload=false.
  • Η διαμόρφωση μπορεί πάντα να διορθωθεί μέσα $HOME/.ksync/ksync.yaml.

σκουός

  • Ουσία: διεργασίες εντοπισμού σφαλμάτων απευθείας στο σύμπλεγμα.
  • GitHub.
  • Σύντομα στατιστικά GH: 1154 αστέρια, 279 δεσμεύσεις, 23 συνεισφέροντες.
  • Γλώσσα: Πηγαίνετε.
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

Αυτό το εργαλείο έχει σχεδιαστεί για διεργασίες εντοπισμού σφαλμάτων απευθείας σε ομάδες. Το βοηθητικό πρόγραμμα είναι απλό και σας επιτρέπει διαδραστικά να επιλέξετε το επιθυμητό πρόγραμμα εντοπισμού σφαλμάτων (Δες παρακάτω) και namespace + pod, στη διαδικασία του οποίου πρέπει να παρέμβετε. Υποστηρίζεται αυτήν τη στιγμή:

  • διερευνώ - για εφαρμογές Go.
  • GDB - μέσω απομακρυσμένου στόχου + προώθηση θύρας.
  • Προώθηση θύρας JDWP για εντοπισμό σφαλμάτων σε εφαρμογές Java.

Από την πλευρά IDE, η υποστήριξη είναι διαθέσιμη μόνο σε VScode (με χρήση επεκτάσεις), ωστόσο, τα σχέδια για το τρέχον (2019) έτος περιλαμβάνουν το Eclipse και το Intellij.

Για τον εντοπισμό σφαλμάτων διεργασιών, το Squash εκτελεί ένα προνομιακό κοντέινερ στους κόμβους συμπλέγματος, επομένως πρέπει πρώτα να εξοικειωθείτε με τις δυνατότητες λειτουργία ασφαλείας για αποφυγή προβλημάτων ασφαλείας.

Ολοκληρωμένες λύσεις

Ας προχωρήσουμε στο βαρύ πυροβολικό - περισσότερα έργα «μεγάλης κλίμακας» που έχουν σχεδιαστεί για να καλύπτουν άμεσα πολλές από τις ανάγκες των προγραμματιστών.

NB: Σε αυτήν τη λίστα, φυσικά, υπάρχει μια θέση για το βοηθητικό πρόγραμμα ανοιχτού κώδικα werf (παλαιότερα γνωστό ως dapp). Ωστόσο, έχουμε ήδη γράψει και μιλήσει για αυτό περισσότερες από μία φορές, και ως εκ τούτου αποφασίσαμε να μην το συμπεριλάβουμε στην κριτική. Για όσους επιθυμούν να εξοικειωθούν περισσότερο με τις δυνατότητές του, συνιστούμε να διαβάσουν/ακούσουν την αναφορά "Το werf είναι το εργαλείο μας για CI/CD στο Kubernetes».

DevSpace

  • Ουσία: για όσους θέλουν να ξεκινήσουν να εργάζονται στο Kubernetes, αλλά δεν θέλουν να εμβαθύνουν στη ζούγκλα του.
  • GitHub.
  • Σύντομα στατιστικά GH: 630 αστέρια, 1912 δεσμεύσεις, 13 συνεισφέροντες.
  • Γλώσσα: Πηγαίνετε.
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

Μια λύση από την ομώνυμη εταιρεία, η οποία παρέχει διαχειριζόμενα clusters με την Kubernetes για ανάπτυξη ομάδας. Το βοηθητικό πρόγραμμα δημιουργήθηκε για εμπορικά συμπλέγματα, αλλά λειτουργεί εξαιρετικά με οποιαδήποτε άλλα.

Κατά την εκτέλεση της εντολής devspace init στον κατάλογο του έργου θα σας προσφερθούν (διαδραστικά):

  • επιλέξτε ένα λειτουργικό σύμπλεγμα Kubernetes,
  • χρησιμοποιούν τα υφιστάμενα Dockerfile (ή να δημιουργήσετε ένα νέο) για να δημιουργήσετε ένα κοντέινερ με βάση αυτό,
  • επιλέξτε ένα αποθετήριο για την αποθήκευση εικόνων κοντέινερ κ.λπ.

Μετά από όλα αυτά τα προπαρασκευαστικά βήματα, μπορείτε να ξεκινήσετε την ανάπτυξη εκτελώντας την εντολή devspace dev. Θα δημιουργήσει το κοντέινερ, θα το ανεβάσει στο αποθετήριο, θα ανοίξει την ανάπτυξη στο σύμπλεγμα και θα ξεκινήσει η προώθηση θύρας και ο συγχρονισμός του κοντέινερ με τον τοπικό κατάλογο.

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

Τέλος, η ομάδα devspace deploy λανσάρει την εφαρμογή και τη σχετική υποδομή στο σύμπλεγμα, μετά από το οποίο όλα αρχίζουν να λειτουργούν σε λειτουργία μάχης.

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

Εργαλεία για προγραμματιστές εφαρμογών που εκτελούνται στο Kubernetes
Αρχιτεκτονική και κύρια στάδια εργασίας με το DevSpace

Επιπλέον, είναι εύκολο να προσθέσετε ένα προκαθορισμένο στοιχείο (για παράδειγμα, ένα MySQL DBMS) ή ένα γράφημα Helm στο έργο. Διαβάστε περισσότερα στο τεκμηρίωση - δεν είναι περίπλοκο.

Σκαλωσιά

  • Τοποθεσία; GitHub.
  • Σύντομα στατιστικά GH: 7423 αστέρια, 4173 δεσμεύσεις, 136 συνεισφέροντες.
  • Γλώσσα: Πηγαίνετε.
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

Αυτό το βοηθητικό πρόγραμμα από την Google ισχυρίζεται ότι καλύπτει όλες τις ανάγκες ενός προγραμματιστή του οποίου ο κώδικας θα εκτελείται με κάποιο τρόπο σε ένα σύμπλεγμα Kubernetes. Η έναρξη χρήσης του δεν είναι τόσο εύκολη όσο το devspace: χωρίς διαδραστικότητα, ανίχνευση γλώσσας και αυτόματη δημιουργία Dockerfile δεν θα σου το προσφέρουν εδώ.

Ωστόσο, αν αυτό δεν σας τρομάζει, δείτε τι σας επιτρέπει να κάνετε το Skaffold:

  • Παρακολούθηση αλλαγών στον πηγαίο κώδικα.
  • Συγχρονίστε το με το δοχείο λοβού εάν δεν χρειάζεται συναρμολόγηση.
  • Συλλέξτε κοντέινερ με κώδικα, εάν η γλώσσα ερμηνεύεται, ή μεταγλωττίστε αντικείμενα και συσκευάστε τα σε δοχεία.
  • Οι εικόνες που προκύπτουν ελέγχονται αυτόματα χρησιμοποιώντας δοχείο-δομή-δοκιμή.
  • Προσθήκη ετικετών και μεταφόρτωση εικόνων στο Μητρώο Docker.
  • Αναπτύξτε μια εφαρμογή σε ένα σύμπλεγμα χρησιμοποιώντας kubectl, Helm ή kustomize.
  • Εκτελέστε προώθηση θύρας.
  • Εντοπισμός σφαλμάτων σε εφαρμογές γραμμένες σε Java, Node.js, Python.

Η ροή εργασίας σε διάφορες παραλλαγές περιγράφεται δηλωτικά στο αρχείο skaffold.yaml. Για ένα έργο, μπορείτε επίσης να ορίσετε πολλά προφίλ στα οποία μπορείτε να αλλάξετε εν μέρει ή πλήρως τα στάδια συναρμολόγησης και ανάπτυξης. Για παράδειγμα, για ανάπτυξη, καθορίστε μια βασική εικόνα βολική για τον προγραμματιστή και για σκηνοθεσία και παραγωγή - μια ελάχιστη (+ χρήση securityContext κοντέινερ ή επαναπροσδιορίστε το σύμπλεγμα στο οποίο θα αναπτυχθεί η εφαρμογή).

Τα κοντέινερ Docker μπορούν να κατασκευαστούν τοπικά ή εξ αποστάσεως: σε Google Cloud Build ή σε ένα σύμπλεγμα χρησιμοποιώντας Κάνικο. Τα Bazel και Jib Maven/Gradle υποστηρίζονται επίσης. Για την προσθήκη ετικετών, το Skaffold υποστηρίζει πολλές στρατηγικές: με git commit hash, ημερομηνία/ώρα, sha256-άθροισμα πηγών κ.λπ.

Ξεχωριστά, αξίζει να σημειωθεί η δυνατότητα δοκιμής δοχείων. Το ήδη αναφερθέν πλαίσιο δοκιμής κοντέινερ-δομή προσφέρει τις ακόλουθες μεθόδους επαλήθευσης:

  • Εκτέλεση εντολών στο πλαίσιο ενός κοντέινερ με παρακολούθηση καταστάσεων εξόδου και έλεγχος της εξόδου κειμένου της εντολής.
  • Έλεγχος της παρουσίας αρχείων στο κοντέινερ και αντιστοίχιση των χαρακτηριστικών που καθορίζονται.
  • Έλεγχος του περιεχομένου του αρχείου με χρήση κανονικών εκφράσεων.
  • Επαλήθευση μεταδεδομένων εικόνας (ENV, ENTRYPOINT, VOLUMES κ.λπ.).
  • Έλεγχος συμβατότητας άδειας χρήσης.

Ο συγχρονισμός αρχείων με το κοντέινερ δεν πραγματοποιείται με τον βέλτιστο τρόπο: το Skaffold απλώς δημιουργεί ένα αρχείο με τις πηγές, το αντιγράφει και το αποσυσκευάζει στο δοχείο (πρέπει να εγκατασταθεί η πίσσα). Επομένως, εάν η κύρια εργασία σας είναι ο συγχρονισμός κώδικα, είναι προτιμότερο να αναζητήσετε μια εξειδικευμένη λύση (ksync).

Εργαλεία για προγραμματιστές εφαρμογών που εκτελούνται στο Kubernetes
Κύρια στάδια λειτουργίας Skaffold

Γενικά, το εργαλείο δεν σας επιτρέπει να κάνετε αφαίρεση από εκδηλώσεις Kubernetes και δεν έχει καμία διαδραστικότητα, επομένως μπορεί να φαίνεται δύσκολο να το κατακτήσετε. Αλλά αυτό είναι και το πλεονέκτημά του - μεγαλύτερη ελευθερία δράσης.

Κήπος

  • Τοποθεσία; GitHub.
  • Σύντομα στατιστικά GH: 1063 αστέρια, 1927 δεσμεύσεις, 17 συνεισφέροντες.
  • Γλώσσα: TypeScript (προβλέπεται να χωριστεί το έργο σε πολλά στοιχεία, μερικά από τα οποία θα είναι στο Go, και επίσης να δημιουργηθεί ένα SDK για τη δημιουργία πρόσθετων στο TypeScript/JavaScript και στο Go).
  • Άδεια χρήσης: Άδεια χρήσης Apache 2.0.

Όπως το Skaffold, έτσι και το Garden στοχεύει στην αυτοματοποίηση των διαδικασιών παράδοσης κώδικα εφαρμογής στο σύμπλεγμα K8s. Για να το κάνετε αυτό, πρέπει πρώτα να περιγράψετε τη δομή του έργου σε ένα αρχείο YAML και, στη συνέχεια, να εκτελέσετε την εντολή garden dev. Θα κάνει όλα τα μαγικά:

  • Συλλέξτε δοχεία με διάφορα μέρη του έργου.
  • Διενεργεί δοκιμές ολοκλήρωσης και μονάδας, εάν έχουν περιγραφεί.
  • Κυκλοφορεί όλα τα στοιχεία του έργου στο σύμπλεγμα.
  • Εάν αλλάξει ο πηγαίος κώδικας, θα επανεκκινήσει ολόκληρη τη διοχέτευση.

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

Μια ενότητα έργου μπορεί να είναι ένα κοντέινερ, ένα κοντέινερ Maven, ένα γράφημα Helm, ένα μανιφέστο για kubectl apply ή ακόμα και μια συνάρτηση OpenFaaS. Επιπλέον, οποιαδήποτε από τις ενότητες μπορεί να τραβηχτεί από ένα απομακρυσμένο αποθετήριο Git. Μια ενότητα μπορεί ή όχι να ορίζει υπηρεσίες, εργασίες και δοκιμές. Οι υπηρεσίες και οι εργασίες μπορεί να έχουν εξαρτήσεις, επομένως μπορείτε να προσδιορίσετε την ακολουθία ανάπτυξης μιας συγκεκριμένης υπηρεσίας και να οργανώσετε την εκκίνηση εργασιών και δοκιμών.

Το Garden παρέχει στον χρήστη έναν όμορφο πίνακα οργάνων (επί του παρόντος πειραματική κατάσταση), το οποίο εμφανίζει το γράφημα έργου: εξαρτήματα, ακολουθία συναρμολόγησης, εκτέλεση εργασιών και δοκιμών, συνδέσεις και εξαρτήσεις τους. Ακριβώς στο πρόγραμμα περιήγησης, μπορείτε να προβάλετε τα αρχεία καταγραφής όλων των στοιχείων του έργου και να ελέγξετε τι εξάγει ένα συγκεκριμένο στοιχείο μέσω HTTP (αν, φυσικά, έχει δηλωθεί ένας πόρος εισόδου για αυτό).

Εργαλεία για προγραμματιστές εφαρμογών που εκτελούνται στο Kubernetes
Πάνελ για τον κήπο

Αυτό το εργαλείο διαθέτει επίσης λειτουργία επανάληψης φόρτωσης, η οποία απλώς συγχρονίζει τις αλλαγές σεναρίου με το κοντέινερ στο σύμπλεγμα, επιταχύνοντας σημαντικά τη διαδικασία εντοπισμού σφαλμάτων της εφαρμογής. Ο κήπος έχει ένα καλό την τεκμηρίωση και όχι άσχημα σύνολο παραδειγμάτων, επιτρέποντάς σας να το συνηθίσετε γρήγορα και να αρχίσετε να το χρησιμοποιείτε. Παρεμπιπτόντως, μόλις πρόσφατα δημοσιεύσαμε μετάφραση άρθρου από τους συγγραφείς του.

Συμπέρασμα

Φυσικά, αυτή η λίστα εργαλείων για την ανάπτυξη και τον εντοπισμό σφαλμάτων εφαρμογών στο Kubernetes δεν περιορίζεται σε. Υπάρχουν πολλά ακόμη πολύ χρήσιμα και πρακτικά βοηθητικά προγράμματα που αξίζουν, αν όχι ξεχωριστό άρθρο, τουλάχιστον μια αναφορά. Πείτε μας τι χρησιμοποιείτε, ποια προβλήματα αντιμετωπίσατε και πώς τα λύσατε!

PS

Διαβάστε επίσης στο blog μας:

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο