Componentes do Kubernetes – CronJobs e Secrets

Logo depois dos volumes, seguimos nos aprofundando nos componentes do Kubernetes! Em primeiro lugar, confesso que ter parado para ler mais sobre defini√ß√Ķes e teoria tem ajudado bastante a organizar o conhecimento dentro da minha cabe√ßa. Ainda tenho muito para ler, mas s√≥ de ter alguns conceitos mais “firmes”, me sinto mais confiante e com mais √Ęnimo para continuar. Venham comigo porque hoje teremos Entendendo Componentes do Kubernetes – CronJobs e Secrets!

Quais componentes essa série de posts vai abordar?

Se você, bem como eu, está fazendo o treinamento Descomplicando Kubernetes: hoje é seu dia de sorte. Saiba que vou tentar colocar aqui no meu blog, nos próximos 3 ou 4 posts, um resumo sobre todos os componentes que são explicados no dia 4 do curso. Dessa forma, meu objetivo é, para cada componente, descrever:

  • Sua defini√ß√£o
  • Exemplos de uso
  • Poss√≠veis comandos relacionados
  • Trecho do respectivo YAML de cria√ß√£o e/ou algum YAML relacionado

No momento em que estou come√ßando a escrever este post, acabei de finalizar os meus estudos deste dia do curso e estou com um pouquinho de medo do simulado final. ūüėÖ Pessoalmente, tenho achado o Kubernetes bem mais dif√≠cil de entender do que o Docker, mas seguimos em frente!

Contudo, se você não está fazendo este curso, deixo aqui os componentes que pretendo abordar:

  • Volumes
  • Cronjobs e Secrets (neste post!)
  • ConfigMaps, InitContainer e Helm
  • RBAC
    • ServiceAccounts
    • ClusterRole
    • ClusterRoleBinding

Ao final dessa s√©rie de posts, pretendo deixar um PDF com todo o conte√ļdo devidamente condensado, e tamb√©m editado de uma forma bem bonitinha, pronto para ser usado para seus estudos de Kubernetes!


CronJobs

Não sei você, mas até hoje eu mexi muito pouco com Linux. Confesso que, às vezes, durante estes cursos da LinuxTips, eu me perco mais por conta de não saber coisas básicas de Linux do que, de fato, com conceitos relacionados à containers. Então, acho que nada melhor do que, antes de explicar o que é um CronJob, explicar o que é um Cron no Linux.

Definição de Cron Job (no Unix)

Um cron job é um comando do Linux usado para agendar tarefas que precisam ocorrer periodicamente. Por exemplo: você precisa que um script seja executado 5 vezes por dia, incluindo quando você não está no trabalho? Então basta configurar um cron job corretamente e ele vai automatizar este processo para você.

A princípio, a maioria dos cron jobs tem três componentes presentes dentro dele:

  1. O script que precisa ser chamado e executado
  2. O comando que vai executar aquele script de forma recorrente
  3. O output da execução desse script, que vai depender bastante do que ele faz quando é chamado
Um homem negro olha para o relógio do escritório e depois para seu próprio relógio

Como escrever um Cron Job (no Unix)

Antes de mais nada, precisamos entender que a funcionalidade Cron roda baseado em comandos específicos que se encontram dentro de uma cron table (cron tab). Cada usuário pode ter um cron file próprio e eles não existem por default: precisam ser criados dentro de um diretório específico, através do comando crontab -e (que também é utilizado para editar um arquivo cron). Não é recomendado abrir o cron file de outra maneira que não o crontab -e, visto que este comando não somente permite a edição do ficheiro, mas também reinicia o cron daemon quando você salva e sai do arquivo, que é quem de fato vai cuidar dos processos que você automatizou.

Para escrevermos e configurarmos a periodicidade da execução de um script, temos que usar a seguinte sintaxe:

# .---------------- minutos (0 - 59)
# |  .------------- horas (0 - 23)
# |  |  .---------- dia do mês (1 - 31)
# |  |  |  .------- mês (1 - 12) OU jan, fev, mar, apr
# |  |  |  |  .---- dia da semana (0 - 6)(Domingo=0 or 7) OU sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * nome-do-usu√°rio comando-a-ser-executado

Definição e utilização de CronJobs no Kubernetes

Em outras palavras, o CronJob do Kubernetes tem a mesma teoria do cron job do Unix, porém aplicado ao cluster: é uma maneira de automatizar processos que precisam ser executados periodicamente; portanto, são escritos da mesma forma que escrevemos no cron file do Unix.

Em s√≠ntese, temos aqui alguns exemplos de processos que pode ser necess√°ria a automatiza√ß√£o: backups dos volumes utilizados pelo cluster, gera√ß√£o de relat√≥rios relativos √† sa√ļde dos pods, envio de notifica√ß√Ķes peri√≥dicas, etc.

Configurando um CronJob

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: giropops-cron
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: giropops-cron
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Bem Vindo ao Descomplicando Kubernetes - LinuxTips VAIIII ;sleep 30
          restartPolicy: OnFailure

