Kubernetes tips & tricks: аб лакальнай распрацоўцы і Telepresence

Kubernetes tips & tricks: аб лакальнай распрацоўцы і Telepresence

Нас усё часцей пытаюцца пра распрацоўку мікрасэрвісаў у Kubernetes. Распрацоўнікі, асабліва інтэрпрэтаваных моў, жадаюць хутка паправіць код у каханай IDE і без чакання зборкі/дэплою ўбачыць вынік — па простым націску на F5. І калі гаворка ішла пра маналітнае прыкладанне, дастаткова было лакальна падняць базу дадзеных і вэб-сервер (у Docker, VirtualBox ...), пасля чаго - адразу ж атрымліваць асалоду ад распрацоўкай. З распілоўваннем маналітаў на мікрасэрвісы і прыходам Kubernetes, са з'яўленнем залежнасцяў сябар ад сябра, усё стала крыху складаней. Чым больш гэтых мікрасэрвісаў, тым больш праблем. Каб ізноў нацешыцца распрацоўкай, трэба падняць ужо не адзін і не два Docker-кантэйнера, а часам - нават не адзін дзясятак… Увогуле, на ўсё гэта можа сыходзіць досыць шмат часу, паколькі патрабуецца яшчэ і падтрымліваць у актуальным стане.

У розны час мы спрабавалі розныя рашэнні праблемы. І пачну я з назапашаных workarounds ці папросту «мыліц».

1. Мыліцы

Большасць IDE мае магчымасць кіраваць код прама на серверы з дапамогай FTP/SFTP. Такі шлях вельмі відавочны і мы адразу вырашылі ім скарыстацца. Сутнасць яго зводзіцца да наступнага:

  1. У pod'е ў акружэнняў для распрацоўкі (dev/review) запускаецца дадатковы кантэйнер з доступам па SSH і пракідам публічнага SSH-ключа таго распрацоўніка, што будзе камiціць/дэплоіць прыкладанне.
  2. На init-стадыі (у рамках кантэйнера prepare-app) пераносім код у emptyDir, Каб мець доступ да кода з кантэйнераў з дадаткам і SSH-сервера.

Kubernetes tips & tricks: аб лакальнай распрацоўцы і Telepresence

Для лепшага разумення тэхнічнай рэалізацыі такой схемы прывяду фрагменты задзейнічаных YAML-канфігурацый у Kubernetes.

канфігурацыі

1.1. values.yaml

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

Тут vasya.pupkin - Гэта значэнне зменнай ${GITLAB_USER_LOGIN}.

1.2. deployment.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 }}

Фінальная рыска

Пасля гэтага застанецца толькі перадаць патрэбныя зменныя 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

Вуаля: распрацоўшчык, які запусціў дэплой, можа падлучыцца па імені сэрвісу (як бяспечна выдаваць доступы да кластара, мы ўжо расказвалі) са свайго дэсктопа па SFTP і правіць код без чакання яго дастаўкі ў кластар.

Гэтае цалкам працоўнае рашэнне, аднак з пункта гледжання рэалізацыі мае відавочныя мінусы:

  • неабходнасць у дапрацоўцы Helm-чарта, што ў далейшым абцяжарвае яго чытанне;
  • выкарыстоўваць можа толькі той, хто задэплоіў сэрвіс;
  • трэба не забыцца потым сінхранізаваць яго з лакальнай дырэкторыяй з кодам і камітнуць у Git.

2. Telepresence

праект Тэлепрысутнасць вядомы дастаткова даўно, аднак сур'ёзна паспрабаваць яго на справе ў нас, што называецца, «не даходзілі рукі». Аднак попыт зрабіў сваю справу і зараз мы рады падзяліцца досведам, які можа апынуцца карысным чытачам нашага блога – тым больш, што на хабры да гэтага часу не было іншых матэрыялаў пра Telepresence.

Калі сцісла, то ўсё аказалася не так страшна. Усе дзеянні, якія патрабуюць выкананні з боку распрацоўніка, мы размясцілі ў тэкставым файле Helm-чарта, названым NOTES.txt. Такім чынам, распрацоўнік пасля дэплою сэрвісу ў Kubernetes бачыць інструкцыю па запуску лакальнага dev-акружэнні ў логу job'а 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
#########################################################################

Не будзем падрабязна спыняцца на апісаных у гэтай інструкцыі кроках… за выключэннем апошняга. Што ж адбываецца падчас запуску Telepresence?

Праца з Telepresence

