Kubernetes Basics

Conceitos Básicos do Kubernetes

Apoie o HackTricks e obtenha benefícios!

O autor original desta página é Jorge (leia seu post original aqui)

Arquitetura e Conceitos Básicos

O que o Kubernetes faz?

  • Permite a execução de contêineres em um mecanismo de contêineres.

  • O agendamento permite que os contêineres sejam executados de forma eficiente.

  • Mantém os contêineres em execução.

  • Permite a comunicação entre contêineres.

  • Permite técnicas de implantação.

  • Manipula volumes de informações.

Arquitetura

  • Node: sistema operacional com pod ou pods.

    • Pod: invólucro em torno de um contêiner ou vários contêineres. Um pod deve conter apenas um aplicativo (portanto, geralmente, um pod executa apenas 1 contêiner). O pod é a maneira como o Kubernetes abstrai a tecnologia de contêiner em execução.

      • Service: Cada pod tem 1 endereço IP interno da faixa interna do nó. No entanto, ele também pode ser exposto por meio de um serviço. O serviço também tem um endereço IP e seu objetivo é manter a comunicação entre os pods, para que, se um morrer, o novo substituto (com um IP interno diferente) seja acessível exposto no mesmo IP do serviço. Ele pode ser configurado como interno ou externo. O serviço também atua como um balanceador de carga quando 2 pods estão conectados ao mesmo serviço. Quando um serviço é criado, você pode encontrar os endpoints de cada serviço executando kubectl get endpoints

  • Kubelet: agente primário do nó. O componente que estabelece a comunicação entre o nó e o kubectl e só pode executar pods (por meio do servidor API). O kubelet não gerencia contêineres que não foram criados pelo Kubernetes.

  • Kube-proxy: é o serviço responsável pelas comunicações (serviços) entre o servidor API e o nó. A base é um IPtables para nós. Usuários mais experientes podem instalar outros kube-proxies de outros fornecedores.

  • Container Sidecar: Os containers Sidecar são os containers que devem ser executados juntamente com o contêiner principal no pod. Este padrão de sidecar estende e aprimora a funcionalidade dos contêineres atuais sem alterá-los. Atualmente, sabemos que usamos a tecnologia de contêiner para envolver todas as dependências para que o aplicativo seja executado em qualquer lugar. Um contêiner faz apenas uma coisa e faz essa coisa muito bem.

  • Processo Master:

    • Api Server: É a maneira como os usuários e os pods usam para se comunicar com o processo master. Somente solicitações autenticadas devem ser permitidas.

    • Scheduler: O agendamento refere-se a garantir que os pods sejam correspondidos aos nós para que o Kubelet possa executá-los. Ele tem inteligência suficiente para decidir qual nó tem mais recursos disponíveis e atribuir o novo pod a ele. Observe que o agendador não inicia novos pods, ele apenas se comunica com o processo Kubelet em execução dentro do nó, que iniciará o novo pod.

    • Kube Controller Manager: Ele verifica recursos como conjuntos de réplicas ou implantações para verificar se, por exemplo, o número correto de pods ou nós está em execução. Caso um pod esteja faltando, ele se comunicará com o agendador para iniciar um novo. Ele controla a replicação, tokens e serviços de conta para a API.

    • etcd: Armazenamento de dados, persistente, consistente e distribuído. É o banco de dados do Kubernetes e o armazenamento de chave-valor onde ele mantém o estado completo dos clusters (cada alteração é registrada aqui). Componentes como o Agendador ou o Gerenciador de controladores dependem desses dados para saber quais alterações ocorreram (recursos disponíveis dos nós, número de pods em execução...)

  • Gerenciador de controladores em nuvem: É o controlador específico para controles de fluxo e aplicativos, ou seja, se você tiver clusters na AWS ou no OpenStack.

Observe que, como pode haver vários nós (executando vários pods), também pode haver vários processos mestre, cujo acesso ao servidor API é balanceado e seu etcd sincronizado.

Volumes:

Quando um pod cria dados que não devem ser perdidos quando o pod desaparecer, eles devem ser armazenados em um volume físico. O Kubernetes permite anexar um volume a um pod para persistir os dados. O volume pode estar na máquina local ou em um armazenamento remoto. Se você estiver executando pods em diferentes nós físicos, deverá usar um armazenamento remoto para que todos os pods possam acessá-lo.

