Kubernetes tips & tricks: sullo sviluppo locale e la telepresenza

Kubernetes tips & tricks: sullo sviluppo locale e la telepresenza

Ci viene chiesto sempre più spesso di sviluppare microservizi in Kubernetes. Gli sviluppatori, soprattutto di linguaggi interpretati, desiderano correggere rapidamente il codice nel loro IDE preferito e vedere il risultato senza attendere la compilazione/distribuzione, semplicemente premendo F5. E quando si trattava di un'applicazione monolitica, bastava installare localmente un database e un server web (in Docker, VirtualBox...), per poi godersi subito lo sviluppo. Con la suddivisione dei monoliti in microservizi e l’arrivo di Kubernetes, con la comparsa delle dipendenze reciproche, tutto è diventato un po' più difficile. Maggiore è il numero di questi microservizi, maggiori saranno i problemi. Per godersi nuovamente lo sviluppo, è necessario creare più di uno o due contenitori Docker, a volte anche più di una dozzina... In generale, tutto ciò può richiedere molto tempo, poiché è necessario anche mantenerlo aggiornato .

In momenti diversi abbiamo provato diverse soluzioni al problema. E inizierò con le soluzioni alternative accumulate o semplicemente con le "stampelle".

1. Stampelle

La maggior parte degli IDE ha la possibilità di modificare il codice direttamente sul server utilizzando FTP/SFTP. Questo percorso è molto evidente e abbiamo subito deciso di utilizzarlo. La sua essenza si riduce a quanto segue:

  1. Nel pod degli ambienti di sviluppo (dev/review), viene lanciato un contenitore aggiuntivo con accesso SSH e inoltrando la chiave SSH pubblica dello sviluppatore che effettuerà il commit/deploy dell'applicazione.
  2. Nella fase iniziale (all'interno del contenitore prepare-app) trasferire il codice a emptyDiravere accesso al codice dai contenitori delle applicazioni e dal server SSH.

Kubernetes tips & tricks: sullo sviluppo locale e la telepresenza

Per comprendere meglio l'implementazione tecnica di tale schema, fornirò frammenti delle configurazioni YAML coinvolte in Kubernetes.

configurazioni

1.1. valori.yaml

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

Qui vasya.pupkin è il valore della variabile ${GITLAB_USER_LOGIN}.

1.2. distribuzione.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. segreto.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 }}

Tocco finale

Dopodiché non resta che trasferirsi variabili gitlab-ci.yml richieste:

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: lo sviluppatore che ha avviato la distribuzione può connettersi in base al nome del servizio (come garantire l'accesso in modo sicuro al cluster, abbiamo già detto) dal tuo desktop tramite SFTP e modifica il codice senza attendere che venga consegnato al cluster.

Questa è una soluzione completamente funzionante, ma dal punto di vista implementativo presenta evidenti svantaggi:

  • la necessità di affinare la carta Helm, che ne rende difficile la lettura in futuro;
  • può essere utilizzato solo dalla persona che ha utilizzato il servizio;
  • bisogna ricordarsi di poi sincronizzarlo con la directory locale con il codice e committarlo su Git.

2. Telepresenza

Progetto Telepresence è noto da molto tempo, ma noi, come si suol dire, "non siamo riusciti a provarlo seriamente nella pratica". Tuttavia, la domanda ha fatto il suo lavoro e ora siamo felici di condividere la nostra esperienza, che potrebbe essere utile ai lettori del nostro blog, soprattutto perché sull'hub non sono ancora presenti altri materiali sulla telepresenza.

In breve, tutto si è rivelato non così spaventoso. Abbiamo inserito tutte le azioni che richiedono l'esecuzione da parte dello sviluppatore in un file di testo del grafico Helm chiamato NOTES.txt. Pertanto, dopo aver distribuito il servizio a Kubernetes, lo sviluppatore vede le istruzioni per avviare l'ambiente di sviluppo locale nel registro del lavoro 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
#########################################################################

Non ci soffermeremo in dettaglio sui passaggi descritti in queste istruzioni... ad eccezione dell'ultimo. Cosa succede durante il lancio della Telepresenza?

Lavorare con la telepresenza

All'avvio (utilizzando l'ultimo comando specificato nelle istruzioni sopra), impostiamo:

  • spazio dei nomi in cui è in esecuzione il microservizio;
  • nomi della distribuzione e del contenitore che vogliamo penetrare.

