José Hisse

Políticas como código com o Kyverno

Gerenciar políticas e garantir que recursos do Kubernetes sigam determinadas regras pré definidas são as principais funções do Kyverno. Com ele podemos definir um conjunto de regras que se aplicarão a deployments, statefulsets, pods ou qualquer outro tipo de recurso. E tudo isso é definido da mesma forma que bem conhecemos quando estamos acostumados com o Kubernetes, através de arquivos yaml.

Pré requisitos

Como este artigo busca explorar de forma prática o funcionamento do Kyverno, precisamos que alguns softwares estejam instalados na máquina. Segue a lista dos que serão usados:

Aplicando uma política simples

Vamos iniciar esta seção criando um cluster kubernetes local. Este cluster será usado ao longo de todo este artigo e será onde executaremos nossos testes. Para isso precisamos ter o kind instalado e executar o seguinte comando no terminal:

kind create cluster --name kyverno

Criando um cluster com o kind

Agora devemos instalar o Kyverno, vamos utilizar o método de instalação via yaml e instalar a versão 1.5.1.

kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/v1.5.1/definitions/release/install.yaml

Vamos aguardar a aplicação estar pronta para seguirmos adiante.

kubectl wait --for=condition=available --timeout=300s deployment kyverno -n kyverno

Até o momento talvez não tenha ficado muito claro a função do Kyverno, por isso vamos definir uma regra simples, aplicar ao cluster e verificar como ele atua nos recursos do cluster.

Imagine que na empresa em que trabalhamos sempre devemos garantir que os recursos de nosso time tenha uma determinada label, ou seja, todos os recursos do nosso namespace devem possuir determinada label. Vamos defini-la por team: my-team-name e todos os nossos pods, services, configmaps e secrets devem ter esta label.

Na página oficial podemos encontrar um conjunto de políticas de exemplo e na maioria das vezes já existe uma que é muito semelhante a sua necessidade. Por isso sempre vale a pena dar uma conferida antes de criar uma política do zero.

A primeira coisa que devemos saber sobre o Kyverno é que ele permite a definição de dois tipos de políticas. Uma é de escopo amplo, que permite a aplicação de determinada regra a todo o cluster, que se chama ClusterPolicy. A outra fica limitada ao namespace que ela está aplicada, ou seja, as regras só serão aplicadas aos recursos daquele namespace em questão, ela é chamada de Policy.

Vamos modificar a política já existente, add label, para que ela adicione a label team nos nossos recursos que estão limitados ao namespace default.

apiVersion: kyverno.io/v1
kind: Policy
metadata:
  name: add-team-label
  namespace: default
spec:
  rules:
    - name: add-labels
      match:
        resources:
          kinds:
            - Pod
      mutate:
        patchStrategicMerge:
          metadata:
            labels:
              team: my-team-name

Vamos salvar o conteúdo acima em um arquivo chamado add-team-label.yaml e em seguida aplicar em nosso cluster recém criado.

kubectl apply -f add-team-label.yaml

Temos que validar a regra aplicada. Vamos criar um pod em nosso cluster e verificar em seguida se a label foi aplicada corretamente.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default
spec:
  containers:
    - name: my-app
      image: k8s.gcr.io/pause:3.2
kubectl apply -f my-pod.yaml

Agora vamos checar se a label team com o valor my-team-name foi aplicada com sucesso em nosso pod. A flag --show-labels mostra as labels dos pods na listagem.

kubectl get pods --show-labels -n default

Pod com a label aplicada pelo Kyverno

Vemos que a label obrigatória foi aplicada com sucesso em nosso recurso.

Acabamos de experimentar um caso de uso do Kyverno e podemos imaginar n outros casos de uso.

Todas essas perguntas acima tem a resposta afirmativa quando estamos utilizando o Kyverno.

Tipos de políticas

Atualmente temos 3 principais comportamentos de políticas no Kyverno. Vamos listar abaixo quais são e qual a função de cada um.

Utilizando o Kyverno CLI

Poderíamos ter validado e testado a política apresentada no começo deste artigo antes de aplicá-la em nosso cluster. Isso é muito útil em processos de CI/CD, onde queremos realizar essas atividades de forma automática.

