Ir para o conteúdo
ou

Software livre Brasil

Minha rede

 Voltar a planetas
Tela cheia Sugerir um artigo
 Feed RSS

Planeta do Gnome Brasil

11 de Fevereiro de 2010, 0:00 , por Software Livre Brasil - | Ninguém está seguindo este artigo ainda.

Georges Stavracas: GNOME Settings: more GNOME, more settings

4 de Fevereiro de 2019, 1:19, por Planeta GNOME Brasil - 0sem comentários ainda

Before deep diving into the more extensive architectural changes that I’ve been working on GNOME Shell and Mutter, let’s take a moment to highlight the latest changes to GNOME Settings.

Being the (co)maintainer of Settings for a full year now, the development pace has been great so far. I would go as far as to say that the project is healthy and sustainable now. The shared maintainership model that we adopted allows us to decrease the review time, and yet make sure that every single contribution is reviewed by at least one maintainer.

Looking at the numbers, we managed to review 110 merge requests targeting 3.32 (and more if we consider the ones targeting 3.30 as well!). That is almost one merge request reviewed and merged every single day. Considering that this is mostly composed of volunteer work, I am comfortable to say that we found a very efficient maintainership model.

Without further ado, let’s see what happened during this cycle.

New Panels

Applications

Mockups for controlling application settings were around and being discussed for some time now, but it eventually came the day where they were to be implemented. And thanks to the fantastic work by Matthias Clasen, we now have a new Applications panel:

Applications panelThe new Applications panel showing information and settings of a Flatpak-based application.

Flatpak-based applications naturally have more system integration points. There are ongoing ideas being discussed about which other integration points should be, but nothing settled so far.

Applications panel for a non-Flatpak applicationNon-Flatpak applications don’t have as many controllable integration points.

There are more immediate improvements that will land before GNOME 3.32 release, but it’s a great addition already.

Sound

Robert Ancell has been working on the Sound panel redesign for some time now, and it’s close to landing. This is how it looks like so far:

Redesigned Sound panelRedesigned Sound panel with a vertical layout and better organization of the options.

Thanks to the awesome work of Outreachy intern Clarissa Borges, we have user testing results of this new layout. And they look pretty damn good! Overall, the testing clearly shows how much of an improvement the redesigned panel is.

Under the Hood

Display

The Display panel is one of the hardest ones to deal with. Mostly because the almost entirety of the UI is programatically done. This was incredibly annoying, since it is somewhat hard to replace bits of the code with template widget without accidentally changing a lot of code.

Thanks to Benjamin Berg, however, this is not a problem anymore: the Display panel now uses modern best practices and is composed of smaller widgets. A new monitor scale widget is also on the way, although it potentially can be postponed to GNOME 3.34.

Responsive Panels

Purism is a great upstream player in GNOME, and so far demonstrated deep understanding on how upstream communitites work. Naturally, I had the chance to review and eventually land some fantastic working making GNOME Settings responsive:

Responsive GNOME SettingsResponsive GNOME Settings.

More to Come

Thanks to the hard work of these and many other awesome contributors, GNOME Settings is improving the way users can control their systems. But these are not the only improvements that will be part of 3.32, and of course, there is much more being targeted to 3.34!



Georges Stavracas: GNOME Shell and Mutter: better, faster, cleaner

31 de Janeiro de 2019, 13:51, por Planeta GNOME Brasil - 0sem comentários ainda

The very first update in the series is about GNOME Shell and Mutter. I’ve been increasingly involved with the development of those two core components of GNOME, and recently this has been the focus of my development time.

Fortunately, Endless allows me to use part of my work time to improve it. Naturally, I prioritize my upstream work considering what will impact Endless OS the most. So far, that lead to a series of very nice improvements to Mutter and GNOME Shell.

GNOME Shell

Most of my work time dedicated to GNOME Shell was oriented to performance and cleanup. At Endless, we have a modified GNOME Shell that constantly needs to be rebased. Since I’m taking care of these rebases now, it makes sense for me to also make myself familiar with the vanilla GNOME Shell codebase.

ShellGenericContainer

I’ll start with the work that makes me the proudest: removing the Shell.GenericContainer class.

First, a bit of history.

There was a time when GJS, the JavaScript engine that GNOME Shell is based on, did not support subclassing GObjects and overriding virtual functions. We could only instantiate GObject-based classes, and subclass them, all thanks to GObject-Introspection, but not override their virtual functions. This made, for example, implementing ClutterContent in JavaScript impossible.

For that reason, GNOME Shell developers created ShellGenericContainer: an actor that sends signals for various virtual functions. Because GJS supports signals, that worked well.

There are a few problems with that approach though:

  • Signals are slow, and should not be used on hot paths like layouting or rendering;
  • Going in and out of JavaScript territory is expensive;
  • It makes the JavaScript code slightly more complicated;

Thanks to the fantastic work by Philip Chimento, Florian Muellner, and Cosimo Cecchi, GJS now supports overriding virtual functions. And that made Shell.GenericContainer obsolete. So I spent quite some time untangling it from GNOME Shell, and results were positive:

https://gitlab.gnome.org/GNOME/gnome-shell/uploads/b61233544ada29773b87de08e48beeb8/ShellGenericContainer.pngIn general, running GNOME Shell without Shell.GenericContainer (blue line) led to more stable framerates compared to the current state (red line).

This is now merged and will be available with GNOME Shell 3.32, to be released on March 2019.