Gli argomenti rimanenti sono facoltativi. Se il nostro servizio interagisce con e per l'API Kubernetes Account di servizio creato, dobbiamo montare certificati/token sul nostro desktop. Per fare ciò, utilizzare l'opzione --mount=true (o --mount=/dst_path), che monterà la radice (/) dal contenitore Kubernetes sul nostro desktop. Successivamente possiamo (a seconda del sistema operativo e di come viene avviata l'applicazione) utilizzare le "chiavi" del cluster.

Innanzitutto, esaminiamo l'opzione più universale per eseguire un'applicazione: in un contenitore Docker. Per fare questo utilizzeremo la chiave --docker-run e monta la directory con il codice nel contenitore: -v `pwd`:/app

Tieni presente che ciò presuppone l'esecuzione dalla directory del progetto. Il codice dell'applicazione verrà montato nella directory /app in un contenitore.

Next: -v /tmp/app/var/run/secrets:/var/run/secrets — per montare la directory con il certificato/token in un contenitore.

Questa opzione è infine seguita dall'immagine in cui verrà eseguita l'applicazione. NB: Quando si crea un'immagine, è necessario specificare CMD o ENTRYPOINT!

Cosa accadrà esattamente dopo?

  • In Kubernetes, per la distribuzione specificata, il numero di repliche verrà modificato in 0. Verrà invece avviata una nuova distribuzione, con un contenitore sostitutivo backend.
  • На десктопе запустятся 2 контейнера: первый — с Telepresence (он будет осуществлять проксирование запросов из/в Kubernetes), второй — с разрабатываемым приложением.
  • Se eseguiamo l'esecuzione nel contenitore con l'applicazione, tutte le variabili ENV trasferite da Helm durante la distribuzione saranno a nostra disposizione e saranno disponibili anche tutti i servizi. Non resta che modificare il codice nel tuo IDE preferito e goderti il ​​risultato.
  • Alla fine del lavoro, basta chiudere il terminale su cui è in esecuzione Telepresence (terminare la sessione con Ctrl+C): i contenitori Docker si fermeranno sul desktop e in Kubernetes tutto tornerà allo stato iniziale. Tutto ciò che resta è impegnarsi, emettere la MR e trasferirla in revisione/unione/... (a seconda dei flussi di lavoro).

Se non vogliamo eseguire l'applicazione in un contenitore Docker - ad esempio, sviluppiamo non in PHP, ma in Go, e la costruiamo comunque localmente - avviare Telepresence sarà ancora più semplice:

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

Se l'applicazione accede all'API Kubernetes, sarà necessario montare la directory delle chiavi (https://www.telepresence.io/howto/volumes). C'è un'utilità per Linux prova:

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

Dopo aver avviato Telepresence senza l'opzione --docker-run tutte le variabili d'ambiente saranno disponibili nel terminale corrente, quindi l'applicazione dovrà essere avviata in esso.

NB: Quando si utilizza, ad esempio, PHP, è necessario ricordarsi di disabilitare vari op_cache, apc e altri acceleratori per lo sviluppo, altrimenti la modifica del codice non porterà al risultato desiderato.

Risultati di

Lo sviluppo locale con Kubernetes è un problema la cui soluzione cresce proporzionalmente alla diffusione di questa piattaforma. Ricevendo richieste pertinenti dagli sviluppatori (dai nostri clienti), abbiamo iniziato a risolverli con i primi mezzi disponibili, che, tuttavia, non si sono dimostrati validi a lungo termine. Fortunatamente, questo è diventato evidente non solo ora e non solo per noi, quindi nel mondo sono già comparsi mezzi più adatti, e la Telepresenza è la più famosa di queste (a proposito, esiste anche impalcatura da Google). La nostra esperienza nell'utilizzo non è ancora delle migliori, ma ci dà già motivo di consigliarlo ai nostri “colleghi di negozio”: provatelo!

PS

Altro dalla serie di suggerimenti e trucchi K8:

Fonte: habr.com

Aggiungi un commento