Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deployando uma Phoenix app com Kubernetes no Go...

Deployando uma Phoenix app com Kubernetes no Google Cloud

O Kubernetes está aí para mudar a forma como fazemos deploy de aplicações para a nuvem. É uma ferramenta muito interessante, pois possibilita o deploy de várias aplicações de maneira padronizada, com fácil escalonamento vertical e horizontal.

Apesar de o ambiente Erlang/Elixir possuir algumas limitações quando rodando no k8s, ganhamos certa flexibilidade no deploy e gerenciamento de nossas apps em produção.

Nessa apresentação falarei um pouco da experiência do nosso time em fazer o deploy de uma aplicação Phoenix usando o k8s do GKE - Google Kubernetes Engine. Vou mostrar algumas particularidades de configuração da app, assim como o build usando Docker, o fluxo de deploy e a conexão com o banco de dados.

Essa apresentação aconteceu no Elug, na B2W em São Paulo.

Alguns links:
- Distillery: https://github.com/bitwalker/distillery
- Episódio número 7 do podcast Elixir Outlaws - https://elixiroutlaws.com/7
- App de exemplo no Github: https://github.com/philss/kates_app
- Twitter: https://twitter.com/philipsampaio
- Github: https://github.com/philss

Philip Sampaio

July 25, 2018
Tweet

More Decks by Philip Sampaio

Other Decks in Programming