Пры старце (па апошняй камандзе, указанай у інструкцыі вышэй) мы задаём:

  • прастора імёнаў (namespace), у якім запушчаны мікрасэрвіс;
  • імёны deployment'а і кантэйнера, у які жадаем пракрасціся.

Астатнія аргументы апцыянальныя. Калі наш сэрвіс узаемадзейнічае з Kubernetes API і для яго створаны ServiceAccount, нам неабходна змантаваць сертыфікаты/токены на свой дэсктоп. Для гэтага выкарыстоўваецца опцыя --mount=true (Або --mount=/dst_path), якая змантуе корань (/) з кантэйнера ў Kubernetes да нас на desktop. Пасля гэтага мы можам (у залежнасці ад АС і спосабу запуску прыкладання) скарыстацца "ключамі" ад кластара.

У пачатку разгледзім самы ўніверсальны варыянт запуску прыкладання – у Docker-кантэйнеры. Для гэтага скарыстаемся ключом --docker-run і прымантаваны дырэкторыю з кодам у кантэйнер: -v `pwd`:/app

Звярніце ўвагу, што тут маецца на ўвазе запуск з каталога з праектам. Код прыкладання будзе змантаваны ў дырэкторыю /app у кантэйнеры.

Далей: -v /tmp/app/var/run/secrets:/var/run/secrets - для мантавання дырэкторыі з сертыфікатам/токенам у кантэйнер.

За гэтай опцыяй варта, нарэшце, выява, у якім будзе запускацца прыкладанне. NB: Пры зборцы вобраза трэба абавязкова ўказаць CMD або ENTRYPOINT!

Што ж, уласна, адбудзецца далей?

  • У Kubernetes для паказанага Deployment'а колькасць рэплік будзе зменена на 0. Замест яго запусціцца новы Deployment - з падмененым кантэйнерам backend.
  • На дэсктопе запусцяцца 2 кантэйнера: першы – з Telepresence (ён будзе ажыццяўляць праксіраванне запытаў з / у Kubernetes), другі – з распрацоўваным дадаткам.
  • Калі exec'нуцца ў кантэйнер з дадаткам, то нам будуць даступныя ўсе ENV-пераменныя, перададзеныя Helm'ом пры дэплоі, а таксама даступныя ўсе сэрвісы. Застаецца толькі кіраваць код у каханай IDE і атрымліваць асалоду ад вынікам.
  • У канцы працы досыць проста зачыніць тэрмінал, у якім запушчаны Telepresence (абарваць сесію па Ctrl+C), – на дэсктопе спыняцца Docker-кантэйнеры, а ў Kubernetes усё вернецца ў пачатковы стан. Застанецца толькі камітнуць, аформіць MR і перадаць яго на review/merge/… (у залежнасці ад вашых працоўных працэсаў).

У выпадку, калі мы не жадаем запускаць прыкладанне ў Docker-кантэйнеры – напрыклад, мы распрацоўваем не на PHP, а на Go, і ўсёткі збіраем яго лакальна, – запуск Telepresence будзе яшчэ прасцей:

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

Калі дадатак звяртаецца да Kubernetes API, спатрэбіцца змантаваць дырэкторыю з ключамі (https://www.telepresence.io/howto/volumes). Для Linux ёсць утыліта корань:

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

Пасля запуску Telepresence без опцыі --docker-run усе зменныя асяроддзі будуць даступныя ў бягучым тэрмінале, таму запуск прыкладання неабходна рабіць менавіта ў ім.

NB: Пры выкарыстанні, напрыклад, PHP, трэба не забываць адключаць для распрацоўкі розныя op_cache, apc і іншыя акселератары - інакш праўка кода не будзе прыводзіць да жаданага выніку.

Вынікі

Лакальная распрацоўка з Kubernetes – праблема, запатрабаванне ў рашэнні якой расце прапарцыйна распаўсюджванню гэтай платформы. Атрымліваючы адпаведныя запыты з боку распрацоўшчыкаў (ад нашых кліентаў), мы пачалі іх вырашаць першымі даступнымі сродкамі, якія, аднак, не зарэкамендавалі сябе на доўгай дыстанцыі. Добра, гэта стала відавочна не толькі цяпер і не толькі нам, таму ў свеце ўжо з'явіліся больш прыдатныя сродкі, і Telepresence – самае вядомае з іх (дарэчы, ёсць яшчэ лясок ад Google). Наш досвед яго выкарыстання яшчэ не такі вялікі, але ўжо дае падставы рэкамендаваць «калегам па цэху» - паспрабуйце!

PS

Іншае з цыклу K8s tips & tricks:

Крыніца: habr.com

Дадаць каментар