Improvements to the texture cache

After various investigations, another potential improvement that showed up was on StTextureCache. Textures (icons, image files, etc) are cached in GNOME Shell by StTextureCache, and that happened by keeping a ClutterTexture object alive.

That turned out to be a problem.

ClutterTexture is deprecated. Clutter has a new interface for drawing the contents of an actor: ClutterContent. It does not necessarily make the code faster, but it allows different actors to share a single ClutterContent without having to override ClutterActor.paint(). In other words, it is a nice and sane abstraction layer to control what an actor is drawing.

So I went ahead and wiped out ClutterTexture from StTextureCache. Then wiped it out entirely from GNOME Shell.

Unexpectedly, it made a small but noticeable difference! Icons are now slightly faster to load, but the most visible impact was in the startup animation.

Mutter

I did not know how fun and exciting compositors could be. It definitely is a new passion of mine, working on Mutter! So much has happened that it’ll be hard to summarize.

Goodbye, Autotools

During last year’s GUADEC, Jonas Ådahl worked on a Meson port of Mutter. After a series of reviews, and a few follow-up fixes, it reached almost complete feature parity with Autotools – the only exception being installed tests.

So I went ahead and added installed tests to the Meson build too.

And also removed Autotools.

Naturally, builds are much faster now. Saving us a few minutes per day.

Wayland vs X11

Another area that was interesting to work on was untangling X11-specific code from Wayland, and vice-versa. There are a handful of developers working on that already, and I had my fair share in better splitting X11 and Wayland code paths in Mutter.

Specifically, I worked on splitting X11-specific code from MetaWindowActor into subclasses. Mutter already handles different surfaces correctly; on X11 sessions, all surfaces are MetaSurfaceActorX11, and under Wayland, MetaSurfaceActorWayland.

MetaWindowActor has now the same split: Wayland windows have a MetaWindowActorWayland associated, while X11 windows have MetaWindowActorX11.

Interestingly, XWayland windows are X11 windows with a Wayland surface. You can check that using GNOME Shell’s Looking Glass:

wayland vs x11.gifExample of a Xwayland window; it has a MetaSurfaceActorWayland surface, and a MetaWindowActorX11 actor associated.

There’s a lot more happening in this front, but I’ll spare the words for now. You’ll hear more about it in the future (and not necessarily from me).

CPU-side picking

More recently, I’ve been experimenting with the Cogl journal and ironing out a few bugs that are preventing a completely CPU-side picking implementation.

Picking is the process to figure out which element is beneath the cursor. There are two big approaches: geometry-based, and color-based. On games, the latter is the usual approach: each object in the scene is drawn with a plain color, and the final image is read to find out the color beneath a point. Geometry-based picking is what browsers usually do, and it’s basically math around rectangles.

Clutter uses color-based picking, but has a nice feature around that: a journal that tracks drawing operations and, under some conditions, hits an optimized path and does geometry-based picking. This is interesting for Mutter and GNOME Shell because it avoids sending draw operations to the GPU unecessarily when picking, reducing resource usage.

Unfortunately, due to various bugs and implementation details, we do not hit this optimization, causing GPU commands to be issued when they could be avoided.

Figuring out these bugs is what I’ve been experimenting with lately.

 


 

There’s much more that happened, so I will probably do a part 2 of this article soon. But those are big points already, and the post is becoming lengthy.

Many of these experiments and investigations already landed, and will be available with GNOME 3.32. This is all valuable work that is partially sponsored by my employer, Endless, and I’m happy to keep working on it!



Georges Stavracas: Sorry for the silence

31 de Janeiro de 2019, 13:49, por Planeta GNOME Brasil - 0sem comentários ainda

It’s been more than 6 months that I do not write in this space. Honestly, that’s the longest period of silence I’ve ever had.

There are various factors that, combined, ended up causing this period of seclusion. Learning about new, massive projects (GNOME Shell, Mutter and GNOME Settings) is one of them. Moving to a new home and marriage is another.

After finishing Masters last year, I have spent the time working with Endless full-time, and dedicating myself to parallel projects, such as Japanese language, music, gardening, and martial arts. It’s being wonderful, but that somehow distracted me from communicating changes to the community.

And for that, my apologies.

I’ll publish a series of blog posts talking about various GNOME-related activities that I’ve been involved since the last update. Hopefully they will be interesting enough.



Jonh Wendell: Istio: O que acontece quando o painel de controle está inativo?

15 de Novembro de 2018, 10:50, por Planeta GNOME Brasil - 0sem comentários ainda

Olá, pessoal!

Eu fiz alguns experimentos no Istio derrubando alguns componentes do painel de controle e observando o que acontece com os aplicativos e a mesh de serviço. Abaixo você encontrará minhas anotações.

Pilot

O Pilot é responsável pelo recurso de gerenciamento de tráfego do Istio e também é responsável por atualizar todos os sidecars com a configuração de mesh mais recente.

Quando o Pilot inicia, ele escuta na porta 15010 (gRPC) e 8080 (HTTP legado).

Quando o sidecar do aplicativo (Envoy, Istio-Proxy) é iniciado, ele se conecta ao pilot.istio-system:15010, obtém a configuração inicial e mantém-se conectado.
Sempre que o pilot detecta uma alteração na mesh (ele monitora os recursos do kubernetes), ele envia uma nova configuração para o sidecars por meio dessa conexão gRPC.

