Kubernetes – porady i wskazówki: o rozwoju lokalnym i teleobecności

Kubernetes – porady i wskazówki: o rozwoju lokalnym i teleobecności

Coraz częściej jesteśmy pytani o rozwój mikroserwisów w Kubernetesie. Programiści, zwłaszcza języków interpretowanych, chcą szybko poprawić kod w swoim ulubionym IDE i zobaczyć wynik bez czekania na kompilację/wdrożenie - po prostu naciskając klawisz F5. A jeśli chodzi o aplikację monolityczną, wystarczyło lokalnie zainstalować bazę danych i serwer WWW (w Dockerze, VirtualBoxie...), a potem od razu cieszyć się rozwojem. Wraz z pocięciem monolitów na mikrousługi i pojawieniem się Kubernetesa, wraz z pojawieniem się wzajemnych zależności, wszystko zrobiło się trochę trudniej. Im więcej tych mikroserwisów, tym więcej problemów. Aby znów cieszyć się rozwojem, trzeba podnieść więcej niż jeden lub dwa kontenery Docker, a czasem nawet kilkanaście... Ogólnie rzecz biorąc, wszystko to może zająć sporo czasu, ponieważ trzeba też być na bieżąco .

W różnych momentach próbowaliśmy różnych rozwiązań problemu. Zacznę od zgromadzonych obejść lub po prostu „kul”.

1. Kule

Większość IDE ma możliwość edycji kodu bezpośrednio na serwerze za pomocą protokołu FTP/SFTP. Ta ścieżka jest bardzo oczywista i od razu postanowiliśmy z niej skorzystać. Jej istota sprowadza się do:

  1. W poddzie środowisk deweloperskich (dev/review) uruchamiany jest dodatkowy kontener z dostępem SSH i przekazujący publiczny klucz SSH dewelopera, który zatwierdzi/wdroży aplikację.
  2. Na etapie początkowym (w kontenerze prepare-app) prześlij kod do emptyDiraby mieć dostęp do kodu z kontenerów aplikacji i serwera SSH.

Kubernetes – porady i wskazówki: o rozwoju lokalnym i teleobecności

Aby lepiej zrozumieć techniczną implementację takiego schematu, przedstawię fragmenty zaangażowanych konfiguracji YAML w Kubernetesie.

Konfiguracje

1.1. wartości.yaml

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

Tutaj vasya.pupkin jest wartością zmiennej ${GITLAB_USER_LOGIN}.

1.2. wdrożenie.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. sekret.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 }}

Ostatni dotyk

Potem pozostaje już tylko transfer wymagane zmienne gitlab-ci.yml:

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: programista, który uruchomił wdrożenie, może połączyć się za pomocą nazwy usługi (jak bezpiecznie przyznać dostęp do klastra, już powiedzieliśmy) z pulpitu za pośrednictwem protokołu SFTP i edytuj kod bez czekania na dostarczenie go do klastra.

Jest to całkowicie działające rozwiązanie, jednak z punktu widzenia implementacji ma oczywiste wady:

  • konieczność udoskonalenia wykresu Helma, co utrudnia jego odczytanie w przyszłości;
  • może z niego korzystać wyłącznie osoba, która wdrożyła usługę;
  • musisz pamiętać, aby następnie zsynchronizować go z lokalnym katalogiem z kodem i zatwierdzić go w Git.

2. Teleobecność

Projekt Teleobecność było znane już od dawna, ale my, jak to mówią, „nie zabraliśmy się do poważnego wypróbowania tego w praktyce”. Zapotrzebowanie jednak zrobiło swoje i teraz chętnie dzielimy się naszymi doświadczeniami, które mogą przydać się czytelnikom naszego bloga – zwłaszcza, że ​​na hubie nie było jeszcze innych materiałów na temat Teleobecności.

Krótko mówiąc, wszystko okazało się nie takie straszne. Wszystkie działania wymagające wykonania ze strony programisty umieściliśmy w pliku tekstowym wykresu Helm o nazwie NOTES.txt. Zatem po wdrożeniu usługi na Kubernetesie programista widzi instrukcje dotyczące uruchomienia lokalnego środowiska deweloperskiego w dzienniku zadań GitLab:

!!! Разработка сервиса локально, в составе 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
#########################################################################

Nie będziemy się szczegółowo rozwodzić nad krokami opisanymi w tej instrukcji... z wyjątkiem ostatniego. Co się stanie podczas uruchomienia Teleobecności?

Praca z teleobecnością