Outras configurações:

  • ConfigMap: Você pode configurar URLs para acessar serviços. O pod obterá dados daqui para saber como se comunicar com o restante dos serviços (pods). Observe que este não é o local recomendado para salvar credenciais!

  • Secret: Este é o local para armazenar dados secretos como senhas, chaves de API... codificadas em B64. O pod poderá acessar esses dados para usar as credenciais necessárias.

  • Implantações: Aqui é onde os componentes a serem executados pelo Kubernetes são indicados. Um usuário geralmente não trabalhará diretamente com pods, os pods são abstraídos em ReplicaSets (número de pods idênticos replicados), que são executados por meio de implantações. Observe que as implantações são para aplicativos sem estado. A configuração mínima para uma implantação é o nome e a imagem a serem executados.

  • StatefulSet: Este componente é especificamente destinado a aplicativos como bancos de dados que precisam acessar o mesmo armazenamento.

  • Ingress: Esta é a configuração que é usada para expor o aplicativo publicamente com uma URL. Observe que isso também pode ser feito usando serviços externos, mas esta é a maneira correta de expor o aplicativo.

    • Se você implementar um Ingress, precisará criar Controladores de Ingress. O Controlador de Ingress é um pod que será o ponto de extremidade que receberá as solicitações e verificará e balanceará as cargas para os serviços. o controlador de ingress enviará a solicitação com base nas regras de ingress configuradas. Observe que as regras de ingress podem apontar para caminhos diferentes ou até subdomínios para diferentes serviços internos do Kubernetes.

      • Uma prática de segurança melhor seria usar um balanceador de carga em nuvem ou um servidor proxy como ponto de entrada para não ter nenhuma parte do cluster Kubernetes exposta.

      • Quando uma solicitação que não corresponde a nenhuma regra de ingress é recebida, o controlador de ingress a direcionará para o "Backend padrão". Você pode descrever o controlador de ingress para obter o endereço desse parâmetro.

      • minikube addons enable ingress

Infraestrutura PKI - Autoridade de Certificação CA:

  • O CA é a raiz confiável para todos os certificados dentro do cluster.

  • Permite que os componentes se validem entre si.

  • Todos os certificados do cluster são assinados pelo CA.

  • ETCd tem seu próprio certificado.

  • tipos:

    • certificado do servidor API.

    • certificado do kubelet.

    • certificado do agendador.

Ações Básicas

Minikube

Minikube pode ser usado para realizar alguns testes rápidos no kubernetes sem precisar implantar um ambiente completo do kubernetes. Ele executará os processos de mestre e nó em uma única máquina. Minikube usará o virtualbox para executar o nó. Veja aqui como instalá-lo.

$ minikube start
😄  minikube v1.19.0 on Ubuntu 20.04
✨  Automatically selected the virtualbox driver. Other choices: none, ssh
💿  Downloading VM boot image ...
    > minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
    > minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB  100.00% 1.78 MiB p/s 2m17.
👍  Starting control plane node minikube in cluster minikube
💾  Downloading Kubernetes v1.20.2 preload ...
    > preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB  100.00% 2.59 MiB
🔥  Creating virtualbox VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
🐳  Preparing Kubernetes v1.20.2 on Docker 20.10.4 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by defaul

$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

---- ONCE YOU HAVE A K8 SERVICE RUNNING WITH AN EXTERNAL SERVICE -----
$ minikube service mongo-express-service
(Este comando abrirá seu navegador para acessar a porta exposta do serviço)

$ minikube delete
🔥  Deleting "minikube" in virtualbox ...
💀  Removed all traces of the "minikube" cluster

Conceitos Básicos do Kubectl

Kubectl é a ferramenta de linha de comando para clusters kubernetes. Ele se comunica com o servidor Api do processo mestre para executar ações no kubernetes ou para solicitar dados.

kubectl version #Obter a versão do cliente e do servidor
kubectl get pod
kubectl get services
kubectl get deployment
kubectl get replicaset
kubectl get secret
kubectl get all
kubectl get ingress
kubectl get endpoints

#kubectl create deployment <deployment-name> --image=<docker image>
kubectl create deployment nginx-deployment --image=nginx
#Acesse a configuração do deployment e modifique-a
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
#Obtenha os logs do pod para depuração (a saída do contêiner docker em execução)
#kubectl logs <replicaset-id/pod-id>
kubectl logs nginx-deployment-84cd76b964
#kubectl describe pod <pod-id>
kubectl describe pod mongo-depl-5fd6b7d4b4-kkt9q
#kubectl exec -it <pod-id> -- bash
kubectl exec -it mongo-depl-5fd6b7d4b4-kkt9q -- bash
#kubectl describe service <service-name>
kubectl describe service mongodb-service
#kubectl delete deployment <deployment-name>
kubectl delete deployment mongo-depl
#Implantar a partir do arquivo de configuração
kubectl apply -f deployment.yml

Painel do Minikube

O painel permite que você veja mais facilmente o que o minikube está executando, você pode encontrar a URL para acessá-lo em:

minikube dashboard --url


🔌  Enabling dashboard ...
    ▪ Using image kubernetesui/dashboard:v2.3.1
    ▪ Using image kubernetesui/metrics-scraper:v1.0.7
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

Exemplos de arquivos de configuração YAML

Cada arquivo de configuração tem 3 partes: metadata, specification (o que precisa ser lançado), status (estado desejado). Dentro da especificação do arquivo de configuração de implantação, você pode encontrar o modelo definido com uma nova estrutura de configuração definindo a imagem a ser executada:

Exemplo de implantação + serviço declarado no mesmo arquivo de configuração (de aqui)