– Se o pilot cair, essa conexão do gRPC entre o piloto e o sidecar será perdida e os sidecars tentarão se reconectar ao pilot indefinidamente.
– O tráfego não é afetado se o pilot estiver fora do ar, porque toda a configuração enviada para o sidecar reside na memória do sidecar.
– Mudanças na mesh (como novos pods, regras, serviços, etc) não chegam aos sidecars, porque o pilot não está lá para ouvir mudanças e encaminhá-las para o sidecars.
– Uma vez que o pilot está ativo novamente, os sidecars se conectam (porque estão sempre tentando se reconectar) a ele e pegam a configuração de mash mais recente.

Mixer Policy

Policy aplica a política de rede.

Mixer lê a configuração na inicialização e também monitora kubernetes para alterações. Uma vez que novas configurações são detectadas, o mixer as carrega em sua memória.

Os sidecars verificam (chamam) o pod mixer policy para cada solicitação direcionada a aplicação (serviço).

Se o pod mixer policy estiver inativo, todas as solicitações para o serviço falharão com um erro “503 UNAVAILABLE: no healthy upstream” – porque o sidecar não pôde se conectar ao pod policy.

No Istio 1.1, há uma nova configuração (policyCheckFailOpen) [global] que permite uma política “Fail Open”, isto é, se o pod mixer policy não estiver alcançável, todas as requisições terão sucesso em vez de falhar com um erro 503. Por padrão, essa configuração está definida com false, isto é, “Fail Close”.

Enquanto o mixer estiver inativo, tudo o que fazemos na mesh (como adicionar regras, alterar qualquer configuração, etc) não terá efeito nos aplicativos até que o mixer esteja ativo novamente.

Mixer Telemetry

Telemetry fornece informações de telemetria para os addons.

Os Sidecars chamam o pod Telemetry após cada solicitação ser concluída, fornecendo informações de telemetria aos adaptadores (Prometheus, etc). Ele faz isso em lotes de 100 solicitações ou 1 segundo (na configuração padrão), o que vier primeiro, para evitar chamadas excessivas ao pod Telemetry.

Se o pod Telemetry estiver desativado, os sidecars registram um erro (no stderr do pod) e descartam as informações de telemetria. As solicitações não são afetadas por isso, como acontece quando o pod Policy está inativo. Uma vez que o pod Telemetry está ativo novamente, ele começa a receber informações de telemetria dos sidecars.

Outras notas

Vale a pena observar que o Istio permite uma instalação personalizada de seus componentes de plano de controle. Por exemplo, se você não precisa de Policy, pode desabilitar totalmente o mixer policy. Essa modularidade está melhorando no Istio 1.1. Para mais informações, confira a documentação.

Além disso, o pilot, mixer policy e a mixer telemetry funcionam bem em uma configuração de alta disponibilidade (HA), com várias réplicas sendo executadas ao mesmo tempo. Na verdade, a configuração padrão vem com um HorizontalPodAutoscaler que varia de 1 a 5 para esses pods. (Curioso? Veja isso e isso).



Isaac Ferreira Filho: Um Novo Atalho no Evince. O que há por trás disso?

18 de Outubro de 2018, 13:28, por Planeta GNOME Brasil - 0sem comentários ainda

Não sei se você está sabendo, mas a versão nova do Evince (3.30) está com um atalho bastante útil.

Agora você pode destacar uma parte do texto selecionando-a com o mouse e pressionando as teclas:

CTRL + H

Este post poderia parar por aqui, mas eu gostaria de escrever mais um pouco acerca do que está por trás de um simples atalho.

O Evince e Eu

O Evince é um visualizador de documentos do GNOME. De acordo com a Wikipedia ele foi incluído no GNOME em sua versão 2.12.

No meu dia a dia, de grande consumo de informações através de arquivos PDF, um bom leitor é fundamental. O Evince sempre supriu bem este papel, porém havia um ponto que me incomodava: a falta de um atalho para destacar as partes relevantes do texto.

Para fazer isso eu tinha que utilizar o mouse, movimentando o cursor do texto até o botão de destaque, ou fazendo o contrário.

O Atalho

Em conversas informais no canal do IRC do GNOME Brasil1, comentei que sentia falta deste recurso. Na época usava o Evince 3.28.

Durante a conversa, o amigo Felipe Borges feborges pediu um tempinho e, em poucos minutos, disse que tinha implementado tal recurso e que ele viria, possivelmente, na próxima versão do Evince.

Lembro que fiquei num misto de alegria e de espanto pela rapidez do processo e também pela consideração de feborges.

Bem, estou usando a versão 3.30 do Evince e estou usando bastante o recurso. Recomendo 😉

Queria concluir este post agradecendo ao Felipe pelo recurso, mas também deixando uma reflexão sobre como o software livre e open source é produzido e melhorado.

Acompanho, em muitos espaços, usuários reclamando da falta do recurso X ou do bug Y, porém pouca gente abre alguma issue para relatar algum bug ou propor alguma melhoria.

Diversas vezes esse modelo de desenvolvimento de software é enquadrado em uma lógica diferente e sofre análises, muito deslocadas a meu ver, como se fosse um modelo proprietário. Mas isso é um papo para um outro post.


  1. irc.gnome.org #gnome-br 


Isaac Ferreira Filho: Fedora 29 Beta

11 de Outubro de 2018, 19:07, por Planeta GNOME Brasil - 0sem comentários ainda

Estou completando duas semanas de uso do Fedora 29 Beta. Até o momento só tive um crash. Por aqui já estamos no GNOME 3.30.1.