‚ö† Lembrete!

Para criar qualquer tipo de componente do Kubernetes a partir de um YAML, basta executar o seguinte comando:

kubectl create -f nome-do-arquivo.yaml

Comandos relacionados

Também conseguimos executar alguns comandos kubeclt relacionados à visualização de CronJobs, bem como deletá-los também:

kubectl get cronjobs
kubectl get cronjob [nome-do-seu-cronjob]
kubectl describe cronjobs.batch [nome-do-seu-cronjob]
kubectl get jobs --watch
kubectl delete cronjob [nome-do-seu-cronjob]

Secrets

Antes de mais nada, quando falamos sobre sistemas e/ou ferramentas dispon√≠veis na internet, tamb√©m √© sempre necess√°rio falar sobre seguran√ßa. Afinal de contas, se voc√™ est√° mexendo com o Kubernetes em um ambiente de produ√ß√£o, provavelmente ele tamb√©m envolve uma aplica√ß√£o grande e com poss√≠veis dados sigilosos. Inclusive, um dos grandes desafios dentro de ambientes containerizados √© a distribui√ß√£o segura de credenciais e secrets necess√°rias para que as aplica√ß√Ķes trabalhem propriamente. Atualmente, o Kubernetes j√° oferece alguns recursos para seguran√ßa da rede, como, por exemplo, controlar quais containers e pods podem se comunicar entre si dentro de uma determinada rede; o orquestrador, do mesmo modo, tamb√©m oferece ferramentas b√°sicas de gerenciamento de secrets, cujo componente √© muito importante para armazenamento de dados sens√≠veis.

Definição

Uma secret, dentro do Kubernetes, √© um componente que cont√©m uma pequena quantidade de dados sens√≠veis, como, por exemplo, tokens de criptografia, chaves de acesso ou at√© mesmo senhas para outras aplica√ß√Ķes. Portanto, usar uma secret significa que voc√™ n√£o vai precisar incluir informa√ß√Ķes confidenciais no c√≥digo da sua aplica√ß√£o.

Visto que as secrets podem ser criadas independentemente dos pods que as utilizam, existe um risco menor dela (e dos dados que ela cont√©m) serem expostos durante o processo de cria√ß√£o, visualiza√ß√£o e edi√ß√£o de um pod. Nesse meio tempo, tamb√©m √© poss√≠vel que tanto o Kubernetes quanto a sua aplica√ß√£o tenham algumas precau√ß√Ķes extras com as secrets criadas.

Assim sendo, existem dois tipos de secrets dentro do Kubernetes: built-in e customized.

Built-in são as secrets que o Kubernetes cria automaticamente e que são plugadas aos containers. Podem ser desabilitadas ou sobrescritas caso seja necessário. Customized, portanto, são as secrets que nós mesmos criamos e definimos quais dados sensíveis armazenaremos ali.

Uma m√£o carimbando um papel com a palavra "Confidential"
Confidencial

Exemplo de uso

Acima de tudo, podemos utilizar as secrets como credenciais digitais, provendo a autentica√ß√£o de uma identidade e autorizando (ou n√£o) acesso privilegiado de contas, aplica√ß√Ķes e servi√ßos. Podemos utiliz√°-las em contextos como:

  • Armazenar tokens de API ou outras aplica√ß√Ķes
  • Chaves SSH
  • Certificados privados de seguran√ßa como TLS e SSL
  • Chaves de encripta√ß√£o
  • Usu√°rios e senha para bancos de dados

Criando e configurando Secrets

Existem duas principais maneiras de criar uma secret. Nos dois casos, √© necess√°rio, posteriormente, associ√°-las √† um pod atrav√©s do seu respectivo arquivo YAML, sendo que, dependendo de como foi a sua cria√ß√£o, √© preciso utilizar um “tipo de v√≠nculo” espec√≠fico.

Caso 1: criando um arquivo com a secret e vinculando-o via volumes

A primeira coisa a se fazer nesse caso é criar um arquivo de texto em uma pasta contendo o valor da nossa secret. Depois disso, vamos efetivamente criar a secret dentro do nosso cluster, através do seguinte comando:

kubectl create secret generic [nome-da-sua-secret] --from-file=[nome-do-seu-arquivo].txt

Quando criamos a nossa secret em um arquivo, √© necess√°rio que a referenciemos dentro do pod utilizando volumes, justamente por ser o recurso do Kubernetes relacionado √† gerenciamento e manipula√ß√£o de informa√ß√Ķes persistentes entre pods e containers.

O YAML de criação de um pod com a utilização da secret vai ficar desta forma:

apiVersion: v1
kind: Pod
metadata:
  name: [nome-do-seu-pod]
  namespace: default
spec:
  containers:
  - image: busybox
    name: busy
    command:
      - sleep
      - "3600"
    volumeMounts:
    - mountPath: [endereco-de-onde-seu-volume-sera-montado]
      name: [nome-do-seu-volume]
  volumes:
  - name: [nome-do-seu-volume]
    secret:
      secretName: [nome-da-sua-secret]

