Tipps und Tricks zu Kubernetes: über lokale Entwicklung und Telepräsenz

Tipps und Tricks zu Kubernetes: über lokale Entwicklung und Telepräsenz

Wir werden zunehmend nach der Entwicklung von Microservices in Kubernetes gefragt. Entwickler, insbesondere von interpretierten Sprachen, möchten Code in ihrer bevorzugten IDE schnell korrigieren und das Ergebnis sehen, ohne auf Build/Bereitstellung warten zu müssen – indem sie einfach F5 drücken. Und wenn es um eine monolithische Anwendung ging, reichte es aus, lokal eine Datenbank und einen Webserver (in Docker, VirtualBox...) zu installieren und dann sofort mit der Entwicklung zu beginnen. Mit der Aufteilung von Monolithen in Microservices und der Einführung von Kubernetes, mit dem Aufkommen von Abhängigkeiten voneinander, alles es wurde etwas schwieriger. Je mehr dieser Microservices, desto mehr Probleme. Um wieder Freude an der Entwicklung zu haben, müssen Sie mehr als ein oder zwei Docker-Container hochfahren, manchmal sogar mehr als ein Dutzend... Generell kann das alles ziemlich viel Zeit in Anspruch nehmen, da es auch auf dem neuesten Stand gehalten werden muss .

Zu verschiedenen Zeiten haben wir verschiedene Lösungen für das Problem ausprobiert. Und ich beginne mit den gesammelten Workarounds oder einfach „Krücken“.

1. Krücken

Die meisten IDEs bieten die Möglichkeit, Code über FTP/SFTP direkt auf dem Server zu bearbeiten. Dieser Weg liegt auf der Hand und wir haben uns sofort entschieden, ihn zu nutzen. Sein Wesen lässt sich wie folgt zusammenfassen:

  1. Im Pod der Entwicklungsumgebungen (dev/review) wird ein zusätzlicher Container mit SSH-Zugriff und Weiterleitung des öffentlichen SSH-Schlüssels des Entwicklers gestartet, der die Anwendung festschreiben/bereitstellen wird.
  2. In der Init-Phase (innerhalb des Containers). prepare-app) Übertragen Sie den Code an emptyDirZugriff auf den Code von den Anwendungscontainern und dem SSH-Server aus zu haben.

Tipps und Tricks zu Kubernetes: über lokale Entwicklung und Telepräsenz

Um die technische Umsetzung eines solchen Schemas besser zu verstehen, werde ich Fragmente der beteiligten YAML-Konfigurationen in Kubernetes bereitstellen.

Konfigurationen

1.1. Werte.yaml

ssh_pub_key:
  vasya.pupkin: <ssh public key in base64> 

Hier vasya.pupkin ist der Wert der Variablen ${GITLAB_USER_LOGIN}.

1.2. Bereitstellung.yaml

...
{{ if eq .Values.global.debug "yes" }}
      volumes:
      - name: ssh-pub-key
        secret:
          defaultMode: 0600
          secretName: {{ .Chart.Name }}-ssh-pub-key
      - name: app-data
        emptyDir: {}
      initContainers:
      - name: prepare-app
{{ tuple "backend" . | include "werf_container_image" | indent 8 }}
        volumeMounts:
        - name: app-data
          mountPath: /app-data
        command: ["bash", "-c", "cp -ar /app/* /app-data/" ]
{{ end }}
      containers:
{{ if eq .Values.global.debug "yes" }}
      - name: ssh
        image: corbinu/ssh-server
        volumeMounts:
        - name: ssh-pub-key
          readOnly: true
          mountPath: /root/.ssh/authorized_keys
          subPath: authorized_keys
        - name: app-data
          mountPath: /app
        ports:
        - name: ssh
          containerPort: 22
          protocol: TCP
{{ end }}
      - name: backend
        volumeMounts:
{{ if eq .Values.global.debug "yes" }}
        - name: app-data
          mountPath: /app
{{ end }}
        command: ["/usr/sbin/php-fpm7.2", "--fpm-config", "/etc/php/7.2/php-fpm.conf", "-F"]
...

1.3. Secret.yaml

{{ if eq .Values.global.debug "yes" }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Chart.Name }}-ssh-pub-key
type: Opaque
data:
  authorized_keys: "{{ first (pluck .Values.global.username .Values.ssh_pub_key) }}"
{{ end }}