No geral a experiência está sendo bastante agradável e estável. Abaixo eu descrevo como fiz para transformar a versão 28 em 29.

Se quiser atualizar o seu sistema, faça por sua conta e risco ok? Lembre-se: faça backup! Desative o rpm-fusion (eu não fiz, mas é aconselhado fazer).

Atualizar o Sistema Atual

sudo dnf upgrade --refresh

Instalar o Plugin para Atualização

sudo dnf install dnf-plugin-system-upgrade

Baixar os Pacotes

sudo dnf system-upgrade download --refresh --releasever=29

Finalizar

sudo dnf system-upgrade reboot

Se tudo der certo…

dnf clean packages

O que você está achando do Fedora 29 ou do GNOME 3.30. Conta aí!



Jonh Wendell: Istio, injeção de sidecar: ativando injeção automática, adicionando exceções e depuração

24 de Setembro de 2018, 21:25, por Planeta GNOME Brasil - 0sem comentários ainda

Ei pessoal. Hoje vamos falar sobre um pouco sobre injeção de sidecar do Istio em Kubernetes.

O Istio no Kubernetes funciona usando um modelo de deployment de sidecar, onde um contêiner auxiliar (sidecar) é anexado ao seu contêiner principal (serviço) em um único Pod. Ao fazer isso, seu serviço e o contêiner de sidecar compartilham a mesma rede e podem ser vistos como dois processos em um único host. Assim, o Istio pode interceptar todas as chamadas de rede de e para o seu contêiner principal e fazer sua mágica para melhorar a comunicação de serviço a serviço.

Esse contêiner de sidecar, denominado istio-proxy, pode ser injetado em seu pod de serviço de duas maneiras: manual e automaticamente. Mesmo essa técnica manual não é 100% feita à mão. Vamos ver.

Injeção manual

O Istio vem com uma ferramenta chamada istioctl. Sim, parece que é inspirado em alguma outra ferramenta amada :). Uma de suas funcionalidades é a capacidade de injetar o sidecar istio-proxy em seu pod de serviço. Vamos usá-la, usando um simples pod de busybox como exemplo:

$ cat busybox.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox-test
spec:
  containers:
  - name: busybox-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep infinity']

$ istioctl kube-inject -f busybox.yaml > busybox-injected.yaml

[jwendell@jw-laptop ~]$ cat busybox-injected.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
  name: busybox-test
spec:
  containers:
  - command:
    - sh
    - -c
    - echo Hello Kubernetes! && sleep infinity
    image: busybox
    name: busybox-container

  - image: docker.io/istio/proxyv2:1.0.2
    imagePullPolicy: IfNotPresent
    name: istio-proxy
    args:
      - proxy
      - sidecar
   ...

Como você pode ver acima, esse comando gerou outro arquivo yaml, semelhante ao input (pod busybox), mas com o sidecar (istio-proxy) adicionado ao pod. Então, de alguma forma, isso não é um trabalho manual de 100%, certo? Isso nos poupa um monte de digitação. Você está pronto para aplicar este yaml modificado ao seu cluster do kubernetes:

$ kubectl apply -f busybox-injected.yaml
# ou, se você não quiser ter um arquivo intermediário, aplique diretamente usando o arquivo original:
$ kubectl apply -f <(istioctl kube-inject -f busybox.yaml)

Uma pergunta natural que pode surgir é: de onde vêm esses dados? Como ele sabe que a imagem do sidecar é docker.io/istio/proxyv2:1.0.2? A resposta é simples: Todos os dados vêm de um ConfigMap que vive no plano de controle do Istio, no namespace istio-system:

$ kubectl -n istio-system describe configmap istio-sidecar-injector
Name:         istio-sidecar-injector
Namespace:    istio-system

Data
====
config:
----
policy: enabled
template: |-
  initContainers:
  - name: istio-init
    image: "docker.io/istio/proxy_init:1.0.2"
...

Você pode editar este ConfigMap com os valores que deseja injetar nos seus pods. Como você pode ver, esse é basicamente um modelo que será adicionado à sua definição de pod. Se você quiser usar outra imagem para o contêiner istio-proxy, use outra tag ou deseje ajustar qualquer coisa que será injetada, essa é a coisa que você precisa editar. Lembre-se que este ConfigMap é usado para injeção em todos os seus pods na malha de serviço. Seja cuidadoso 🙂

Porque istioctl lê um ConfigMap para saber o que injetar, isso significa que você precisa ter acesso a um cluster do Kubernetes em funcionamento com o Istio devidamente instalado. Se por algum motivo você não tiver tal acesso, você ainda pode usar istioctl, fornecendo um arquivo de configuração local:

# execute isso antes, com acesso apropriado ao cluster k8s
$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml
# sinta-se à vontade para modificar esse arquivo, e você pode executar a qualquer momento depois:
$ istioctl kube-inject --injectConfigFile inject-config.yaml ...

Injeção automática

A outra maneira de ter istio-proxy injetado em seus pods é dizendo ao Istio para fazer isso automaticamente por você. Na verdade, isso é ativado por padrão para todos os namespaces com o rótulo istio-injection=enabled. Isso significa que, se um namespace tiver esse rótulo, todos os pods dentro dele receberão o sidecar istio-proxy automaticamente. Você não precisa executar istioctl ou fazer qualquer coisa com seus arquivos yaml!

