Kubernetes Basics
Reading time: 19 minutes
Kubernetes Basics
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
O autor original desta página é Jorge (leia seu post original aqui)
Arquitetura & Fundamentos
O que o Kubernetes faz?
- Permite executar contêiner/es em um mecanismo de contêiner.
- O agendador permite que as missões dos contêineres sejam eficientes.
- Mantém os contêineres ativos.
- Permite comunicações entre contêineres.
- Permite técnicas de implantação.
- Gerencia volumes de informação.
Arquitetura
- Node: sistema operacional com pod ou pods.
- Pod: Envoltório em torno de um contêiner ou múltiplos contêineres. Um pod deve conter apenas uma aplicação (então, geralmente, um pod executa apenas 1 contêiner). O pod é a forma 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, 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, então, se um falhar, o novo substituto (com um IP interno diferente) será acessível exposto no mesmo IP do serviço. 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 executandokubectl get endpoints
- Kubelet: Agente principal do nó. O componente que estabelece a comunicação entre o nó e o kubectl, e só pode executar pods (através 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 apiserver e o nó. A base é um IPtables para nós. Usuários mais experientes podem instalar outros kube-proxies de outros fornecedores.
- Contêiner Sidecar: Contêineres sidecar são os contêineres que devem ser executados junto com o contêiner principal no pod. Este padrão sidecar estende e aprimora a funcionalidade dos contêineres atuais sem alterá-los. Hoje em dia, sabemos que usamos a tecnologia de contêiner para envolver todas as dependências para que a aplicação funcione em qualquer lugar. Um contêiner faz apenas uma coisa e faz isso muito bem.
- Processo mestre:
- Api Server: É a forma como os usuários e os pods se comunicam com o processo mestre. Apenas 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. Note que o agendador não inicia novos pods, ele apenas se comunica com o processo Kubelet em execução dentro do nó, que lançará 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 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 mantém o estado completo dos clusters (cada alteração é registrada aqui). Componentes como o Scheduler ou o Controller manager dependem desses dados para saber quais alterações ocorreram (recursos disponíveis dos nós, número de pods em execução...)
- Cloud controller manager: É o controlador específico para controle de fluxo e aplicações, ou seja: se você tem clusters na AWS ou OpenStack.
Note que, como pode haver vários nós (executando vários pods), também pode haver vários processos mestres, 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, deve 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). Note que este não é o lugar recomendado para salvar credenciais!
- Secret: Este é o lugar para armazenar dados secretos como senhas, chaves de API... codificados em B64. O pod poderá acessar esses dados para usar as credenciais necessárias.
- Deployments: Este é o local 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 iguais replicados), que são executados por meio de implantações. Note que as implantações são para aplicações sem estado. A configuração mínima para uma implantação é o nome e a imagem a ser executada.
- StatefulSet: Este componente é destinado especificamente a aplicações como bancos de dados que precisam acessar o mesmo armazenamento.
- Ingress: Esta é a configuração que é usada para expor a aplicação publicamente com uma URL. Note que isso também pode ser feito usando serviços externos, mas esta é a forma correta de expor a aplicação.
- Se você implementar um Ingress, precisará criar Ingress Controllers. O Ingress Controller é um pod que será o endpoint que receberá as solicitações e verificará e balanceará elas para os serviços. O ingress controller enviará a solicitação com base nas regras de ingress configuradas. Note que as regras de ingress podem apontar para diferentes caminhos ou até mesmo 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 ingress controller a direcionará para o "Default backend". Você pode
describe
o ingress controller para obter o endereço deste parâmetro. minikube addons enable ingress
Infraestrutura PKI - Autoridade Certificadora CA:
- CA é a raiz confiável para todos os certificados dentro do cluster.
- Permite que os componentes se validem mutuamente.
- Todos os certificados do cluster são assinados pela CA.
- O etcd tem seu próprio certificado.
- tipos:
- certificado apiserver.
- certificado kubelet.
- certificado scheduler.
Ações Básicas
Minikube
Minikube pode ser usado para realizar alguns testes rápidos no Kubernetes sem precisar implantar um ambiente Kubernetes completo. Ele executará os processos mestre e nó em uma máquina. O 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
(This will open your browser to access the service exposed port)
$ minikube delete
🔥 Deleting "minikube" in virtualbox ...
💀 Removed all traces of the "minikube" cluster
Noções Básicas do Kubectl
Kubectl
é a ferramenta de linha de comando para clusters kubernetes. Ele se comunica com o servidor Api do processo mestre para realizar ações no kubernetes ou para solicitar dados.
kubectl version #Get client and server version
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
#Access the configuration of the deployment and modify it
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
#Get the logs of the pod for debbugging (the output of the docker container running)
#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
#Deploy from config file
kubectl apply -f deployment.yml
Minikube Dashboard
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: metadados, especificação (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 template 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 é acessível apenas 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
nodePort: 30000
note
Isso é útil para testes, mas para produção você deve ter apenas serviços internos e um Ingress para expor a aplicação.
Exemplo de arquivo de configuração do Ingress
Isso exporá a aplicação em http://dashboard.com
.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress
namespace: kubernetes-dashboard
spec:
rules:
- host: dashboard.com
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 80
Exemplo de arquivo de configuração de segredos
Note como as senhas estão codificadas em B64 (o que não é seguro!)
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
type: Opaque
data:
mongo-root-username: dXNlcm5hbWU=
mongo-root-password: cGFzc3dvcmQ=
Exemplo de ConfigMap
Um ConfigMap é a configuração que é dada aos pods para que eles saibam como localizar e acessar outros serviços. Neste caso, cada pod saberá que o nome mongodb-service
é o endereço de um pod com o qual eles podem se comunicar (este pod estará executando um mongodb):
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service
Então, dentro de uma deployment config, este endereço pode ser especificado da seguinte maneira para que seja carregado dentro do env do pod:
[...]
spec:
[...]
template:
[...]
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_SERVER
valueFrom:
configMapKeyRef:
name: mongodb-configmap
key: database_url
[...]
Exemplo de configuração de volume
Você pode encontrar diferentes exemplos de arquivos de configuração de armazenamento yaml em https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes.
Note que volumes não estão dentro de namespaces
Namespaces
Kubernetes suporta múltiplos clusters virtuais suportados pelo mesmo cluster físico. Esses clusters virtuais são chamados de namespaces. Eles são destinados ao uso em ambientes com muitos usuários espalhados por várias equipes ou projetos. Para clusters com poucos a dezenas de usuários, você não deve precisar criar ou pensar em namespaces. Você só deve começar a usar namespaces para ter um melhor controle e organização de cada parte da aplicação implantada no kubernetes.
Namespaces fornecem um escopo para nomes. Nomes de recursos precisam ser únicos dentro de um namespace, mas não entre namespaces. Namespaces não podem ser aninhados dentro de outros e cada recurso Kubernetes pode estar em um namespace apenas.
Existem 4 namespaces por padrão se você estiver usando minikube:
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-node-lease Active 1d
kube-public Active 1d
kube-system Active 1d
- kube-system: Não é destinado ao uso dos usuários e você não deve tocá-lo. É para processos de master e kubectl.
- kube-public: Dados acessíveis publicamente. Contém um configmap que contém informações do cluster.
- kube-node-lease: Determina a disponibilidade de um nó.
- default: O namespace que o usuário usará para criar recursos.
#Create namespace
kubectl create namespace my-namespace
note
Note que a maioria dos recursos do Kubernetes (por exemplo, pods, serviços, controladores de replicação e outros) estão em alguns namespaces. No entanto, outros recursos, como recursos de namespace e recursos de baixo nível, como nodes e persistentVolumes, não estão em um namespace. Para ver quais recursos do Kubernetes estão e não estão em um namespace:
kubectl api-resources --namespaced=true #Em um namespace
kubectl api-resources --namespaced=false #Não em um namespace
Você pode salvar o namespace para todos os comandos kubectl subsequentes nesse contexto.
kubectl config set-context --current --namespace=<insert-namespace-name-here>
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 <keyword>
Helm também é um mecanismo de template que permite gerar arquivos de configuração com variáveis:
Segredos do Kubernetes
Um Secret é um objeto que contém dados sensíveis como uma senha, um token ou uma chave. Essas informações poderiam ser colocadas em uma especificação de Pod ou em uma imagem. Os usuários podem criar Secrets e o sistema também cria Secrets. O nome de um objeto Secret deve ser um nome de subdomínio DNS válido. Leia aqui a documentação oficial.
Os Secrets podem ser coisas como:
- Chaves de API, SSH.
- Tokens OAuth.
- Credenciais, Senhas (texto simples ou b64 + criptografia).
- Informações ou comentários.
- Código de conexão com banco de dados, strings… .
Existem diferentes tipos de secrets no Kubernetes
Tipo Integrado | Uso |
---|---|
Opaque | dados arbitrários definidos pelo usuário (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 do token de bootstrap |
note
O tipo Opaque é o padrão, o típico par chave-valor definido pelos usuários.
Como os secrets funcionam:
O seguinte arquivo de configuração define um secret chamado mysecret
com 2 pares 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_PASSWOR
. Ele também montará o secret username
dentro de mysecret
no caminho /etc/foo/my-group/my-username
com permissões 0640
.
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 #Wait until the pod secretpod is running
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 certs, chaves e URLs estão localizados no FS. Uma vez que você os obtenha, poderá se conectar ao etcd.
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] 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
Uma vez que você estabeleça a comunicação, você poderá obter os segredos:
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>
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 simples dentro do etcd, a menos que você aplique uma camada de criptografia. O seguinte exemplo é baseado em https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
- identity: {}
Depois disso, você precisa definir a flag --encryption-provider-config
no kube-apiserver
para apontar para a localização do arquivo de configuração criado. Você pode modificar /etc/kubernetes/manifest/kube-apiserver.yaml
e adicionar as seguintes linhas:
containers:
- command:
- kube-apiserver
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>
Role para baixo em volumeMounts:
- mountPath: /etc/kubernetes/etcd
name: etcd
readOnly: true
Role para baixo em volumeMounts até hostPath:
- hostPath:
path: /etc/kubernetes/etcd
type: DirectoryOrCreate
name: etcd
Verificando se os dados estão criptografados
Os dados são criptografados quando escritos no etcd. Após reiniciar seu kube-apiserver
, qualquer segredo recém-criado ou atualizado deve ser criptografado ao ser armazenado. Para verificar, você pode usar o programa de linha de comando etcdctl
para recuperar o conteúdo do seu segredo.
- Crie um novo segredo chamado
secret1
no namespacedefault
:
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
- Usando a linha de comando etcdctl, leia esse segredo do etcd:
ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
onde [...]
deve ser os argumentos adicionais para conectar ao servidor etcd.
- Verifique se o segredo armazenado está prefixado com
k8s:enc:aescbc:v1:
, o que indica que o provedoraescbc
criptografou os dados resultantes. - Verifique se o segredo é corretamente descriptografado quando recuperado via API:
kubectl describe secret secret1 -n default
deve corresponder a mykey: bXlkYXRh
, mydata está codificado, verifique decodificando um segredo para decodificar completamente o segredo.
Como os segredos são criptografados na gravação, realizar uma atualização em um segredo criptografará esse conteúdo:
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
Dicas finais:
- Tente não manter segredos no FS, obtenha-os de outros lugares.
- Confira https://www.vaultproject.io/ para adicionar mais proteção aos seus segredos.
- https://kubernetes.io/docs/concepts/configuration/secret/#risks
- https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm
Referências
kubesectips v1 | sickrov.github.io
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.