Przy uruchomieniu (używając ostatniego polecenia podanego w instrukcji powyżej) ustawiamy:

  • przestrzeń nazw, w której działa mikroserwis;
  • nazwy wdrożenia i kontenera, do którego chcemy penetrować.

Pozostałe argumenty są opcjonalne. Jeśli nasza usługa współdziała z interfejsem Kubernetes API i dla niego Utworzono konto serwisowe, musimy zamontować certyfikaty/tokeny na naszym pulpicie. W tym celu skorzystaj z opcji --mount=true (or --mount=/dst_path), który zamontuje root (/) z kontenera Kubernetes na naszym pulpicie. Po tym możemy (w zależności od systemu operacyjnego i sposobu uruchomienia aplikacji) wykorzystać „klucze” z klastra.

Na początek przyjrzyjmy się najbardziej uniwersalnej opcji uruchamiania aplikacji – w kontenerze Docker. Aby to zrobić, użyjemy klucza --docker-run i zamontuj katalog z kodem w kontenerze: -v `pwd`:/app

Należy pamiętać, że zakłada to uruchomienie z katalogu projektu. Kod aplikacji zostanie zamontowany w katalogu /app w pojemniku.

Dalej: -v /tmp/app/var/run/secrets:/var/run/secrets — aby zamontować katalog z certyfikatem/tokenem w kontenerze.

Po tej opcji na koniec pojawia się obraz, w którym będzie uruchamiana aplikacja. NB: Budując obraz, musisz określić CMD lub ENTRYPOINT!

Co dokładnie stanie się dalej?

  • W Kubernetesie dla określonego Wdrożenia liczba replik zostanie zmieniona na 0. Zamiast tego zostanie uruchomione nowe Wdrożenie - z kontenerem zastępczym backend.
  • Na pulpicie uruchomione zostaną 2 kontenery: pierwszy z Telepresence (będzie proxy żądań z/do Kubernetes), drugi z rozwijaną aplikacją.
  • Jeśli wykonamy do kontenera z aplikacją, to wszystkie zmienne ENV przekazane przez Helma podczas wdrożenia będą dla nas dostępne, dostępne będą również wszystkie usługi. Pozostaje tylko edytować kod w ulubionym IDE i cieszyć się efektem.
  • Na koniec pracy wystarczy zamknąć terminal, na którym działa Telepresence (zakończ sesję klawiszem Ctrl+C) - kontenery Dockera zatrzymają się na pulpicie, a w Kubernetesie wszystko wróci do stanu początkowego. Pozostaje tylko zatwierdzić, wystawić MR i przekazać go do przeglądu/scalenia/… (w zależności od przepływów pracy).

Jeśli nie chcemy uruchamiać aplikacji w kontenerze Dockera – np. programujemy nie w PHP, a w Go, a mimo to budujemy ją lokalnie – uruchomienie Teleobecności będzie jeszcze prostsze:

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

Jeśli aplikacja uzyskuje dostęp do API Kubernetes, konieczne będzie zamontowanie katalogu kluczy (https://www.telepresence.io/howto/volumes). Istnieje narzędzie dla systemu Linux pierwiastek:

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

Po uruchomieniu Teleobecności bez tej opcji --docker-run wszystkie zmienne środowiskowe będą dostępne w bieżącym terminalu, dlatego aplikację należy w nim uruchomić.

NB: Używając na przykład PHP, musisz pamiętać o wyłączeniu różnych akceleratorów op_cache, apc i innych na potrzeby programowania - w przeciwnym razie edycja kodu nie doprowadzi do pożądanego rezultatu.

Wyniki

Rozwój lokalny z Kubernetesem to problem, którego rozwiązania rośnie proporcjonalnie do rozprzestrzeniania się tej platformy. Otrzymując odpowiednie prośby od deweloperów (od naszych klientów), zaczęliśmy je rozwiązywać pierwszymi dostępnymi środkami, które jednak nie sprawdziły się na dłuższą metę. Na szczęście stało się to oczywiste nie tylko teraz i nie tylko dla nas, więc na świecie pojawiły się już bardziej odpowiednie środki, a teleobecność jest z nich najsłynniejsza (swoją drogą jest też rusztowanie z Google). Nasze doświadczenie w korzystaniu z niego nie jest jeszcze zbyt duże, ale już daje nam powód, aby polecić go naszym „kolegom w sklepie” - wypróbuj!

PS

Inne z serii porad i trików K8s:

Źródło: www.habr.com

Dodaj komentarz