O modo como funciona é bem simples: ele faz uso de uma funcionalidade do Kubernetes chamado MutatingWebhook que consiste em Kubernetes notificando o Istio sempre que um novo pod está prestes a ser criado e dando ao Istio a chance de modificar a especificação do pod durante seu uso, pouco antes de realmente criar esse pod. Assim, o Istio injeta o sidecar istio-proxy usando o template encontrado no ConfigMap que vimos acima.

Soa bem, certo?

Você pode estar se perguntando: Ei, isso é muito intrusivo! Sim, tudo depende das suas necessidades. Esta injeção automática é muito flexível:

  • No istio-sidecar-injector ConfigMap, há um sinalizador booleano indicando se esta injeção automática está habilitada ou não.
  • Somente os namespaces rotulados adequadamente receberão a injeção automática. Você pode escolher seletivamente quais namespaces terão injeção automática.
  • Além disso, você pode ajustar esse rótulo, alterá-lo ou mesmo remover esse filtro (o que significa que a injeção ocorrerá automaticamente em todos os namespaces! Seja cuidadoso!) Editando o MutatingWebhookConfiguration: kubectl -n istio-system edit MutatingWebhookConfiguration istio-sidecar-injector. Procure o campo namespaceSelector.
  • Você pode evitar que a injeção aconteça em pods seletivos. Se um pod tiver a anotação sidecar.istio.io/inject: "false", então o Istio não irá injetar o sidecar nele.
  • Você pode inverter a lógica se você for mais conservador. Desative a injeção automática para todos e ative-a apenas para pods selecionados. Para isso, você só precisa definir a política como falsa (kubectl -n istio-system edit configmap istio-sidecar-injector) e anotar os pods que você deseja para injetar com sidecar.istio.io/inject: "true"

Eu quero mais flexibilidade!

Aqui está um caso de uso em que a flexibilidade acima não foi suficiente:

Para aqueles que não estão familiarizados com o Openshift (distribuição de Kubernetes da Red Hat), ele possui uma funcionalidade chamada source-to-image – s2i, que magicamente cria imagens de contêiner com base no código-fonte. Você fornece um repositório git (funciona com muitas linguagens de programação!) como entrada e obtém uma imagem de contêiner, sendo executada no Openshift como resultado.

É uma funcionilidade incrível! Não vou entrar em detalhes aqui, vou apenas dizer o que precisamos saber agora: para fazer isso, o Openshift cria um ou mais pods auxiliares, intermediários, para construir o código-fonte. Quando a compilação estiver concluída, os artefatos binários vão para a imagem do contêiner resultante, prontos para serem executados no Openshift, e esses conjuntos auxiliares são então descartados.

Se habilitarmos a injeção automática em um determinado namespace e usarmos a funcionalidade de s2i do Openshift, isso significa que todos os pods receberão o sidecar injetado. Mesmo aqueles pods compiladores (intermediários, auxiliares)! Pior, como eles não estão sob nosso controle (eles são criados pelo Openshift, não por nós), não podemos anotar para não obter o sidecar injetado. As compilações não se comportam bem com o sidecar injetado, então não queremos que eles sejam automaticamente injetados. O que fazer agora?

Bem, uma solução possível é seguir a abordagem conservadora explicada no último item acima: Desativar a injeção automática para todos e ativá-la apenas para os pods selecionados. Isso funciona, mas exige que você anote ativamente os pods que você deseja que a injeção automática aconteça.

Ou… Há uma nova solução para esse problema:

A nova solução

A partir da versão 1.1.0, a injeção automática do Istio tem uma maneira de adicionar exceções com base em rótulos, ou seja: não injetar o sidecar em pods que correspondam a esses rótulos, mesmo se a política for true e esse namespace for marcado para ter injeção automática. Você pode adicionar essas exceções no istio-sidecar-injector ConfigMap:

$ kubectl -n istio-system describe configmap istio-sidecar-injector
apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-sidecar-injector
data:
  config: |-
    policy: enabled
    neverInjectSelector:
      - matchExpressions:
        - {key: openshift.io/build.name, operator: Exists}
      - matchExpressions:
        - {key: openshift.io/deployer-pod-for.name, operator: Exists}
    template: |-
      initContainers:
...

Você pode ver acima um campo neverInjectSelector. É uma matriz de seletores de rótulos de Kubernetes. Eles são comparados com OR, parando no primeiro jogo. A instrução acima significa: Nunca injetar em pods que tenham o rótulo openshift.io/build.name ou openshift.io/deployer-pod-for.name – os valores dos rótulos não importam, estamos apenas verificando se as chaves existem. Com essa regra adicionada, nosso caso de uso de s2i do Openshift está coberto, o que significa que os pods auxiliares não terão sidecars injetados (porque os pods auxiliares de s2i contêm esses rótulos).

Para completar, você também pode usar um campo chamado alwaysInjectSelector, que sempre injetará o sidecar em pods que correspondam ao seletor de rótulo, apesar da política global.

A abordagem do seletor de rótulos oferece muita flexibilidade sobre como expressar essas exceções. Dê uma olhada em sua documentação para ver o que você pode fazer com eles!

Vale a pena observar que as anotações nos pods ainda têm a preferência. Se um pod é anotado com sidecar.istio.io/inject: "true/false", então ele será honrado. Então, a ordem de avaliação é:

Pod Annotations → NeverInjectSelector → AlwaysInjectSelector → Namespace Policy