Transcript

  1. Philip Sampaio • Desenvolvedor de software senior na Magnetis; •

    Trabalha com Ruby, Elixir e Javascript; • Criou o Floki. 2
  2. Objetivo dessa talk Explicar quais foram as decisões, desafios técnicos

    e da equipe na adoção do Kubernetes como plataforma para nossa infra. Também mostrar um pouco de código 3
  3. História • Nasceu em 2014, dentro da Google; • Foi

    baseado no projeto Borg, da Google, que por 15 anos rodou containeres em produção; • É desenvolvido pela Cloud native computing foundation • Já teve mais de 1700 pessoas contribuindo. 8
  4. Como era nossa stack • Majoritariamente Heroku; • Uma app

    Rails; • PostgreSQL, MongoDB, Redis e ElasticSearch. 10
  5. 2 anos trabalhando com containeres em dev • vimos o

    time crescer; • a necessidade de dividir o time e aplicação em partes menores; • o Heroku estava ficando caro . 16
  6. k8s • feito para aplicações containerizadas; • abstrai o conceito

    de servidor; • fácil de operar (mas não de manter um cluster!); • facilita escalar sua infra. 18
  7. k8s • uma grande comunidade; • possui algumas PaaS, como:

    • Amazon; • Digital Ocean; • Azure; • Google Cloud. 19
  8. A imagem Docker • gerada no CI; • contém só

    a OTP app; • gerada com o Distillery. 22
  9. Distillery • uma ferramenta p/ gerar releases das nossas aplicações;

    • releases são "pacotes" que dizem como nossa app deve rodar; • geralmente elas são auto-contidas. 24
  10. Distillery defp deps do [{:distillery, "~> 1.5", runtime: false}] end

    Precisamos rodar mix release p/ gerar a release. 25
  11. FROM elixir:1.6.4-alpine as builder ARG APP_NAME=kates_app ENV MIX_ENV=prod REPLACE_OS_VARS=true RUN

    apk add --update alpine-sdk coreutils curl RUN mix local.hex --force \ && mix local.rebar --force WORKDIR /opt/app COPY . /opt/app RUN mix deps.get && \ mix release --env=prod --verbose RUN mkdir -p /opt && \ mv /opt/app/_build/prod/rel/${APP_NAME} /opt/release 27
  12. FROM elixir:1.6.4-alpine as builder ARG APP_NAME=kates_app ENV MIX_ENV=prod REPLACE_OS_VARS=true RUN

    apk add --update alpine-sdk coreutils curl RUN mix local.hex --force \ && mix local.rebar --force WORKDIR /opt/app COPY . /opt/app RUN mix deps.get && \ mix release --env=prod --verbose RUN mkdir -p /opt && \ mv /opt/app/_build/prod/rel/${APP_NAME} /opt/release 28
  13. REPLACE_OS_VARS Possibilita que as env vars sejam diferentes entre o

    build e produção. É um hack do Distillery/Erlang. 30
  14. REPLACE_OS_VARS Seu config/prod.exs precisa declarar env var com $ {ENV_VAR_NAME}.

    config :kates_app, KatesApp.Repo, adapter: Ecto.Adapters.Postgres, url: "${DATABASE_URL}" 31
  15. FROM alpine:3.7 ARG REVISION ENV MIX_ENV=prod PORT=4000 REPLACE_OS_VARS=true APP_REVISION=$REVISION RUN

    apk update && apk --no-cache --update add bash curl openssl-dev postgresql-client WORKDIR /opt/app EXPOSE ${PORT} COPY --from=builder /opt/release . CMD /opt/app/bin/kates_app foreground 34
  16. FROM alpine:3.7 ARG REVISION ENV MIX_ENV=prod PORT=4000 REPLACE_OS_VARS=true APP_REVISION=$REVISION RUN

    apk update && apk --no-cache --update add bash curl openssl-dev postgresql-client WORKDIR /opt/app EXPOSE ${PORT} COPY --from=builder /opt/release . CMD /opt/app/bin/kates_app foreground 35
  17. Multi stage build Permite que em um Dockerfile seja possível

    ter dois passos de build (ou mais). A nossa segunda parte não precisa ter Elixir pois a release do Distillery já é auto-contida. 36
  18. O script de build no CI image_name="gcr.io/kates-project/kates-app:$REVISION" docker build \

    --build-arg REVISION=$REVISION \ -t $image_name \ -f deploy/Dockerfile . docker push gcr.io/kates-project/kates-app:$REVISION 38
  19. Um cluster k8s possui 2 partes principais 1. O master,

    que é o que controla o cluster; 2. Os nodes que são reponsáveis por rodar nossos Objetos. 41
  20. Objetos do kubernetes • entidades persistidas que representam o estado

    do cluster; • alguns exemplos desses objetos: • deployment; • service; • ingress. • specs geralmente em YAML. 42
  21. Pra aplicar uma mudança ao cluster $ kubectl apply -f

    spec-do-objeto.yaml Remover essa mudança $ kubectl delete -f spec-do-objeto.yaml 43
  22. 44

  23. Deployment • é onde descrevemos como nossa aplicação será deployada;

    • é a descrição de um Pod com um ou mais containeres; • nosso container vai ser descrito aqui. 45
  24. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: api spec: replicas: 3

    template: metadata: labels: name: api spec: containers: - name: api image: gcr.io/kates-project/kates-app:53af84191asf85 imagePullPolicy: Always ports: - containerPort: 4000 46
  25. Service • o Service serve para expor uma determina porta

    ou portas para um conjunto de pods; • funciona como um "load balancer"; • é também conhecido como "back-end" informalmente. 47
  26. apiVersion: v1 kind: Service metadata: name: api-svc labels: name: api-svc

    spec: selector: name: api type: NodePort ports: - port: 80 protocol: TCP name: http targetPort: 4000 48
  27. Ingress • conecta o mundo exterior aos services; • é

    onde se configura o SSL; • informalmente conhecido como "front-end". 49
  28. apiVersion: extensions/v1beta1 kind: Ingress metadata: name: api-ingress annotations: kubernetes.io/ingress.class: "gce"

    labels: name: api-ingress spec: tls: - secretName: tls-secrets-20180723 backend: serviceName: api-svc servicePort: 80 50
  29. 51

  30. O padrão sidecar É uma forma de manter um proxy

    p/ o seu banco no mesmo Pod, ao lado da sua aplicação. Conectamos como se fosse "localhost". E é bem mais seguro. 55
  31. As incompatibilidades com ecossistema Elixir Muitos dos conceitos do k8s

    e do Erlang/OTP são similares. Isso faz com que às vezes não sejam muito compatíveis. 58
  32. Feature Motivo Equivalente no k8s? É contornável? Hot code swapping

    Os containeres são efêmeros. Não compartilham disco, por padrão Não Sim (mas difícil) Clustering de nodes É necessário ter dois tipos de container: um master e node Sim Sim Controle de recursos de hardware O próprio k8s faz isso Sim Não muito 59
  33. Quando não usar k8s com Elixir? • Se performance e

    recursos são críticos p/ sua app; • Se você quer ter controle de todo o sistema operacional; • Se você não vai trabalhar em um cenário com vários serviços. 61
  34. Onde conhecer mais? • Docs do Google Cloud; • Livro

    Site Reliability Engineering do Google; • @kubernetesio • app de exemplo: https://github.com/philss/kates_app 62