Como um serviço geralmente está relacionado a uma implantação, é possível declarar ambos no mesmo arquivo de configuração (o serviço declarado nesta configuração só é acessível internamente):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb-deployment
  labels:
    app: mongodb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
      - name: mongodb
        image: mongo
        ports:
        - containerPort: 27017
        env:
        - name: MONGO_INITDB_ROOT_USERNAME
          valueFrom:
            secretKeyRef:
              name: mongodb-secret
              key: mongo-root-username
        - name: MONGO_INITDB_ROOT_PASSWORD
          valueFrom: 
            secretKeyRef:
              name: mongodb-secret
              key: mongo-root-password
---
apiVersion: v1
kind: Service
metadata:
  name: mongodb-service
spec:
  selector:
    app: mongodb
  ports:
    - protocol: TCP
      port: 27017
      targetPort: 27017

Exemplo de configuração de serviço externo

Este serviço será acessível externamente (verifique os atributos nodePort e type: LoadBlancer):

---
apiVersion: v1
kind: Service
metadata:
  name: mongo-express-service
spec:
  selector:
    app: mongo-express
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8081
### Helm

Helm é o **gerenciador de pacotes** para Kubernetes. Ele permite empacotar arquivos YAML e distribuí-los em repositórios públicos e privados. Esses pacotes são chamados de **Helm Charts**.

helm search


Helm também é um mecanismo de modelo que permite gerar arquivos de configuração com variáveis:

## Segredos do Kubernetes

Um **Segredo** é um objeto que **contém dados sensíveis** como uma senha, um token ou uma chave. Essas informações podem ser colocadas em uma especificação de Pod ou em uma imagem. Os usuários podem criar segredos e o sistema também cria segredos. O nome de um objeto Secret deve ser um **nome de subdomínio DNS válido**. Leia aqui [a documentação oficial](https://kubernetes.io/docs/concepts/configuration/secret/).

Segredos podem ser coisas como:

* Chaves API, SSH.
* Tokens OAuth.
* Credenciais, senhas (texto simples ou b64 + criptografia).
* Informações ou comentários.
* Código de conexão de banco de dados, strings....

Existem diferentes tipos de segredos no Kubernetes

| Tipo Incorporado                     | Uso                                       |
| ----------------------------------- | ----------------------------------------- |
| **Opaco**                           | **dados definidos pelo usuário arbitrários (padrão)** |
| kubernetes.io/service-account-token | token de conta de serviço                 |
| kubernetes.io/dockercfg             | arquivo \~/.dockercfg serializado         |
| kubernetes.io/dockerconfigjson      | arquivo \~/.docker/config.json serializado |
| kubernetes.io/basic-auth            | credenciais para autenticação básica      |
| kubernetes.io/ssh-auth              | credenciais para autenticação SSH         |
| kubernetes.io/tls                   | dados para um cliente ou servidor TLS     |
| bootstrap.kubernetes.io/token       | dados de token de inicialização           |

<div data-gb-custom-block data-tag="hint" data-style='info'>

**O tipo Opaque é o padrão, o par chave-valor típico definido pelos usuários.**

</div>

**Como os segredos funcionam:**

![](https://sickrov.github.io/media/Screenshot-164.jpg)

O arquivo de configuração a seguir define um **segredo** chamado `mysecret` com 2 pares de chave-valor `username: YWRtaW4=` e `password: MWYyZDFlMmU2N2Rm`. Ele também define um **pod** chamado `secretpod` que terá o `username` e `password` definidos em `mysecret` expostos nas **variáveis de ambiente** `SECRET_USERNAME` e `SECRET_PASSWORD`. Ele também irá **montar** o segredo `username` dentro de `mysecret` no caminho `/etc/foo/my-group/my-username` com permissões `0640`.

<div data-gb-custom-block data-tag="code" data-title='secretpod.yaml'>

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
---
apiVersion: v1
kind: Pod
metadata:
  name: secretpod
spec:
  containers:
  - name: secretpod
    image: nginx
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  restartPolicy: Never
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
        mode: 0640
kubectl apply -f <secretpod.yaml>
kubectl get pods #Aguarde até que o pod secretpod esteja em execução
kubectl exec -it  secretpod -- bash
env | grep SECRET && cat /etc/foo/my-group/my-username && echo

Segredos no etcd

etcd é um armazenamento de chave-valor consistente e altamente disponível usado como armazenamento de suporte do Kubernetes para todos os dados do cluster. Vamos acessar os segredos armazenados no etcd:

cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd

Você verá que os certificados, chaves e URLs estão localizados no FS. Depois de obtê-los, você poderá se conectar ao etcd.

#ETCDCTL_API=3 etcdctl --cert <caminho para client.crt> --key <caminho para client.ket> --cacert <caminho para CA.cert> endpoint=[<ip:porta>] health

ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health

Depois de estabelecer a comunicação, você poderá obter os segredos:

#ETCDCTL_API=3 etcdctl --cert <caminho para client.crt> --key <caminho para client.ket> --cacert <caminho para CA.cert> endpoint=[<ip:porta>] get <caminho/para/segredo>

ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02

Adicionando criptografia ao ETCD

Por padrão, todos os segredos são armazenados em texto plano dentro do etcd, a menos que você aplique uma camada de criptografia. O exemplo a seguir é baseado em https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/

encryption.yaml

```yaml apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMX

Última actualización