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! ✨

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.