Letzte Berührung

Danach bleibt nur noch die Übertragung Erforderliche gitlab-ci.yml-Variablen:

dev:
  stage: deploy
  script:
   - type multiwerf && source <(multiwerf use 1.0 beta)
   - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
   - werf deploy
     --namespace ${CI_PROJECT_NAME}-stage
     --set "global.env=stage"
     --set "global.git_rev=${CI_COMMIT_SHA}"
     --set "global.debug=yes"
     --set "global.username=${GITLAB_USER_LOGIN}"
 tags:
   - build

Voila: Der Entwickler, der die Bereitstellung gestartet hat, kann sich über den Dienstnamen verbinden (wie er sicher Zugriff auf den Cluster gewährt, wir haben es schon gesagt) von Ihrem Desktop über SFTP und bearbeiten Sie den Code, ohne darauf zu warten, dass er an den Cluster übermittelt wird.

Dies ist eine völlig funktionierende Lösung, die jedoch aus Sicht der Implementierung offensichtliche Nachteile hat:

  • die Notwendigkeit, das Helm-Diagramm zu verfeinern, was es in Zukunft schwierig macht, es zu lesen;
  • kann nur von der Person genutzt werden, die den Dienst bereitgestellt hat;
  • Sie müssen daran denken, es dann mit dem lokalen Verzeichnis mit dem Code zu synchronisieren und an Git zu übergeben.

2. Telepräsenz

Projekt Telepräsenz ist schon seit längerem bekannt, aber wir sind, wie man so schön sagt, „nicht dazu gekommen, es ernsthaft in der Praxis auszuprobieren.“ Die Nachfrage hat jedoch ihren Zweck erfüllt, und nun freuen wir uns, unsere Erfahrungen zu teilen, die für die Leser unseres Blogs nützlich sein können – insbesondere, da es auf dem Hub bisher keine weiteren Materialien zu Telepräsenz gab.

Kurz gesagt, es stellte sich heraus, dass alles nicht so beängstigend war. Wir haben alle Aktionen, die eine Ausführung seitens des Entwicklers erfordern, in einer Helm-Chart-Textdatei namens „ NOTES.txt. Nach der Bereitstellung des Dienstes auf Kubernetes sieht der Entwickler daher Anweisungen zum Starten der lokalen Entwicklungsumgebung im GitLab-Jobprotokoll:

!!! Разработка сервиса локально, в составе Kubernetes !!!

