Dicas e truques do Kubernetes: sobre desenvolvimento local e telepresença

Dicas e truques do Kubernetes: sobre desenvolvimento local e telepresença

Somos cada vez mais questionados sobre o desenvolvimento de microsserviços em Kubernetes. Os desenvolvedores, especialmente de linguagens interpretadas, desejam corrigir rapidamente o código em seu IDE favorito e ver o resultado sem esperar pela construção/implantação - simplesmente pressionando F5. E quando se tratava de uma aplicação monolítica, bastava instalar localmente um banco de dados e um servidor web (em Docker, VirtualBox...), e então aproveitar imediatamente o desenvolvimento. Com a divisão dos monólitos em microsserviços e a chegada do Kubernetes, com o surgimento das dependências entre si, tudo ficou um pouco mais difícil. Quanto mais desses microsserviços, mais problemas. Para aproveitar o desenvolvimento novamente, você precisa criar mais de um ou dois contêineres Docker, e às vezes até mais de uma dúzia... Em geral, tudo isso pode levar bastante tempo, pois também precisa ser mantido atualizado .

Em momentos diferentes tentamos soluções diferentes para o problema. E começarei com as soluções alternativas acumuladas ou simplesmente “muletas”.

1. Muletas

A maioria dos IDEs tem a capacidade de editar código diretamente no servidor usando FTP/SFTP. Este caminho é muito óbvio e decidimos imediatamente utilizá-lo. Sua essência se resume ao seguinte:

  1. No pod dos ambientes de desenvolvimento (dev/review), é lançado um container adicional com acesso SSH e encaminhamento da chave SSH pública do desenvolvedor que irá submeter/deploy a aplicação.
  2. No estágio init (dentro do contêiner prepare-app) transferir o código para emptyDirpara ter acesso ao código dos contêineres do aplicativo e do servidor SSH.

Dicas e truques do Kubernetes: sobre desenvolvimento local e telepresença

Para entender melhor a implementação técnica de tal esquema, fornecerei fragmentos das configurações YAML envolvidas no Kubernetes.

Configurações

1.1. valores.yaml

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

é vasya.pupkin é o valor da variável ${GITLAB_USER_LOGIN}.

1.2. implantação.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. segredo.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 }}

Toque final

Depois disso só falta transferir variáveis ​​​​gitlab-ci.yml necessárias:

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: o desenvolvedor que iniciou a implantação pode se conectar pelo nome do serviço (como conceder acesso seguro ao cluster, nós já falamos) do seu desktop via SFTP e edite o código sem esperar que ele seja entregue ao cluster.

Esta é uma solução totalmente funcional, mas do ponto de vista da implementação tem desvantagens óbvias:

  • a necessidade de refinar o gráfico do Helm, o que dificulta sua leitura no futuro;
  • só pode ser utilizado pela pessoa que implantou o serviço;
  • você precisa se lembrar de sincronizá-lo com o diretório local com o código e enviá-lo para o Git.

2. Telepresença

Projeto Telepresença é conhecido há muito tempo, mas nós, como dizem, “não tivemos tempo de tentar seriamente na prática”. Porém, a demanda fez o seu trabalho e agora temos o prazer de compartilhar nossa experiência, que pode ser útil aos leitores do nosso blog - principalmente porque ainda não houve outros materiais sobre Telepresença no hub.

Resumindo, tudo acabou não sendo tão assustador. Colocamos todas as ações que requerem execução por parte do desenvolvedor em um arquivo de texto de gráfico do Helm chamado NOTES.txt. Assim, após implantar o serviço no Kubernetes, o desenvolvedor vê instruções para iniciar o ambiente de desenvolvimento local no log de tarefas do 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
#########################################################################

Não nos deteremos detalhadamente nas etapas descritas nesta instrução... com exceção da última. O que acontece durante o lançamento da Telepresença?

Trabalhando com Telepresença