Como este {Never,Always}InjectSelector é uma adição recente, eu ainda tenho que atualizar as documentações para mencioná-lo, mas para todas as outras coisas, para mais informações e exemplos confira a documentação oficial.

Por que meu pod [não] está sendo intejado?

Essa é uma pergunta muito comum. Você seguiu todas as instruções (como rotular o namespace com istio-injection=enabled) e seus pods não estão recebendo a injeção automática.

Ou bem pelo contrário, você anotou seu pod com sidecar.istio.io/inject: "false" e ele está sendo injetado. Por que?

Uma coisa que você pode fazer para descobrir o que está acontecendo é olhar nos logs do pod sidecar-injector:

$ pod=$(kubectl -n istio-system get pods -l istio=sidecar-injector -o jsonpath='{.items[0].metadata.name}')
$ kubectl -n istio-system logs -f $pod

Em seguida, você pode criar seus pods e monitorar aquele log por qualquer saída. Para uma saída de log mais detalhada – confie em mim, é realmente útil – devemos editar o deployment do sidecar-injector e anexar o argumento --log_output_level=default:debug ao executável de contêiner sidecar-injector:

$ kubectl -n istio-system edit deployment istio-sidecar-injector
...
      containers:
      - args:
        - --caCertFile=/etc/istio/certs/root-cert.pem
        - --tlsCertFile=/etc/istio/certs/cert-chain.pem
        - --tlsKeyFile=/etc/istio/certs/key.pem
        - --injectConfig=/etc/istio/inject/config
        - --meshConfig=/etc/istio/config/mesh
        - --healthCheckInterval=2s
        - --healthCheckFile=/health
        - --log_output_level=default:debug
        image: docker.io/istio/sidecar_injector:1.0.2
        imagePullPolicy: IfNotPresent
...

Salve e saia do seu editor. Agora o Kubernetes está fazendo deployment do pod sidecar-injector e o sinalizador depuração deve estar em vigor. Aguarde alguns segundos para o pod estar ativo, então você pode monitorar os logs novamente:

$ pod=$(kubectl -n istio-system get pods -l istio=sidecar-injector -o jsonpath='{.items[0].metadata.name}')
$ kubectl -n istio-system logs -f $pod
Dica

Se mesmo com a saída de depuração ativada você não viu nada relevante em seus logs, isso significa que o pod sidecar-injector não está sendo notificado sobre a criação do pod. Não está sendo invocado para fazer a injeção automática. Isso pode ser devido a uma configuração incorreta em relação ao rótulo do namespace. Verifique se o namespace está rotulado de acordo com o que está no MutatingWebhookConfiguration. Por padrão, o namespace deve ter o rótulo istio-injection=enabled. Verifique se isto foi alterado executando o kubectl -n istio-system edit MutatingWebhookConfiguration istio-sidecar-injector e verifique o campo namespaceSelector.

Quando terminar a sessão de depuração, você poderá editar o deployment novamente e remover esse argumento de depuração.

É isso. Espero que ajude. Sinta-se à vontade para perguntar ou comentar qualquer coisa, aqui ou no twitter! Nos vemos em breve!



Jonh Wendell: (English) Istio sidecar injection: enabling automatic injection, adding exceptions and debugging

24 de Setembro de 2018, 21:25, por Planeta GNOME Brasil - 0sem comentários ainda

Desculpe-nos, mas este texto esta apenas disponível em Inglês Americano.



Jonh Wendell: Istio, mTLS, depurando um erro 503

28 de Agosto de 2018, 23:33, por Planeta GNOME Brasil - 0sem comentários ainda

Olá pessoal. Neste post eu compartilharei com vocês um problema que tive enquanto testava o tutorial de Circuit Breaking na documentação do Istio. Vou seguir todos os passos que fiz durante a resolução deste problema, e espero que seja útil para alguém. Foi pelo menos para mim que aprendi um pouco mais sobre o Istio no processo.

As etapas da tarefa são bem simples:
1) Instalar um par de pods (um servindo httpbin + um com curl para se comunicar com o serviço httpbin)
2) Criar um objeto DestinationRule para que as chamadas para o serviço httpbin sejam limitadas (Circuit Breaking)
Bem simples, não? Então, vamos começar a diversão.

Vamos instalar os pods de httpbin e auxiliar:

$ kubectl create ns foo
$ kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n foo
$ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo

$ kubectl -n foo get pod,svc
NAME                           READY     STATUS    RESTARTS   AGE
pod/httpbin-6bbb775889-wcp45   2/2       Running   0          35s
pod/sleep-5b597748b4-77kj5     2/2       Running   0          35s

NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/httpbin   ClusterIP   10.105.25.98           8000/TCP   36s
service/sleep     ClusterIP   10.111.0.72            80/TCP     35s

No pod auxiliar, vamos invocar o serviço httpbin, usando o curl:

$ kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl http://httpbin:8000/get
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "0", 
    "Host": "httpbin:8000", 
    "User-Agent": "curl/7.35.0", 
    "X-B3-Sampled": "1", 
    "X-B3-Spanid": "b5d006d3d9bf1f4d", 
    "X-B3-Traceid": "b5d006d3d9bf1f4d", 
    "X-Request-Id": "970b84b2-999b-990c-91b4-b6c8d2534e77"
  }, 
  "origin": "127.0.0.1", 
  "url": "http://httpbin:8000/get"
}

Por enquanto, tudo bem. O próximo passo na tarefa de Circuit Breaking é adicionar uma DestinationRule:

