Deep Dive Kubernetes Architeture (API Server - Part 2)
AuthX
O kube-apiserver trata as autorizações e autenticações.
Todas as autenticações em nível de sistema (AuthN) e autorizações (AuthZ) são tratadas por ele. AuthX geralmente se refere a AuthN e AuthZ
Também podemos dizer que o kube-apiserver é o centro de segurança do Kubernetes.
É altamente recomendável habilitar a segurança da camada de transporte (TLS) entre todos os componentes do Kubernetes.
Todas as solicitações que estão sendo enviadas ao kube-apiserver precisam passar pelos estágios de autenticação, autorização e controle de admissão e, em seguida, chegar aos estágios finais de validação de recursos e armazenamento persistente.
Autenticação
Kube-apiserver precisa autenticar cada solicitação recebida para validar a identidade do usuário
- O método de autenticação mais simples é usar nome de usuário, senha e tokens (não recomendado)
- Tokens Bootstrap e ServiceAccount são gerenciados diretamenta pelo Kubernetes. ServiceAccounts podem ser montados em Pod e gerenciado via RoleBinding e ClusterRoleBinding para criar a autorização a algum recurso
- O método x509 é outro método de autenticação amplamente utilizado no Kubernetes. Qualquer solicitação que apresente um certificado válido assinado pela CA (autoridade certificadora) do nosso cluster é considerada válida. O=system:nodes, CN=system:node:master este certificado será interpretado para o usuário system:node:master do grupo system:nodes
- Se tivermos serviços de autenticação auto-hospedados, como LDAP ou Kerberos, os métodos de autenticação acima não atendem aos nossos requisitos. Usar o webhook de autenticação é uma excelente opção para tais cenários. O webhook nos permite gerar e usar tokens definidos pelo usuário.
Autorização
A autorização ocorre após a autenticação ter sido aprovada. A autorização desempenha um papel importante na rejeição de quaisquer solicitações com privilégios de usuário incorretos.
O controle de acesso baseado em atributos (ABAC) é o método de autorização mais simples no Kubernetes. O arquivo estático no servidor contém um grupo de políticas de usuário com atributos combinados. Não é recomendado para o ambiente de produção
O controle de acesso baseado em função (RBAC) é o método de autorização integrado mais comumente usado no Kubernetes.
Semelhante à autenticação, o Kubernetes fornece um webhook para autorização, onde podemos integrar com um sistema auto-hospedado.
A introdução do webhook não significa que estamos descartando as regras RBAC existentes.Todos os plug-ins de autorização são agrupados como uma cadeia sindical e serão invocados um por um. Se nenhum deles puder determinar o privilégio do usuário, a solicitação será rejeitada e um código de status 403 será retornado.
Webhooks
Webhook Token Authentication
O webhook de autenticação é um retorno de chamada HTTP que será chamado na fase de autenticação.
Durante o estágio de autenticação, se os plug-ins anteriores na cadeia de autenticação sindical não conseguirem identificar o usuário, o plug-in webhook será chamado para determinar a legitimidade do usuário.
Este plugin webhook extrai o token de portador HTTP da solicitação original. Em seguida, ele invoca uma solicitação HTTP POST para o serviço de autenticação remota especificada na config acima.
Aqui, o serviço remoto de autenticação de token webhook é totalmente independente do Kubernetes. Ele pode ser executado em qualquer lugar, desde que kube-apiserver possa acessá-lo.
Isso deve nascer junto com o nó, então lembre de adicionar como um daemon set para os nós, ou adicionar aos arquivos que serão deployados pelo kubelet. Sem isso vc não autentica.
Webhook Authorization
Cada plugin implementa um método de autorização específico, como Node, RBAC, ABAC, etc.
Quaisquer solicitações autenticadas serão apresentadas a cada plugin de autorização, uma por uma, até que um deles consiga determinar com sucesso os privilégios do usuário no recurso solicitado.
Admission Control
O kube-apiserver atende todas as solicitações CRUD. No entanto, às vezes precisamos de mais granularidade nas operações de recursos, e não apenas nas regras do RBAC.
Precisamos ter uma maneira de interceptar as solicitações e tomar algumas decisões para permitir ou negar as solicitações, aplicar nossas configurações padrão, injetar contêineres secundários, etc.
Esses admission controllers funcionam como gatekeepers que impõem uma série de regras configuráveis para verificar a validade das solicitações e permitir customizações sobre o que é permitido rodar em nosso cluster.
Todos os plug-ins do admission controller precisam implementar o MutationInterface ou ValidationInterface ou ambos. A fase de mutação é executada antes da fase de validação.
Todos esses plugins habilitados compõem uma cadeia de admissão, que será chamada uma a uma com a ordem definida. Se qualquer um dos plug-ins rejeitar a solicitação, toda a solicitação HTTP será marcada como rejeitada com um erro retornado ao usuário final.
Webhooks
Mutating Admission Webhooks
São responsáveis por modicar um recurso quando é criado, atualizado ou até deletado. Pode ser implementado tanto em controllers como de forma independente e externa ao cluster, onde a API server deve realizar requisições ao webhook. Ele sempre vem primeiro que o validating
Validating Admission Webhooks
São responsáveis por validar se um recurso pode ser criado, atualizado ou até deletado. Pode ser implementado tanto em controllers como de forma independente e externa ao cluster, onde a API server deve realizar requisições ao webhook.
Aggregated Apiserver
O Kubernetes introduziu dois mecanismos de extensão principais para estender as APIs do Kubernetes: CustomResourceDefinition (CRD) e o Aggregated Apiserver
O Aggregated Apiserver (também conhecido como custom apiserver) é um servidor HTTP independente que fornece APIs REST. No entanto, funciona de forma totalmente diferente do CRD.
No Aggregated Apiserver, podemos desenvolver APIs Kubernetes com todos os recursos. Em termos simples, o Aggregated Apiserver funciona como outro kube-apiserver. Ele se espalha para o kube-apiserver para fornecer APIs adicionais que não são oferecidas pelas APIs principais do Kubernetes.
O Aggregated Apiserver fica atrás do kube-apiserver. Esse tipo de arranjo também é chamado de API Aggregation (AA).
Normalmente, executamos nossos aggregated apiservers em pods executados em nosso cluster e expomos em um service para se comunicar com o api-server
Poderíamos ter vários aggregate apiservers em execução dentro de um cluster Kubernetes. Esses apiservers podem ser desenvolvidos para diferentes grupos de APIs e mantidos por diferentes equipes.
Aggregated Apiserver (Part 2)
Quando usar o aggregate apiserver
A primeira escolha sem deve ser o CRD para estender o api-server, pela simplicidade do seu uso.
Limitações do CRD
Os CRDs usam o mesmo meio de armazenamento que o kube-apiserver. O kube-apiserver armazena todos os recursos personalizados diretamente no etcd.
CRDs usam JSON apenas para serializações de API. Protobuf não é suportado por CRDs. Portanto, quando o protobuf é um requisito para nossas APIs, temos que usar o aggregate apiserver.
Os CRDs não suportam sub-recursos/endpoints de longa duração, como websocket e proxy, para nossos próprios recursos – eles estão fora do escopo dos CRDs. No entanto, os CRDs podem lidar bem com os sub-recursos /status e /scale.
Os CRDs fazem validações de forma confinada. A maioria das validações é suportada no CRD usando OpenAPI v3.0. Todas as validações são feitas de forma genérica. Para outras validações, precisamos construir um webhook de validação para adicionar nossas regras personalizadas, como validar os relacionamentos do campo A e do campo B.
Os CRDs não podem ser integrados a outros sistemas externos. Não há como intervir em todas as solicitações da API. Todas as APIs que estão servindo são hospedadas exclusivamente pelo kube-apiserver. Não podemos interagir com nosso próprio sistema ou ajustar as solicitações ou respostas.
Os CRDs suportam apenas a semântica CRUD padrão para todos os endpoints da API.
Com aggregated apiserver, podemos:
Use qualquer meio de armazenamento que desejarmos. Para proteger melhor os dados, também podemos criptografar informações confidenciais.
Fornece todos os tipos de suporte de esquema, incluindo JSON e Protobuf. Assim, nossos clientes de recursos personalizados podem usar buffers de protocolo para comunicação.
Forneça quaisquer sub-recursos personalizados, como /exec, /logs e /proxy. Também podemos usar protocolos personalizados como WebSocket e HTTP/2.
Implemente operações personalizadas para validação, admissão e conversão, bem como mutação e defaulting, em qualquer linguagem com a qual estejamos familiarizados. Para CRDs, podemos implementá-los por meio de webhooks, mas precisamos adicionar latência. Também podemos precisar nos esforçar para manter vários webhooks ao mesmo tempo.
Implemente semântica personalizada, como acionar outros sistemas para criar recursos correspondentes.
Desvantagens
Usar o aggregated apiserver também pode introduzir latência de resposta. Cada solicitação nas APIs de extensão é encaminhada para o aggregated apiserver pelo kube-apiserver.
A rede pode ter alta latência e o aggregated apiserver executa etapas extras (como autenticação, autorização, processamento de armazenamento, etc.) para lidar com cada solicitação. Em seguida, ele retorna a resposta ao kube-apiserver.
APIService Object
Podemos registrar dinamicamente nossos aggregated apiservers no kube-apiserver criando um objeto APIService.
Para registrar múltiplas APIs com grupos e versões, precisamos apenas criar vários objetos APIService correspondentes. Assim é fácil deletar e adicionar novas versões
O kube-apiserver agrega essas APIs registradas pelo agregated e as expõe uniformemente para acesso externo, como kubectl e outros clientes de API.
Isso traz uma experiência de usuário consistente, porque os usuários não precisam se preocupar com onde as APIs são realmente servidas. Tudo o que os usuários precisam saber é o endereço do kube-apiserver. Lembre, o api-server sempre está na frente dos aggregated.
No kube-apiserver, existe um componente chamado kube-aggregator para lidar com esse trabalho de proxy.
kube-aggregator
Faz o serviço de proxy entre o api-server e outros aggregated api-servers
O kube-apiserver descobre automaticamente os grupos de API visitando /apis e /apis/<group-name> de todos os aggregated apiserver.
Todas as APIs são expostas no kube-apiserver.
O kube-apiserver recebe todas as solicitações e as passa para uma cadeia de handlers que consiste em autenticação, registro de auditoria, impersonation, in-flight throttle, autorização, etc.
O kube-apiserver conhece APIs auto-fornecidas (APIs Kubernetes e APIs de recursos personalizados definidas por CRDs) e APIs agregadas claramente. Ele passa todas as APIs auto-fornecidas para handlers de recursos integrados para pós-processamento, como decodificação, conversão, defaulting, conversão de versão, etc.
À medida que o servidor API Kubernetes reconhece as APIs agregadas, ele as intercepta e as encaminha para os aggregated apiserver. Isso é feito pelo kube-aggregator. O kube-aggregator não precisa conhecer todos os recursos servidos no grupo de APIs /api/<group-name>/<version>. Ele apenas faz lazy proxying. Todas as solicitações no caminho HTTP correspondente serão proxy.
Lembre que o aggregator conhece o caminho para as api-aggregated pela configuração no objeto APIService
Aggregated Apiserver (Part 3)
Ele tem sua própria cadeia de handlers, incluindo autenticação, auditoria, impersonation e autorização. Embora a autenticação e autorização, mas reaproveita praticamente tudo do api-server
Ele possui seus próprios handlers de recursos para cada grupo de API personalizado. Cada pipeline de handlers consiste em decodificação de objetos, conversão, defaulting, admissão, mapeamento REST, armazenamento de objetos e codificação para o resultado da resposta. Isso é exatamente o mesmo que o kube-apiserver.
Para autorização, os aggregated apiserver também utilizam regras RBAC.
Durante a fase de admissão, também podemos chamar webhooks de admissão.
O kube-apiserver já lida com a parte de autenticação, e os aggregated apiserver podem reutilizar os resultados dessa autenticação (ou seja, o nome de usuário e o grupo).