Na inicialização (usando o último comando especificado nas instruções acima), definimos:

  • namespace no qual o microsserviço está sendo executado;
  • nomes da implantação e do contêiner que queremos penetrar.

Os argumentos restantes são opcionais. Se nosso serviço interagir com e para a API Kubernetes Conta de serviço criada, precisamos montar certificados/tokens em nosso desktop. Para fazer isso, use a opção --mount=true (ou --mount=/dst_path), que montará a raiz (/) do contêiner Kubernetes em nosso desktop. Depois disso, podemos (dependendo do sistema operacional e de como o aplicativo é iniciado) usar as “chaves” do cluster.

Primeiro, vejamos a opção mais universal para executar um aplicativo - em um contêiner Docker. Para fazer isso usaremos a chave --docker-run e monte o diretório com o código no contêiner: -v `pwd`:/app

Observe que isso pressupõe a execução a partir do diretório do projeto. O código do aplicativo será montado no diretório /app em um contêiner.

Seguinte: -v /tmp/app/var/run/secrets:/var/run/secrets — para montar o diretório com o certificado/token em um contêiner.

Esta opção é finalmente seguida pela imagem na qual a aplicação será executada. NB: Ao construir uma imagem, você deve especificar CMD ou ENTRYPOINT!

O que exatamente acontecerá a seguir?

  • No Kubernetes, para a implantação especificada, o número de réplicas será alterado para 0. Em vez disso, uma nova implantação será lançada - com um contêiner substituto backend.
  • 2 contêineres serão lançados no desktop: o primeiro com Telepresença (fará proxy de solicitações de/para Kubernetes), o segundo com o aplicativo em desenvolvimento.
  • Se executarmos no contêiner com o aplicativo, todas as variáveis ​​ENV transferidas pelo Helm durante a implantação estarão disponíveis para nós e todos os serviços também estarão disponíveis. Resta apenas editar o código no seu IDE favorito e aproveitar o resultado.
  • Ao final do trabalho, basta fechar o terminal em que o Telepresence está rodando (encerrar a sessão com Ctrl+C) - os containers Docker irão parar no desktop, e no Kubernetes tudo retornará ao seu estado inicial. Tudo o que resta é confirmar, emitir o MR e transferi-lo para revisão/mesclagem/… (dependendo dos seus fluxos de trabalho).

Se não quisermos executar o aplicativo em um contêiner Docker - por exemplo, desenvolvemos não em PHP, mas em Go, e ainda o construímos localmente - iniciar o Telepresence será ainda mais simples:

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

Caso a aplicação acesse a API Kubernetes, será necessário montar o diretório de chaves (https://www.telepresence.io/howto/volumes). Existe um utilitário para Linux raiz:

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

Depois de lançar a Telepresença sem a opção --docker-run todas as variáveis ​​de ambiente estarão disponíveis no terminal atual, portanto o aplicativo deve ser iniciado nele.

NB: Ao usar, por exemplo, PHP, lembre-se de desabilitar vários op_cache, apc e outros aceleradores para desenvolvimento - caso contrário, a edição do código não levará ao resultado desejado.

Resultados de

O desenvolvimento local com Kubernetes é um problema cuja solução cresce proporcionalmente à difusão desta plataforma. Recebendo solicitações relevantes de desenvolvedores (de nossos clientes), começamos a resolvê-las pelos primeiros meios disponíveis, que, no entanto, não se mostraram eficazes no longo prazo. Felizmente, isso se tornou óbvio não só agora e não só para nós, então meios mais adequados já surgiram no mundo, e a Telepresença é o mais famoso deles (aliás, também existe andaime do Google). A nossa experiência de utilização ainda não é tão boa, mas já nos dá motivos para recomendá-lo aos nossos “colegas de loja” - experimente!

PS

Outros da série de dicas e truques do K8s:

Fonte: habr.com

Adicionar um comentário