No Kyverno command line temos três principais comandos, o validate, utilizado para verificar se nossa especificação da política está correta e é válida. O comando apply aplica a política em uma especificação de recurso, como de um pod, por exemplo, e tem como output o recurso modificado. E por último temos o test, que varre o diretório especificado para executar uma série de testes.

Kyverno CLI Validate

Vamos utilizar cada um dos três citados acima na ordem apresentada. O primeiro será o validate e seu uso é bastante simples. Com o arquivo yaml contendo nossa política, vamos executar o seguinte comando:

kyverno validate add-team-label.yaml

A saída esperada desse comando é uma mensagem indicando que nossa política é válida, como esperado.

Política validada pelo Kyverno

Por curiosidade vamos executar um comando para testar uma política inválida. Vamos alterar o campo metadata.labels para metadata.tags, como sabemos não existe o campo metadata.tags nas especificações do kubernetes, portanto nossa política deve ser apontada como inválida.

cat << EOF | kyverno validate -
apiVersion: kyverno.io/v1
kind: Policy
metadata:
  name: add-team-label
  namespace: default
spec:
  rules:
  - name: add-labels
    match:
      resources:
        kinds:
        - Pod
        - Service
        - ConfigMap
        - Secret
    mutate:
      patchStrategicMerge:
        metadata:
          tags:
            team: my-team-name
EOF

Política inválida pelo Kyverno

Como observado na imagem acima, nossa política foi diagnosticada como inválida. O que está correto, já que não existe o campo metadata.tags.

Kyverno CLI Apply

O comando apply, como dito anteriormente, aplica determinada regra a um recurso e tem como output um yaml modificado.

kyverno apply add-team-label.yaml --resource my-pod.yaml

Kyverno CLI Apply

Kyverno CLI Test

Podemos executar testes em nossas políticas. Esses testes se assemelham a testes unitários, vamos defini-los em um arquivo chamado test.yaml e colocá-lo no mesmo diretório dos outros arquivos. O conteúdo deste arquivo será:

name: add-always-pull-policy
policies:
  - always-pull-images.yaml
resources:
  - my-pod.yaml
results:
  - policy: always-pull-images
    rule: always-pull-images
    resource: my-pod
    kind: Pod
    patchedResource: my-pod-patched.yaml
    result: pass

A regra que iremos executar neste teste é a Always Pull Image e a colocaremos no arquivo always-pull-images.yaml.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: always-pull-images
spec:
  rules:
    - name: always-pull-images
      match:
        resources:
          kinds:
            - Pod
      mutate:
        patchStrategicMerge:
          spec:
            containers:
              - (name): '?*'
                imagePullPolicy: Always

Outro arquivo que deve estar em nosso diretório é o que conterá a definição sem a política aplicada my-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default
spec:
  containers:
    - name: my-app
      image: k8s.gcr.io/pause:3.2

Como queremos executar um teste que verifica a aplicação correta de uma política, precisamos ter um arquivo de definição com a política já aplicada ao recurso. Então, vamos criar um arquivo chamado my-pod-patched.yaml onde terá o estado final da definição.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default
spec:
  containers:
    - name: my-app
      image: k8s.gcr.io/pause:3.2
      imagePullPolicy: Always

A estrutura final de diretórios é a seguinte:

.
├── my-pod.yaml
├── my-pod-patched.yaml
├── always-pull-images.yaml
└── test.yaml

Agora basta executar os testes no terminal.

kyverno test .

Kyverno Cli test - Always Pull Policy

Conclusão

Neste artigo exploramos uma função básica do Kyverno, quando alteramos um recurso de forma automática devido a uma regra. Recomendo ao leitor a experimentar outras políticas disponibilizadas no site e observar a consequência que ela causa quando um novo recurso é criado. Exploramos também um pouco mais o cli do Kyverno, muito útil em processos de ci/cd.

De forma geral o Kyverno se mostrou uma ferramenta muito interessante e com um caso de uso muito pertinente quando queremos trabalhar em um cluster kubernetes mais organizado, padronizado e seguro.

Lembrando que todo o artigo teve como referência a página oficial do Kyverno, onde contêm variados exemplos e uma ótima documentação.