$ cat <<EOF | kubectl -n foo apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutiveErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100
EOF

Agora, vamos tentar novamente o serviço httpbin:

$ kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl http://httpbin:8000/get
upstream connect error or disconnect/reset before headers

Ops, alguma coisa deu errado. Vamos tornar o curl mais verboso:

$ kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl -v http://httpbin:8000/get
* Hostname was NOT found in DNS cache
*   Trying 10.105.235.142...
* Connected to httpbin (10.105.235.142) port 8000 (#0)
> GET /get HTTP/1.1
> User-Agent: curl/7.35.0
> Host: httpbin:8000
> Accept: */*
> 
< HTTP/1.1 503 Service Unavailable
< content-length: 57
< content-type: text/plain
< date: Tue, 28 Aug 2018 12:26:54 GMT
* Server envoy is not blacklisted
< server: envoy
< 
* Connection #0 to host httpbin left intact
upstream connect error or disconnect/reset before headers

Hmmm, erro 503… Por que? De acordo com a tarefa Circuit Breaking, deveria funcionar bem. Adicionamos apenas uma regra que define o número máximo de conexões TCP como 1 e, de fato, com o comando curl acima, geramos apenas uma conexão. Então, o que há de errado?

A primeira coisa que me veio à mente foi emitir o comando para verificar se Circuit Breaking estava em vigor:

$ kubectl -n foo exec -it -c istio-proxy sleep-5b597748b4-77kj5 -- curl localhost:15000/stats | grep httpbin | grep pending
cluster.outbound|8000||httpbin.foo.svc.cluster.local.upstream_rq_pending_active: 0
cluster.outbound|8000||httpbin.foo.svc.cluster.local.upstream_rq_pending_failure_eject: 0
cluster.outbound|8000||httpbin.foo.svc.cluster.local.upstream_rq_pending_overflow: 0
cluster.outbound|8000||httpbin.foo.svc.cluster.local.upstream_rq_pending_total: 5

Então, o valor 0 para a variável upstream_rq_pending_overflow confirma que nenhuma chamada foi capturada pelo Circuit Breaking.

Explicação do comando acima:
O sidecar do Istio (contêiner Envoy denominado istio-proxy) expõe (localmente) a porta 15000, que é acessível via HTTP e possui alguns utilitários, como a impressão de algumas estatísticas sobre o serviço.
Então, no comando acima nós executamos o curl (curl localhost:15000/stats) dentro do contêiner sidecar (-c istio-proxy) do pod auxiliar (sleep-5b597748b4-77kj5), filtrando a saída pelo serviço que queremos investigar (| grep httpbin) e depois filtrando para o estado pendente do circuit breaker (| grep pending).

Para confirmar que o culpado é o DestinationRule, vamos excluí-lo e tentar novamente:

$ kubectl -n foo delete DestinationRule httpbin
destinationrule.networking.istio.io "httpbin" deleted
$ kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl -v http://httpbin:8000/get
...
< HTTP/1.1 200 OK
...

Adicionando-o novamente:

...
< HTTP/1.1 503 Service Unavailable
...

Então, parece que o DestinationRule é o vilão aqui. Mas por quê? Precisamos investigar um pouco mais. Ei! E se verificarmos os logs do Envoy (istio-proxy sidecar)? Vamos fazer isso:

$ kubectl -n foo logs -c istio-proxy sleep-5b597748b4-77kj5 -f
# Em outro terminal, emita o comando curl (kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl -v http://httpbin:8000/get)
# Então, vemos no log:
[2018-08-28T13:06:56.454Z] "GET /get HTTP/1.1" 503 UC 0 57 0 - "-" "curl/7.35.0" "19095d07-320a-9be0-8ba5-e0d08cf58f52" "httpbin:8000" "172.17.0.14:8000"

Isso não ajuda. O log nos diz que o Envoy está recebendo o erro 503 do servidor. Então, vamos verificar os logs para o lado do servidor (httpbin):

$ kubectl -n foo logs -c istio-proxy httpbin-94fdb8c79-h9zrq -f
# Em outro terminal, emita o comando curl (kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl -v http://httpbin:8000/get)
# Log está vazio...

O que? Nós não vemos nada na saída do log. É como se a requisição não estivesse chegando ao servidor. Então, o que fazer agora?… Ei! E se pudéssemos aumentar a verbosidade do log? Talvez o pedido esteja chegando, mas não está sendo produzido? Vamos ver.

Lembre-se de que eu disse acima sobre a porta 15000 do Envoy sendo exposta localmente ao pod de serviço? Nós usamos isso para pegar estatísticas. Vamos dar uma olhada para descobrir o que mais oferece:

$ kubectl -n foo exec -it -c istio-proxy httpbin-94fdb8c79-h9zrq -- curl http://localhost:15000/help
admin commands are:
  /: Admin home page
  /certs: print certs on machine
...
  /logging: query/change logging levels
...

Ei! Parece que encontramos o que estávamos procurando: /logging. Vamos usá-lo:

$ kubectl -n foo exec -it -c istio-proxy httpbin-94fdb8c79-h9zrq -- curl http://localhost:15000/logging?level=trace
active loggers:
  admin: trace
...

O comando acima definiu todos os registradores de log de Envoy para o nível trace, o melhor. Para obter mais informações sobre essa interface administrativa, verifique os documentos do Envoy. Agora, vamos tentar recuperar o log do servidor Envoy e, esperançosamente, com o nível trace, obteremos algo (na verdade, recebemos muitos logs!):

$ kubectl -n foo logs -c istio-proxy httpbin-94fdb8c79-h9zrq -f
# Em outro terminal, emita o comando curl (kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl -v http://httpbin:8000/get)
# Agora, vemos nos logs (Eu filtrei parte do conteúdo não relevante):
[debug][filter] external/envoy/source/extensions/filters/listener/original_dst/original_dst.cc:18] original_dst: New connection accepted
[debug][main] external/envoy/source/server/connection_handler_impl.cc:217] [C31] new connection
[trace][connection] external/envoy/source/common/network/connection_impl.cc:389] [C31] socket event: 2
[trace][connection] external/envoy/source/common/network/connection_impl.cc:457] [C31] write ready
[debug][connection] external/envoy/source/common/ssl/ssl_socket.cc:111] [C31] handshake error: 2
[trace][connection] external/envoy/source/common/network/connection_impl.cc:389] [C31] socket event: 3
[trace][connection] external/envoy/source/common/network/connection_impl.cc:457] [C31] write ready
[debug][connection] external/envoy/source/common/ssl/ssl_socket.cc:111] [C31] handshake error: 1
[debug][connection] external/envoy/source/common/ssl/ssl_socket.cc:139] [C31] SSL error: 268435612:SSL routines:OPENSSL_internal:HTTP_REQUEST
[debug][connection] external/envoy/source/common/network/connection_impl.cc:133] [C31] closing socket: 0

Uau, isso parece interessante! Podemos ver que a requisição está realmente chegando ao servidor, mas está falhando devido a um erro de handshake e o Envoy está fechando a conexão. A questão agora é: Por que um erro de handshake? Por que o SSL está envolvido?

Quando falamos de SSL no contexto do Istio, lembramos do TLS Mútuo. Então eu fui à documentação do Istio, tentando encontrar algo relevante para o meu problema. A leitura da tarefa de tutorial de segurança abriu meus olhos!

Eu descobri que eu tinha instalado o Istio com o TLS Mútuo ativado!

Vamos fazer algumas verificações:

$ kubectl get MeshPolicy default -o yaml
apiVersion: authentication.istio.io/v1alpha1
kind: MeshPolicy
metadata: ...
spec:
  peers:
  - mtls: {}

$ kubectl -n istio-system get DestinationRule default -o yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata: ...
spec:
  host: '*.local'
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

Essas saídas acima mostram que o mTLS está instalado no cluster. Esses objetos só existem quando o mTLS está ativado.

OK, olhando novamente os meus scripts de instalação, eu percebi que eu realmente baguncei tudo e instalei o Istio com o mTLS ativado. No entanto, a questão ainda está lá: por que o serviço httpbin está falhando? Sabendo que o mTLS está ativo na malha e lendo a documentação, não é difícil deduzir que o servidor está esperando uma conexão TLS e o cliente está emitindo um texto simples. Mudamos a pergunta novamente: Por que o cliente (sleep pod) está se conectando ao servidor (pod httpbin) usando texto simples?

Novamente, olhando para a documentação, encontramos a resposta. A maneira como o mTLS trabalha no Istio é simples: existe um objeto DestinationRule (chamado “default”, como podemos ver no comando acima) que instrui todo o tráfego na malha a passar pelo TLS. No entanto, quando criamos nossa própria DestinationRule, para o propósito da tarefa Circuit Breaking, sobrescrevemos essa configuração padrão com a nossa, que não tem nenhum TLS! Isso é indicado na documentação do TLS para o Istio (tradução livre do conteúdo):

Não se esqueça de que as regras de destino também são usadas por motivos além de autenticação, como a instalação do deployment de canary, mas a mesma ordem de precedência se aplica. Portanto, se um serviço exigir uma regra de destino específica por qualquer motivo – por exemplo, para um balanceador de carga de configuração – a regra deverá conter um bloco TLS semelhante com o modo ISTIO_MUTUAL, pois, do contrário, ele substituirá as configurações de TLS de malha ou namespace e desativará o TLS.

Então, está claro agora o que devemos fazer: Modificar a DestinationRule para a tarefa Circuit Breaking de forma a incluir o bloco TLS (linhas 20-21 abaixo):

cat <<EOF | kubectl -n foo apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutiveErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100
    tls:
      mode: ISTIO_MUTUAL
EOF
destinationrule.networking.istio.io/httpbin configured

Agora, vamos tentar nosso serviço httpbin:

kubectl -n foo exec -it -c sleep sleep-5b597748b4-77kj5 -- curl -v http://httpbin:8000/get
...
< HTTP/1.1 200 OK
...

\o/

Agora, eu posso continuar com meu tutorial de Circuit Breaking!

Algumas lições aprendidas:
– Confirme se você está usando mTLS ou não; Habilitá-lo abre a porta para erros obscuros 🙂
– As DestinationRules têm ordem de precedência: as mais específicas sobrescrevem as globais
– Às vezes, podemos fazer bom uso da interface administrativa do Sidecar (porta local 15000)
– Sempre leia a documentação 🙂

Nos vemos em breve!



Jonh Wendell: (English) Istio, mTLS, debugging a 503 error

28 de Agosto de 2018, 23:33, por Planeta GNOME Brasil - 0sem comentários ainda

Desculpe-nos, mas este texto esta apenas disponível em Inglês Americano.



Tags deste artigo: gnome planet planeta