* Настройка окружения
* * Должен быть доступ до кластера через VPN
* * На локальном ПК установлен kubectl ( https://kubernetes.io/docs/tasks/tools/install-kubectl/ )
* * Получить config-файл для kubectl (скопировать в ~/.kube/config)
* * На локальном ПК установлен telepresence ( https://www.telepresence.io/reference/install )
* * Должен быть установлен Docker
* * Необходим доступ уровня reporter или выше к репозиторию https://gitlab.site.com/group/app
* * Необходимо залогинится в registry с логином/паролем от GitLab (делается один раз):

#########################################################################
docker login registry.site.com
#########################################################################

* Запуск окружения

#########################################################################
telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=/tmp/app --docker-run -v `pwd`:/app -v /tmp/app/var/run/secrets:/var/run/secrets -ti registry.site.com/group/app/backend:v8
#########################################################################

Auf die in dieser Anleitung beschriebenen Schritte gehen wir nicht näher ein... mit Ausnahme des letzten. Was passiert beim Start von Telepresence?

Arbeiten mit Telepräsenz

Beim Start (mit dem letzten in der obigen Anleitung angegebenen Befehl) stellen wir Folgendes ein:

  • Namespace, in dem der Microservice ausgeführt wird;
  • Namen der Bereitstellung und des Containers, in den wir eindringen möchten.

Die übrigen Argumente sind optional. Wenn unser Dienst mit und für die Kubernetes-API interagiert ServiceAccount erstellt, müssen wir Zertifikate/Tokens auf unserem Desktop bereitstellen. Nutzen Sie dazu die Option --mount=true (oder --mount=/dst_path), wodurch der Root (/) des Kubernetes-Containers auf unserem Desktop bereitgestellt wird. Danach können wir (abhängig vom Betriebssystem und der Art und Weise, wie die Anwendung gestartet wird) die „Schlüssel“ aus dem Cluster verwenden.

Schauen wir uns zunächst die universellste Möglichkeit zum Ausführen einer Anwendung an – in einem Docker-Container. Dazu verwenden wir den Schlüssel --docker-run und mounten Sie das Verzeichnis mit dem Code in den Container: -v `pwd`:/app

Bitte beachten Sie, dass hierbei die Ausführung aus dem Projektverzeichnis vorausgesetzt wird. Der Anwendungscode wird im Verzeichnis bereitgestellt /app in einem Behälter.

Next: -v /tmp/app/var/run/secrets:/var/run/secrets – um das Verzeichnis mit dem Zertifikat/Token in einem Container bereitzustellen.

Auf diese Option folgt schließlich das Image, in dem die Anwendung ausgeführt wird. NB: Beim Erstellen eines Bildes müssen Sie angeben CMD oder ENTRYPOINT!

Was genau wird als nächstes passieren?

  • In Kubernetes wird für das angegebene Deployment die Anzahl der Replikate auf 0 geändert. Stattdessen wird ein neues Deployment gestartet – mit einem Ersatzcontainer backend.
  • Auf dem Desktop werden zwei Container gestartet: der erste mit Telepresence (er leitet Anfragen von/an Kubernetes weiter), der zweite mit der zu entwickelnden Anwendung.
  • Wenn wir die Anwendung in den Container ausführen, stehen uns alle von Helm während der Bereitstellung übertragenen ENV-Variablen und alle Dienste zur Verfügung. Sie müssen nur noch den Code in Ihrer bevorzugten IDE bearbeiten und das Ergebnis genießen.
  • Am Ende der Arbeit müssen Sie nur noch das Terminal schließen, in dem Telepresence läuft (beenden Sie die Sitzung mit Strg+C) – Docker-Container werden auf dem Desktop angehalten und in Kubernetes kehrt alles in seinen Ausgangszustand zurück. Jetzt müssen Sie nur noch einen Commit durchführen, den MR ausstellen und ihn zur Überprüfung/Zusammenführung/... übertragen (abhängig von Ihren Arbeitsabläufen).

Wenn wir die Anwendung nicht in einem Docker-Container ausführen möchten – wir entwickeln beispielsweise nicht in PHP, sondern in Go und bauen sie trotzdem lokal auf – wird der Start von Telepresence noch einfacher:

telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=true

Wenn die Anwendung auf die Kubernetes-API zugreift, müssen Sie das Schlüsselverzeichnis mounten (https://www.telepresence.io/howto/volumes). Es gibt ein Dienstprogramm für Linux Beweis:

proot -b $TELEPRESENCE_ROOT/var/run/secrets/:/var/run/secrets bash

Nach dem Start von Telepresence ohne die Option --docker-run Alle Umgebungsvariablen sind im aktuellen Terminal verfügbar, daher muss die Anwendung dort gestartet werden.

NB: Wenn Sie beispielsweise PHP verwenden, müssen Sie daran denken, verschiedene op_cache, apc und andere Beschleuniger für die Entwicklung zu deaktivieren – andernfalls führt die Bearbeitung des Codes nicht zum gewünschten Ergebnis.

Ergebnisse

Die lokale Entwicklung mit Kubernetes ist ein Problem, dessen Lösung mit der Verbreitung dieser Plattform wächst. Nachdem wir entsprechende Anfragen von Entwicklern (unseren Kunden) erhalten hatten, begannen wir, diese mit den ersten verfügbaren Mitteln zu lösen, die sich jedoch auf lange Sicht nicht bewährten. Glücklicherweise ist dies nicht erst jetzt und nicht nur für uns offensichtlich geworden, so dass bereits geeignetere Mittel auf der Welt aufgetaucht sind, und Telepräsenz ist das bekannteste davon (übrigens gibt es sie auch). Gerüst von Google). Unsere Erfahrung mit der Anwendung ist zwar noch nicht so toll, gibt uns aber schon Grund, es unseren „Kollegen im Laden“ zu empfehlen – probieren Sie es aus!

PS

Weiteres aus der K8s-Tipps- und Trickserie:

Source: habr.com

Kommentar hinzufügen