Após a criação do pod (através do kubectl create), podemos verificar das seguintes formas se a secret foi criada e associada corretamente ao componente.

kubectl exec -ti [nome-do-seu-pod] -- ls [endereco-de-onde-seu-volume-sera-montado]
kubectl exec -ti [nome-do-seu-pod] -- cat [endereco-de-onde-seu-volume-sera-montado]/[nome-do-seu-arquivo].txt

O primeiro comando verificar√° se o arquivo est√° corretamente presente no endere√ßo que apontamos; j√° o segundo ir√° printar o conte√ļdo do arquivo.

Caso 2: criando uma secret com vari√°veis de ambiente e vinculando-a no pod

Da mesma forma que criamos uma secret via um arquivo, vamos criar outra via linha de comando; a diferença é que, desta vez, passaremos a chave e o valor da secret diretamente pelo comando, sem ser necessário um arquivo para armazená-los.

kubectl create secret generic [nome-da-sua-secret] --from-literal user=[nome-usuario] --from-literal password=[senha]

Visto que criamos essa secret “diretamente no sistema”, n√£o √© necess√°rio que utilizemos volumes para vincul√°-las √† um pod. Precisamos utilizar uma estrutura diferente, relacionada justamente √† captura de vari√°veis ENV do sistema.

apiVersion: v1
kind: Pod
metadata:
  name: [nome-do-seu-pod]
  namespace: default
spec:
  containers:
  - image: busybox
    name: busy-secret-env
    command:
      - sleep
      - "3600"
    env:
    - name: MEU_USERNAME
      valueFrom:
        secretKeyRef:
          name: [nome-da-sua-secret]
          key: user
    - name: MEU_PASSWORD
      valueFrom:
        secretKeyRef:
          name: [nome-da-sua-secret]
          key: password

Também conseguimos verificar se a nossa secret está devidamente vinculada com o pod que acabamos de criar através do seguinte comando:

kubectl exec [nome-do-seu-pod] -c busy-secret-env -it -- printenv

Este comando n√£o vai verificar especificamente a sua secret, mas sim listar todas as vari√°veis de ambiente que est√£o contidas dentro do container relacionado ao pod que criamos. Se a chave que criamos estiver l√° e o valor estiver correto, sua secret foi vinculada com sucesso ao seu pod.

YAML de uma secret

Deixo aqui também, à título de curiosidade, o YAML de uma secret tal qual está descrito na documentação do Kubernetes:

apiVersion: v1
kind: Secret
metadata:
	name: secret-sa-sample
	annotations:
		kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
	extra: YmFyCg==

Comandos relacionados

Conseguimos executar alguns comandos kubeclt relacionados à visualização de Secrets.

kubectl get secret
kubectl describe secret [nome-da-secret]

√Č interessante notar, contudo, que o comando de describe n√£o vai funcionar de maneira t√£o literal: ele vai sim mostrar dados relacionados √† secret, como o namespace onde foi criada, seu tipo e quais dados est√£o relacionados √† ela, mas n√£o vai mostrar propriamente o valor que marcamos como confidencial.

Uma maneira de conseguirmos acessar esse valor através do Kubernetes, ou seja, sem ser abrindo diretamente o arquivo que foi criamos ou visualizando as variáveis de ambiente do sistema, é através de um dry-run no comando de visualização de secrets e a decodificação do valor da secret. Em suma, para realizar o dry-run, basta executar o seguinte comando:

kubectl get secret [nome-da-sua-secret] -o yaml

Dentro da tag data do arquivo YAML que ser√° disponibilizado, haver√° o conte√ļdo da sua secret, criptografado atrav√©s do Base64. Para descriptografar, basta executar o comando:

echo '[a-chave-que-apareceu-no-YAML]' | base64 --decode

ūüďĖ Links consultados

ūüďē Documenta√ß√£o do Kubernetes – Volumes

ūüďė Reposit√≥rio do treinamento Descomplicando Kubernetes

ūüďó What is Cron Job? – Hivelocity

ūüďô How I use cron in Linux – David Both, opensource.com

ūüďē The Cron Daemon – Richard Layton, A Cloud Guru

ūüďė Kubernetes Security: Best Practices for Kubernetes Secrets Management – John Walsh, conjur.org

ūüďó Protecting Kubernetes Secrets: A Practical Guide – Rani Osnat, blog.aquasec.com


ūüďú Posts mais recentes

ūüõ≥ Entendendo componentes do Kubernetes ‚Äď Volumes

‚ô¶ Um ambiente de desenvolvimento Rails com Docker


ūüíĆ Recadinhos

Gostou do texto? Tem algo a adicionar? Alguma cr√≠tica construtiva? Feedbacks? Sugest√Ķes? Pedidos? Fique √† vontade para me contatar via email (oli.pmatt@gmail.com), Twitter (@oliviamattiazzo), LinkedIn (/oliviamattiazzo) ou pela caixa de coment√°rios aqui embaixo! Vai ser um prazer conversar contigo! ‚ú®